Learn Python with Talk Python's 270 hours of courses

SQLAlchemy 2.0

Episode #344, published Thu, Dec 9, 2021, recorded Wed, Nov 10, 2021

SQLAlchemy is the most widely used ORM (Object Relational Mapper) for Python developers. It's been around since February 2006. But we might be in for the most significant release since the first one: SQLAlchemy 2.0. This version adds async and await support, new context-manager friendly features everywhere, and even a unified query syntax. Mike Bayer is back to give us a glimpse of what's coming and why Python's database story is getting stronger.

Watch this episode on YouTube
Play on YouTube
Watch the live stream version

Episode Deep Dive

Guest Introduction and Background

Mike Bayer is the original creator and lead developer of SQLAlchemy, the hugely popular Python SQL toolkit and ORM that debuted back in 2006. He has spent years refining SQLAlchemy’s internals to handle the most advanced and diverse database use-cases, drawing on experience with complex data systems in industries like finance, content management, and more. In this episode, Mike shares deep insights into SQLAlchemy 2.0, talks about the philosophies of ORM design, and reflects on the evolution of Python itself.

What to Know If You’re New to Python

Here are a few suggestions to help you better follow along with the topics in this episode:

  • Basic Python syntax and objects: Know how classes, methods, and functions work.
  • Working with virtual environments: Helpful when installing and experimenting with SQLAlchemy and database drivers.
  • Basic database queries: Understanding SQL SELECT, INSERT, and JOIN statements will help clarify how ORMs automate these operations.

Key Points and Takeaways

  1. SQLAlchemy 2.0’s Core Philosophy and History SQLAlchemy has been around since 2006, balancing ease of use with the power to generate complex SQL. Version 2.0 is the biggest update since its first release, modernizing many aspects of the library. Mike Bayer emphasizes that SQLAlchemy doesn't “hide” SQL but rather automates repetitive tasks, letting developers stay close to the database’s real capabilities.
  2. Major 2.0 Changes and the 1.4 Transition Version 1.4 set the stage for 2.0 by introducing new internals and a “future” API. With 2.0, many old and less-documented features are dropped or marked legacy. Developers are encouraged to switch to the modern APIs (e.g., the select() function) for clearer, more explicit code.
  3. Async and Await Support One of the headline features is native support for async/await, which allows efficient non-blocking database I/O. Rather than rewriting the ORM core from scratch, the team wrapped SQLAlchemy’s internals with “greenlet” so async code runs seamlessly, and you can integrate with frameworks like FastAPI.
  4. Unified Query Syntax with select() SQLAlchemy 2.0 encourages users to rely on the explicit select() constructs rather than the older session.query(...) style. Under the hood, both produce similar query structures, but select() leads to cleaner code, better static type checks, and clearer async usage.
  5. Context Managers and Transactions The newer APIs embrace Python context managers (with statements) to handle connections and transactions. Developers can open a transaction with with session.begin(): and, if there’s no exception, it auto-commits at the end; otherwise it rolls back, improving reliability and readability.
  6. Caching and Performance Improvements SQLAlchemy 2.0 introduces a caching layer for query compilation and processing, reducing overhead on repeated statements. This layer means bigger features—like detecting cartesian joins—won’t slow apps down. Longer term, there are plans to incorporate Cython for even more speed gains.
  7. Typing and Pydantic/SQLModel Modern Python uses type hints extensively, and SQLAlchemy is adapting with typed declarations on model fields. Projects like SQLModel and Pydantic leverage these type hints even further for validation and create a Pythonic approach to data models that integrate well with SQLAlchemy.
  8. Unit of Work and Transaction Handling SQLAlchemy’s “Unit of Work” pattern automatically tracks database changes and flushes them in the proper order. This approach frees developers from manually managing insert vs. update order, especially with complex, self-referential data structures.
  9. Python Memory and GC Considerations Large ORM-based queries can trigger Python’s garbage collector. SQLAlchemy tries to eliminate circular references to minimize unnecessary GC cycles. Mike noted they have a test suite specifically to track down excessive GC calls and optimize object lifecycles.
  10. Migration with Alembic Alembic is the official migration tool for SQLAlchemy. It automates generating and applying schema changes but still allows you to review the resulting scripts to handle complex database-specific DDL. Although it’s not as “magical” as certain Django or Rails tools, it’s highly flexible and robust.

Interesting Quotes and Stories

  • On SQLAlchemy’s Philosophy: “We really want you to be in SQL as much as possible, while letting SQLAlchemy automate the boring, repetitive stuff.” — Mike Bayer
  • On the Transition to Async: “The async approach is basically an extra layer—we didn’t rewrite the ORM. We just made sure we can gracefully switch context under the hood.”

Key Definitions and Terms

  • ORM (Object Relational Mapper): A technique for converting data between incompatible systems (objects in Python) and relational databases.
  • Context Manager: A Python structure (using with) that sets up a resource and automatically tears it down.
  • Greenlet: A lightweight coroutine library for Python that powers context switches, used here to wrap blocking operations in async code.
  • Unit of Work: A design pattern that keeps track of everything you do during a business transaction that can affect the database.

Learning Resources

To explore Python and SQLAlchemy further, consider these courses from Talk Python Training.

Overall Takeaway

SQLAlchemy 2.0 represents a major leap forward for Python’s most popular ORM. It brings new levels of clarity and performance, thanks to native async support, a unified query syntax, and improved transaction handling. Yet it continues to fulfill SQLAlchemy’s core mission: Let you remain close to SQL while offloading repetitive tasks. Whether you’re upgrading existing apps or starting fresh, the changes in 2.0 open the door to cleaner, more modern Python database code.

Links from the show

SQLAlchemy: sqlalchemy.org
Mike on Twitter: @zzzeek
Migrating to SQLAlchemy 2.0: sqlalchemy.org
awesome-sqlalchemy: github.com
sqlalchemy-continuum versioning: readthedocs.io
enum support: github.com
alembic: sqlalchemy.org
GeoAlchemy: geoalchemy.org
sqltap profiling: github.com

Michael K.'s ORM GC "problem" example
pythons-gc-and-orms: github.com

nplusone: github.com
Unit of work: duckduckgo.com
ORM + Dataclasses: sqlalchemy.org
SQLModel: sqlmodel.tiangolo.com
Cython example: cython.org
Async SQLAlchemy example: sqlalchemy.org
ORM Usages Stats (see ORM section): jetbrains.com
Watch this episode on YouTube: youtube.com
Episode transcripts: talkpython.fm

--- Stay in touch with us ---
Subscribe to Talk Python on YouTube: youtube.com
Talk Python on Bluesky: @talkpython.fm at bsky.app
Talk Python on Mastodon: talkpython
Michael on Bluesky: @mkennedy.codes at bsky.app
Michael on Mastodon: mkennedy

Talk Python's Mastodon Michael Kennedy's Mastodon