Asynchronous FastAPI starter that combines SQLAlchemy 2.0, Alembic migrations, and Pydantic v2 schemas to deliver modular CRUD APIs for users and todos while enforcing bearer authentication and emitting structured JSON logs.
- Global HTTP bearer guard (
Authorization: Bearer Nina) backed byHTTPBearerand reusable auth helpers. - Modular domain packages in
src/features/<domain>with alignedmodels,schemas,services, androutesmodules. - SQLAlchemy 2.0 async stack with explicit
async with db.begin()transaction boundaries. - Structlog-powered request middleware that stamps each response with an
X-Request-IDand logs duration, status, and endpoint. - Shared pagination helpers that return a consistent
{items,total,page,page_size}payload. - Health and status probes (
GET /andGET /health) for readiness checks.
- Python 3.11+
- SQLite (default), or any SQLAlchemy-supported database URL for
settings.db_url - Optional: uv for fast dependency management
- Clone the repository
git clone <your-fork-url> fastapi-template cd fastapi-template
- Create a virtual environment
python -m venv .venv source .venv/bin/activate - Install dependencies
Or, if you use
pip install -e . # Install test tooling if you plan to run the suite pip install pytest pytest-asyncio
uv:uv sync
Create .env in the project root (the Settings object in src/settings.py loads it automatically). At minimum set a database URL; SQLite is convenient for local work:
db_url=sqlite+aiosqlite:///./data.db
log_level=DEBUG
cors_allow_origins=http://localhost:3000,http://localhost:5173Comma-separated values are expanded into lists for the CORS settings.
- Apply migrations (run from
src/so Alembic can locateenv.py):cd src alembic upgrade head - Start the API with auto-reload:
fastapi dev
- Authenticate every request with
Authorization: Bearer Nina(including the Swagger “Authorize” dialog) to avoid401responses. - Visit
http://localhost:8000/docsfor the interactive schema orhttp://localhost:8000/redocfor an alternative view.
Logs are JSON-formatted and include request metadata emitted by StructlogRequestMiddleware.
- Create a revision:
cd src alembic revision -m "add new table"
- Apply the latest migration:
alembic upgrade head
Alembic reads the SQLAlchemy URL from settings.db_url, so keep .env in sync with your target database.
GET /– Lightweight status check that logs a debug entry.GET /health– Pings the database; returns500if the connection fails.
POST /users/– Create a user (transactional)GET /users/{user_id}– Retrieve a single userGET /users/– List users with paginationPATCH /users/{user_id}– Partially update a user (transactional)DELETE /users/{user_id}– Remove a user (transactional)
POST /todos/– Create a todo, verifying referenced users exist (transactional)GET /todos/{todo_id}– Retrieve a todoGET /todos/– List todos with paginationGET /todos/with-users– List todos and optionally eager-load related usersPATCH /todos/{todo_id}– Update a todo (transactional)DELETE /todos/{todo_id}– Remove a todo (transactional)
Paginated responses return:
{
"items": [...],
"total": 42,
"page": 1,
"page_size": 20
}Use the page and page_size query parameters (max 100) to control pagination.
Run the async API suite (uses an in-memory SQLite database) after activating your virtual environment:
pytest -v --maxfail=1Fixtures in tests/conftest.py handle app bootstrapping, dependency overrides, and injecting the required bearer token so integration tests mirror real requests.
.
├── AGENTS.md
├── pyproject.toml
├── uv.lock
├── src
│ ├── main.py # FastAPI app & router wiring
│ ├── middleware.py # Structlog request middleware
│ ├── settings.py # Pydantic settings (loads .env)
│ ├── database.py # Async engine, session factory, DeclarativeBase
│ ├── logger.py # Structlog configuration
│ ├── alembic # Migration environment & versions
│ └── features
│ ├── auth # HTTP bearer dependency
│ ├── common # Pagination and shared utilities
│ ├── todos # Todo domain models/routes/services/schemas
│ └── users # User domain models/routes/services/schemas
└── tests
├── conftest.py # Async test fixtures & client factory
├── test_todos.py
└── test_users.py
- Add a new folder under
src/features/<domain>and mirror the existingmodels,schemas,services, androutesstructure. - Import new models in
src/alembic/env.pyso Alembic picks them up, then generate migrations. - Register the router in
src/main.pyto expose endpoints. - Cover new behaviors with tests in
tests/using the provided fixtures. - Wrap multi-operation writes in a shared
async with db.begin()block and passflush=Falseinto services that participate in wider transactions.
fastapi devwatches the project for code changes and reloads automatically.- Structured logs bind request metadata (method, path, status, duration, request id) so collectors can index and search easily.
- Global CORS settings are read from
.env; provide comma-separated lists for origins, headers, or methods when tightening access for different environments.