# What changed in asgiref

> 14 changes in asgiref 3 from its official release notes, upgrade guides and advisories: 4 breaking, 1 deprecations, 1 new APIs and options. Each one cited. Sources checked 2026-10-28. HTML: https://unstale.sh/pypi/asgiref/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## asgiref 3

### Breaking changes

- Local is now marked @final and raises TypeError if subclassed; subclassing was unsupported and could not work correctly with the specialised implementations. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)
- Support for EOL Python 3.10 has been dropped. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)
- Support for EOL Python 3.9 was dropped. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)
- The tests extra no longer installs mypy. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)

### Deprecations

- asgiref.timeout.timeout is deprecated and will be removed in a future release; use asyncio.timeout() instead. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)

### New APIs and options

- An explicit executor can be provided to nest ThreadSensitiveContext and move thread-sensitive work away from the parent context's shared worker. The executor must run sequentially on a single thread, and the caller manages its lifecycle. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)

### Performance

- Local attribute access is now 2–3x faster because internal specialisations are selected by thread_critical instead of checking the mode on every access. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)

### Tooling

- A separate extra is available for type-checking the codebase. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)

### Fixes and other changes

- Support for Python 3.15 has been added. (3.13.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3130-2026-10-23)
- Restored the previous internal code shape relied on by some APM services; this does not constitute an API stability promise. (3.12.1) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3121-2026-07-14)
- The event loop is resolved when the callable is invoked rather than when AsyncToSync is instantiated, helping avoid deadlocks involving stopped event loops. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)
- Fixed data leaking between unrelated sync threads when thread_inherit_context is enabled, restoring documented thread-local behavior. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)
- Fixed failure on Python 3.14 by using asyncio.run() when no event loop exists. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)
- Fixed an event loop deadlock when exiting ThreadSensitiveContext while its executor thread was still blocked waiting on the event loop. (3.12.0) — [release notes](https://github.com/django/asgiref/blob/03dcd190a363be6e501b2819803e70495200551c/CHANGELOG.txt#3120-2026-07-14)
