News and Updates
SQLAlchemy 2.1.0rc2 Released
September 08, 2026 permalink
A second release candidate for the SQLAlchemy 2.1 series is now available.
Version 2.1.0rc2 is a small release that addresses issues reported against 2.1.0rc1, most notably a series of memory growth fixes. The final 2.1.0 release is anticipated next, barring any new surprises.
This release includes fixes and improvements to SQLite table reflection, an ORM related change which re-targets the __declare_first__() and __declare_last__() hooks to make use of the new RegistryEvents feature, and also adds new visiblity into the Session.binds and AsyncSession.binds collections.
Applications that have not yet tested within the 2.1 series should make sure their requirements are pinned within the 2.0 series, as pip install will begin fetching 2.1 by default once the final release occurs. Upgrades from 2.0.x to 2.1.x should always be tested.
Be sure to check out the What's New in SQLAlchemy 2.1? migration guide, as well as the detailed changelog at Changelog.
SQLAlchemy 2.1.0rc2 by naming convention is a prerelease, so only installs with pip if the --pre flag is included. Links to pypi for SQLAlchemy 2.1.0rc2 are available on the Download Page.
SQLAlchemy 2.1.0rc1 Released
August 31, 2026 permalink
The first release candidate of the SQLAlchemy 2.1 series is now available.
Version 2.1.0rc1 is hoped to be very close to the final 2.1.0 release, which is anticipated within a week or so, barring newly reported issues that would call for additional release candidates. Along with a broad set of bug fixes, this release includes a small number of remaining behavioral and platform changes that were held for the end of the beta cycle.
Highlights of this release include:
- Python 3.11 is now the minimum Python version - Support for Python 3.10 is dropped, in addition to the drop of Python 3.9, 3.8 and 3.7 that took place in 2.1.0b1. Python 3.10 reaches EOL in October of 2026, so dropping support now gives the SQLAlchemy 2.1 series an extra year of space to remain on current Python versions.
- Faster SQL cache key generation - The traversal that produces the cache key for a SQL construct has been moved into the Cython extension modules, with the set of attributes participating in the key, and the handler for each one, now resolved once at class setup time rather than being rediscovered per attribute, per cache key. Benchmarks across a range of Core and ORM statements show cache key generation running approximately 1.5 to 2.2 times faster with the Cython extensions compiled, and 1.05 to 1.2 times faster in a pure Python build, with the generated cache keys themselves unchanged.
- Fewer round trips for MetaData.create_all() - A new reflection method Inspector.has_multi_table() checks for the existence of many tables at once, implemented natively for the PostgreSQL, Oracle and SQL Server dialects and available to third party dialects as well. MetaData.create_all() now makes use of this method, greatly reducing the number of round trips when creating a large schema.
- Deterministic loader options for objects loaded at multiple paths - Fixed a long-standing issue where an object loaded at more than one path within a single query, such as when a chain of joinedload() options leads back to an entity also loaded at the top level, would retain the loader options of whichever path the query happened to see last, varying with the loader strategy in use. As these options are applied to all subsequent lazy loading for that object, an otherwise identical set of options could behave differently. The shallowest path is now favored, which is deterministic.
- Readable stack traces for runtime-generated code - Python source generated at runtime is now compiled against a descriptive filename registered with the linecache module, so that generated functions on a stack trace render with their source rather than as an opaque File "<string>" frame, and tools such as pdb and inspect.getsource() work with them.
- Multiple ON CONFLICT clauses for SQLite - The SQLite insert() construct now accepts more than one on_conflict_do_update() / on_conflict_do_nothing() clause against the same statement, rendering in the order established. Pull request courtesy Diemid Berozkin.
Applications that have not yet tested within the 2.1 series should make sure their requirements are pinned within the 2.0 series, as pip install will begin fetching 2.1 by default once the final release occurs. Upgrades from 2.0.x to 2.1.x should always be tested.
SQLAlchemy 2.1 includes over 150 individual documented changes across all betas and this release candidate, so be sure to check out not just the What's New in SQLAlchemy 2.1? migration guide, but the detailed changelog at Changelog as well.
SQLAlchemy 2.1.0rc1 by naming convention is a prerelease, so only installs with pip if the --pre flag is included. Links to pypi for SQLAlchemy 2.1.0rc1 are available on the Download Page.
SQLAlchemy 2.0.52 Released
August 11, 2026 permalink
SQLAlchemy 2.0.52 is now available.
This is a larger than usual maintenance release with fixes across the ORM, Core, and dialects. Items of note include:
- Python 3.15 support - Python 3.15 is now supported and tested.
- Literal execute processor audit - The test suite now exercises literal execute processors, used when bindparam(..., literal_execute=True) is given, across all datatypes and dialects to ensure string input is either rejected or correctly escaped. Fixes were made to SQL Server Uuid rendering, the PostgreSQL JSONPATH type, and the Float / Numeric family of types.
- ORM UPDATE with synchronize_session="fetch" - Fixed a result column misalignment where rows returned by .returning() could be delivered under incorrect keys, a problem most likely to appear under concurrent workloads.
- Wildcard loader options and pickling - Fixed failures unpickling ORM objects loaded with wildcard-based loader options such as load_only() or raiseload("*"), which could raise KeyError or IndexError when the unpickling process had not yet constructed a matching loader path. This is most likely to be seen with the forkserver multiprocessing start method, which became the default on POSIX platforms as of Python 3.14.
Links to the detailed changelog for 2.0.52 is at Changelog.
SQLAlchemy 2.0.52 is available on the Download Page.
SQLAlchemy 2.1.0b3 Released
June 27, 2026 permalink
The third beta release of the SQLAlchemy 2.1 series is now available.
Release 2.1.0b3 brings a focused set of new features, performance improvements, and bug fixes. With no major regressions reported against 2.1.0b2, we are hoping this release will be the last beta before a final 2.1.0 release, targeting end of summer 2026.
Highlights of this release include:
- ORM Loading Performance Improvements - ORM result row fetching now processes rows as plain tuples rather than constructing Row objects, since ORM loaders use position-based access and do not require the Row interface. Additional optimizations were made to selectinload and subqueryload result handling. Benchmarks show a 3-16% improvement in ORM entity load times depending on query shape. Thanks to Oliver Parker for this work.
- selectinload omit_join for Many-to-Many - The selectinload loader strategy now applies the omit_join optimization automatically for many-to-many non-self-referential relationships, selecting from the secondary (association) table directly rather than joining back to the parent entity, reducing the number of JOINs in the emitted SELECT.
- SQLite JSONB Type - A new JSONB type supports SQLite's binary JSON storage format, available as of SQLite version 3.45.0. Values are stored and retrieved using the jsonb() / json() SQL functions while Python-side behavior remains identical to JSON. Thanks to Shamil Abdulaev.
- selectinload chunksize Parameter - A new chunksize parameter on selectinload allows configuring the number of primary keys sent per IN clause when loading relationships, giving applications control over query size for very large result sets. Thanks to bekapono.
- Delete.using() for Multi-Table DELETE - A new Delete.using() method allows explicit FROM expressions to be rendered in backend-specific multiple-table DELETE forms, including MySQL/MariaDB DELETE .. USING. Thanks to cjc0013.
- SQL Server Bulk Reflection - The SQL Server dialect now implements native multi-table reflection methods, issuing a single bulk query per object type against the sys.* catalog views rather than a per-table round trip loop, matching the pattern already used by the PostgreSQL and Oracle dialects. Thanks to Gaurav Sharma.
- Session execution_options for Unit of Work Core SQL - Session-level execution_options now take effect for Core-level SQL emitted by unit of work operations, in addition to ORM statement executions. This allows options such as schema_translate_map to be applied to a Session globally.
SQLAlchemy 2.1 includes over 90 individual documented changes across all betas, so be sure to check out not just the What's New in SQLAlchemy 2.1? migration guide, but the detailed changelog at Changelog as well.
SQLAlchemy 2.1.0b3 by naming convention is a beta release, so only installs with pip if the --pre flag is included. Links to pypi for SQLAlchemy 2.1.0b3 are available on the Download Page.
SQLAlchemy 2.0.51 Released
June 15, 2026 permalink
SQLAlchemy 2.0.51 is now available.
Links to the detailed changelog for 2.0.51 is at Changelog.
SQLAlchemy 2.0.51 is available on the Download Page.