How to Use SQLAlchemy with FastAPI: Simple Guide
To use
SQLAlchemy with FastAPI, define your database models with SQLAlchemy ORM, create an async session with AsyncSession, and use dependency injection to access the session in your routes. This setup allows you to perform database operations asynchronously and cleanly within FastAPI endpoints.Syntax
This is the basic pattern to use SQLAlchemy with FastAPI:
- Define your database URL and create an async engine.
- Set up a session maker with
AsyncSession. - Create your ORM models by inheriting from
declarative_base(). - Use FastAPI dependencies to provide a session to your path operations.
python
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker, declarative_base from fastapi import Depends, FastAPI DATABASE_URL = "sqlite+aiosqlite:///./test.db" engine = create_async_engine(DATABASE_URL, echo=True) AsyncSessionLocal = sessionmaker( bind=engine, class_=AsyncSession, expire_on_commit=False ) Base = declarative_base() async def get_session() -> AsyncSession: async with AsyncSessionLocal() as session: yield session app = FastAPI()
Example
This example shows a complete FastAPI app using SQLAlchemy async ORM to create and read users from a SQLite database.
python
from fastapi import FastAPI, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker, declarative_base from sqlalchemy import Column, Integer, String, select DATABASE_URL = "sqlite+aiosqlite:///./test.db" engine = create_async_engine(DATABASE_URL, echo=False) AsyncSessionLocal = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False) Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) async def get_session() -> AsyncSession: async with AsyncSessionLocal() as session: yield session app = FastAPI() @app.on_event("startup") async def startup(): async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) @app.post("/users/") async def create_user(name: str, session: AsyncSession = Depends(get_session)): new_user = User(name=name) session.add(new_user) await session.commit() await session.refresh(new_user) return {"id": new_user.id, "name": new_user.name} @app.get("/users/{user_id}") async def read_user(user_id: int, session: AsyncSession = Depends(get_session)): result = await session.execute(select(User).where(User.id == user_id)) user = result.scalars().first() if user is None: raise HTTPException(status_code=404, detail="User not found") return {"id": user.id, "name": user.name}
Output
POST /users/ with JSON {"name": "Alice"} returns {"id": 1, "name": "Alice"}
GET /users/1 returns {"id": 1, "name": "Alice"}
Common Pitfalls
Common mistakes when using SQLAlchemy with FastAPI include:
- Using synchronous SQLAlchemy sessions instead of async sessions, which blocks the event loop.
- Not using dependency injection for sessions, causing session management issues.
- Forgetting to commit transactions after adding or modifying data.
- Not creating database tables before running queries.
python
## Wrong: Using synchronous session in async route (blocks event loop) # from sqlalchemy.orm import Session # def get_session(): # db = Session(bind=engine) # try: # yield db # finally: # db.close() ## Right: Use AsyncSession with async context from sqlalchemy.ext.asyncio import AsyncSession async def get_session() -> AsyncSession: async with AsyncSessionLocal() as session: yield session
Quick Reference
Tips for using SQLAlchemy with FastAPI:
- Use
create_async_engineandAsyncSessionfor async DB operations. - Define models with
declarative_base(). - Use FastAPI
Dependsto inject sessions into routes. - Always commit and refresh after adding new objects.
- Run
Base.metadata.create_all()on startup to create tables.
Key Takeaways
Use SQLAlchemy's async engine and AsyncSession for non-blocking database access in FastAPI.
Inject database sessions into routes using FastAPI's dependency system for clean session management.
Always commit transactions and refresh objects after adding or updating data.
Create database tables at app startup to avoid runtime errors.
Avoid mixing synchronous SQLAlchemy sessions in async FastAPI routes to prevent blocking.