Skip to content
tezvyn:

Async SQLAlchemy 2.0: the mental model that clicks

Source: SQLAlchemy DocsMediumHow cards are made

Async SQLAlchemy 2.0: the mental model that clicks

SQLAlchemy's async layer bridges its synchronous ORM internals to asyncio. Use AsyncSession and AsyncEngine with an async driver, and await database work. Prerequisites: Python asyncio and basic SQLAlchemy ORM; lazy relationships must be loaded explicitly to avoid implicit I/O errors.

Why it exists

SQLAlchemy's ORM, its unit of work, identity map, and relationship loading, was built around synchronous database drivers that block a thread while waiting on the network. As async frameworks like FastAPI became the default for new Python services, a blocking database call inside an async route would freeze the entire event loop for every other concurrent request, not just the one waiting. SQLAlchemy needed an async path without discarding decades of synchronous ORM logic.

The mental model

Think of the async layer as a bridge over the existing engine, not a new engine. Underneath AsyncSession and AsyncEngine, SQLAlchemy still runs its ordinary synchronous code, query construction, identity tracking, the whole unit of work, but it runs that code inside a lightweight greenlet. The greenlet yields control back to the asyncio event loop at the exact moment a real network call reaches the database driver, then resumes when the response arrives. From the outside it looks like a normal coroutine, underneath, the ORM itself never became async.

How it works

You swap in create_async_engine and AsyncSession, and every call that touches the database becomes an await: execute, commit, flush, close. An async driver such as asyncpg or aiosqlite performs the actual socket I/O, and the greenlet bridge is what lets synchronous SQLAlchemy internals cooperate with that without being rewritten. The direct consequence is that implicit I/O outside of an awaited call no longer works: touching a lazily loaded relationship attribute after the session has moved on raises a MissingGreenlet error instead of quietly issuing a query, so relationships that will be accessed later must be loaded eagerly with an option like selectinload at query time.

When it matters

It matters anywhere SQLAlchemy runs inside an async application, since a single blocking synchronous call there stalls every other request sharing that event loop, not just the slow one. The footgun is lazy loading: code that works perfectly with the synchronous ORM, because a touched relationship just triggers a fresh query, breaks under async the moment that same attribute is accessed outside an await, often only under a request pattern your tests never exercised.

A concrete example

A FastAPI endpoint loads an Order, then a response serializer accesses order.customer.name. Under the synchronous ORM this quietly lazy loads the customer row. Under AsyncSession it raises MissingGreenlet unless the original query used select(Order).options(selectinload(Order.customer)) to load the relationship eagerly while still inside the awaited execute call.

Interview question

Which category covers 'Async SQLAlchemy 2.0: the mental model that clicks' most accurately?

  • a.Python & FastAPICorrect
  • b.Cybersecurity
  • c.Frontend
  • d.Databases
Why?

This bite is filed under Python & FastAPI.

Just read this? Test yourself on what you have been reading.

Read the original → docs.sqlalchemy.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles