Production-ready FastAPI boilerplate with async SQLAlchemy, JWT auth, and Docker — ship your API in hours, not weeks.
This template gives you a fully functional async FastAPI application with user authentication, database integration, rate limiting, and a scalable project structure. Everything is wired together with dependency injection, making it easy to extend with your own business logic.
fastapi-starter-template/
├── app/
│ ├── main.py # FastAPI app entry point
│ ├── config.py # Pydantic settings from env vars
│ ├── models/
│ │ ├── base.py # SQLAlchemy Base + mixins
│ │ └── user.py # User model
│ ├── schemas/
│ │ └── user.py # Pydantic request/response schemas
│ ├── api/
│ │ ├── deps.py # Shared dependencies
│ │ └── v1/
│ │ ├── auth.py # Auth routes (register/login/refresh)
│ │ └── users.py # User CRUD routes
│ ├── core/
│ │ ├── security.py # JWT + password hashing
│ │ └── database.py # Async engine + session
│ └── middleware/
│ └── rate_limit.py # Rate limiting middleware
├── tests/
│ ├── conftest.py # Test fixtures
│ └── test_auth.py # Auth endpoint tests
├── docker/
│ ├── Dockerfile # Multi-stage build
│ └── docker-compose.yml # Full stack
├── alembic/
│ └── env.py # Async migration env
└── pyproject.toml # Project configuration
Everything runs on async I/O — SQLAlchemy 2.0 async engine, async session middleware, and async route handlers. This means your API can handle hundreds of concurrent connections without blocking:
# app/core/database.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost:5432/db",
echo=True,
pool_size=10,
max_overflow=20,
)
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield sessionFull JWT auth with access tokens, refresh tokens, and role-based access control:
# Example: using the auth endpoints
import httpx
async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
# Register a new user
resp = await client.post("/api/v1/auth/register", json={
"email": "dev@example.com",
"password": "supersecret123"
})
print(resp.json())
# {"id": 1, "email": "dev@example.com", "is_active": true}
# Login to get tokens
resp = await client.post("/api/v1/auth/login", json={
"email": "dev@example.com",
"password": "supersecret123"
})
tokens = resp.json()
# {"access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer"}# Clone and enter the project
git clone <repo-url> && cd fastapi-starter-template
# Copy environment variables
cp .env.example .env
# Edit .env with your database credentials
# Run with Docker (recommended)
docker compose -f docker/docker-compose.yml up -d
# Or run locally
pip install -e ".[dev]"
alembic upgrade head
uvicorn app.main:app --reloadThe API will be available at http://localhost:8000 with interactive docs at http://localhost:8000/docs.
This chapter covers every way to configure and run the FastAPI Starter Template, from local development to production deployment.
The application uses Pydantic's BaseSettings to load configuration from environment variables with sensible defaults:
# app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "FastAPI Starter"
debug: bool = False
database_url: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/app"
redis_url: str = "redis://localhost:6379/0"
secret_key: str = "change-me-in-production"
access_token_expire_minutes: int = 30
refresh_token_expire_minutes: int = 10080 # 7 days
allowed_hosts: list[str] = ["*"]
cors_origins: list[str] = ["http://localhost:3000"]
rate_limit_per_minute: int = 60
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
settings = Settings()Create a .env file in the project root:
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/app
SECRET_KEY=a8f3b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0
DEBUG=true
RATE_LIMIT_PER_MINUTE=120The Docker Compose setup includes the app, PostgreSQL, and Redis:
# docker/docker-compose.yml
version: "3.8"
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/app
- REDIS_URL=redis://redis:6379/0
depends_on:
- db
- redis
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
pgdata:Start everything with one command:
docker compose -f docker/docker-compose.yml up -dpython3 -m venv .venv && source .venv/bin/activatepip install -e ".[dev]"Make sure PostgreSQL is running, then:
createdb app
alembic upgrade headuvicorn app.main:app --reload --host 0.0.0.0 --port 8000# test_api.py
import httpx
import asyncio
async def verify():
async with httpx.AsyncClient(base_url="http://localhost:8000") as c:
# Health check
r = await c.get("/health")
assert r.status_code == 200
print("Health check:", r.json())
# Register
r = await c.post("/api/v1/auth/register", json={
"email": "test@example.com",
"password": "StrongPass1!"
})
assert r.status_code == 201
print("Registered:", r.json())
# Login
r = await c.post("/api/v1/auth/login", json={
"email": "test@example.com",
"password": "StrongPass1!"
})
token = r.json()["access_token"]
print("Got access token")
# Access protected route
r = await c.get("/api/v1/auth/me", headers={
"Authorization": f"Bearer {token}"
})
assert r.status_code == 200
print("My profile:", r.json())
asyncio.run(verify())Before deploying to production:
1. Change SECRET_KEY to a cryptographically secure random value
2. Set DEBUG=false
3. Configure ALLOWED_HOSTS and CORS_ORIGINS for your domain
4. Switch Redis-based rate limiting (in-memory is for development only)
5. Use a managed PostgreSQL instance (RDS, Cloud SQL, etc.)
6. Set up a reverse proxy (NGINX, Caddy) with SSL termination
Get the full FastAPI Starter Template and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.