Skip to main content
For better performance with I/O-bound database operations, FastAPI supports async database operations using async SQLAlchemy and asyncio.
Async database operations are especially beneficial when:
  • Handling many concurrent requests
  • Working with slow database queries
  • Building high-throughput APIs

Why Async Databases?

Async operations allow your application to handle other requests while waiting for database I/O:
  • Sync: Request waits for database → blocks thread → limited concurrency
  • Async: Request waits for database → thread handles other requests → higher concurrency
If your database operations are fast and your traffic is low, regular sync operations might be simpler and sufficient.

Install Dependencies

Install SQLModel with async support:

Async Database Setup

1

Create an Async Engine

Use create_async_engine instead of create_engine:
Notice the different URL format: sqlite+aiosqlite:// or postgresql+asyncpg:// - the driver must support async operations.
2

Define Models (Same as Sync)

Model definitions remain the same:
3

Create Tables Asynchronously

Use an async function to create tables:
Note the async/await keywords and run_sync() wrapper.

Async Session Dependency

Create an async session dependency for FastAPI:

Using Annotated for Type Hints

expire_on_commit=False prevents SQLAlchemy from expiring objects after commit, which is useful when you want to access them after the transaction.

Async CRUD Operations

All database operations must use async/await syntax.

Create - Async Add Records

Key differences from sync:
  • Function is async def
  • await session.commit()
  • await session.refresh()

Read - Async Queries

Notable changes:
  • Use session.execute() with await
  • Call .scalars().all() to get the results

Get by Primary Key

session.get() becomes await session.get().

Update - Async Modifications

Delete - Async Removal

Complete Async Example

Advanced Async Patterns

Concurrent Queries

Run multiple independent queries in parallel:

Transaction Management

Explicitly manage transactions for complex operations:

Performance Comparison

Async databases aren’t always faster for single requests - they excel at handling many concurrent requests.

Database Connection Pooling

Configure connection pool for production:

Common Pitfalls

Don’t mix sync and async:
  • Don’t call async functions without await
  • Don’t use sync database calls in async endpoints
  • Don’t use async database calls in sync endpoints

Next Steps

  • Explore database migrations with Alembic
  • Learn about SQLModel relationships and joins
  • Implement caching strategies for better performance
  • Set up database connection pooling for production