FastAPI Async SQLAlchemy Project Structure
Fully async FastAPI with SQLAlchemy 2.0 and Alembic migrations. Production-ready database setup.
Project Directory
myproject/
main.py
App factory, lifespan events
app/
Application code
__init__.py
config.py
Pydantic settings
dependencies.py
Shared DI dependencies
core/
Core utilities
__init__.py
database.py
Async engine & session
security.py
JWT, hashing
exceptions.py
Custom HTTP exceptions
models/
SQLAlchemy models
__init__.py
Export all models
base.py
DeclarativeBase, mixins
user.py
item.py
Example domain model
schemas/
Pydantic schemas
__init__.py
user.py
UserCreate, UserRead, etc.
item.py
common.py
Pagination, responses
api/
API routes
__init__.py
deps.py
Route dependencies
v1/
Version 1 endpoints
__init__.py
router.py
Aggregates all routes
users.py
items.py
auth.py
Login, register
services/
Business logic
__init__.py
user_service.py
item_service.py
repositories/
Data access layer
__init__.py
base.py
Generic CRUD repository
user_repository.py
item_repository.py
alembic/
Database migrations
env.py
Async migration config
script.py.mako
versions/
Migration files
.gitkeep
alembic.ini
Alembic configuration
tests/
__init__.py
conftest.py
Fixtures, async test DB
api/
__init__.py
test_users.py
test_items.py
services/
__init__.py
test_user_service.py
requirements.txt
requirements-dev.txt
Test dependencies
.env.example
.gitignore
pyproject.toml
Project metadata, tools config
Why This Structure?
This structure leverages SQLAlchemy 2.0's native async support with a clean layered architecture. Routes → Services → Repositories pattern keeps business logic testable and database access centralized. Alembic handles schema migrations asynchronously.
Key Directories
- app/models/-SQLAlchemy ORM models (database tables)
- app/schemas/-Pydantic schemas (API contracts)
- app/services/-Business logic, orchestrates repositories
- app/repositories/-Database CRUD operations
- app/api/v1/-Versioned API endpoints
- alembic/-Database migration scripts
Getting Started
- python -m venv venv && source venv/bin/activate
- pip install -r requirements.txt -r requirements-dev.txt
- cp .env.example .env (set DATABASE_URL)
- alembic upgrade head
- uvicorn main:app --reload
- Visit /docs for Swagger UI
Async Database Pattern
Use async with AsyncSession as session for all database operations. The database.py file provides get_async_session() as a FastAPI dependency. Never use synchronous Session—SQLAlchemy 2.0 async is fully native, not wrapped.
Layer Responsibilities
- Route-HTTP handling, validation, calls service
- Service-Business logic, calls repository
- Repository-Database queries only
- Model-SQLAlchemy table definition
- Schema-Pydantic request/response shapes
When To Use This
- Production APIs with PostgreSQL/MySQL
- Projects needing database migrations
- Teams wanting clear separation of concerns
- APIs with complex business logic
- Long-lived projects expecting growth
Alembic Commands
# Generate a new migration file
alembic revision --autogenerate -m "Add users table"
# Apply migrations to database
alembic upgrade head
# Rollback last migration
alembic downgrade -1
# View migration history
alembic history
# View current revision
alembic current
# Upgrade to specific revision
alembic upgrade
# Create migration without autogenerate
alembic revision -m "Manual migration"
Testing Strategy
- conftest.py-Async test client, test database fixtures
- tests/api/-Integration tests against endpoints
- tests/services/-Unit tests with mocked repositories
Trade-offs
- More boilerplate-Layers add files but improve maintainability
- Learning curve-SQLAlchemy 2.0 async is different from 1.x
- Complexity-Overkill for < 5 endpoints (use minimal)