Contents

Chapter 1

Chapter 1: Getting Started & Project Setup

Production-ready FastAPI boilerplate with async SQLAlchemy, JWT auth, and Docker — ship your API in hours, not weeks.


Overview

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.

Project Structure

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

Key Features

Async-First Architecture

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:

python
# 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 session

JWT Authentication

Full JWT auth with access tokens, refresh tokens, and role-based access control:

python
# 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"}

Requirements

  • Python 3.11+
  • PostgreSQL 15+
  • Redis 7+ (optional, for production rate limiting)

Getting Started

bash
# 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 --reload

The API will be available at http://localhost:8000 with interactive docs at http://localhost:8000/docs.

Chapter 2

Chapter 2: Configuration & Running

This chapter covers every way to configure and run the FastAPI Starter Template, from local development to production deployment.


Configuration via Environment Variables

The application uses Pydantic's BaseSettings to load configuration from environment variables with sensible defaults:

python
# 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:

env
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/app
SECRET_KEY=a8f3b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0
DEBUG=true
RATE_LIMIT_PER_MINUTE=120

The Docker Compose setup includes the app, PostgreSQL, and Redis:

yaml
# 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:

bash
docker compose -f docker/docker-compose.yml up -d

Running Locally (without Docker)

1. Create a virtual environment

bash
python3 -m venv .venv && source .venv/bin/activate

2. Install dependencies

bash
pip install -e ".[dev]"

3. Set up the database

Make sure PostgreSQL is running, then:

bash
createdb app
alembic upgrade head

4. Start the development server

bash
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Verifying It Works

python
# 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())

Production Considerations

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

Chapter 3
🔒 Available in full product

Chapter 3: Architecture & Testing

You’ve reached the end of the free preview

Get the full FastAPI Starter Template and unlock everything.

All Chapters

Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.

Full Tool Suite

Access all interactive tools with complete data, all workload profiles, and the full scenario library.

Source Files

Downloadable source code, configuration files, and working examples from every chapter.

Lifetime Updates

Free updates for life. Every new chapter, tool, and improvement included.

Buy Now — $39 →
📦 Free sample included — download another copy for the full product.
FastAPI Starter Template v1.0.0 — Free Preview