Updated Jun 23, 2026

SQLAlchemy From Zero

SQLAlchemy is the database toolkit most serious Python talks to a database through. If you used Flask-SQLAlchemy in Flask From Zero or SQLModel in FastAPI From Zero, you used SQLAlchemy without meeting it - those are thin layers over this. Learning it directly is doubly worth it: it's the most powerful, flexible ORM in the Python world, and understanding it turns those wrappers from magic into "oh, that's SQLAlchemy, configured for me."

The mental model that makes it click is that SQLAlchemy is really two libraries stacked: Core (a Pythonic way to build and run SQL - the foundation) and the ORM (maps Python classes to tables, built on Core). Most app code lives in the ORM, but knowing Core is there - and that you can always drop down to it - is what makes SQLAlchemy feel like a tool you command rather than fight. We build it idea-first the whole way, including the two ideas that govern every ORM: the Session (the unit of work) and how it decides what SQL to send.

📝 This assumes Python (classes, decorators - Python From Zero) and basic databases (tables, keys, joins - What a Database Is). The ORM concepts transfer directly from Hibernate & JPA - this is the Python equivalent. SQLAlchemy needs a real database engine, so examples are shown with their output.

How to read this

Read in order - it builds one schema (authors, books, tags) from a bare engine up to relationships and migrations. Uses modern SQLAlchemy 2.0 style throughout. Phases carry difficulty badges.

The phases

Part 1 - Foundations (🟢 Basic → 🟡)

  1. What SQLAlchemy Is (Core vs ORM) 🟢 - the two-layer design and where it sits under the frameworks.
  2. The Engine & Connecting 🟢 - create_engine, connections, transactions, and running SQL with Core.
  3. Defining Models 🟡 - declarative classes, Mapped/mapped_column, and the table they imply.

Part 2 - The ORM in action (🔴 → 🟡) 4. The Session & Unit of Work 🔴 - the heart: the identity map, flush, and dirty tracking. 5. Querying with select() 🟡 - the modern 2.0 query API: filtering, ordering, and fetching results. 6. Relationships 🔴 - relationship(), foreign keys, one-to-many, many-to-many, back_populates. 7. Loading Strategies & the N+1 Trap 🔴 - lazy vs eager, selectinload/joinedload, and the trap that bites everyone.

Part 3 - Real projects (🟡 → 🟢) 8. Migrations with Alembic 🟡 - versioned schema changes, autogenerate, and why create_all isn't enough. 9. SQLAlchemy in the Real World & Where to Go Next 🟢 - Core vs ORM choices, async SQLAlchemy, and what to build.

After this, Flask-SQLAlchemy and SQLModel read as conveniences over a Session, mapped classes, and select() - the things you now understand directly.


Phase 1: What SQLAlchemy Is (Core vs ORM) →