Skip to content

Configuration

Learn how to configure your FastAPI Boilerplate application for different environments. Configuration is driven by environment variables and validated by Python settings classes.

What You'll Learn

Quick Start

cd backend
cp .env.example .env
$EDITOR .env

Essential variables:

# Application
APP_NAME=My FastAPI App
SECRET_KEY=your-super-secret-key-here

# Database
POSTGRES_USER=your_user
POSTGRES_PASSWORD=your_password
POSTGRES_DB=your_database

# Admin Account (used by setup_initial_data)
ADMIN_NAME=Admin User
ADMIN_EMAIL=admin@example.com
ADMIN_USERNAME=admin
ADMIN_PASSWORD=secure_password

Configuration Architecture

Environment Variables (.env file)
Settings Classes (Pydantic BaseSettings)
Application Code (via get_settings())

Layer 1: Environment Variables

Primary configuration through backend/.env:

POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
CACHE_REDIS_HOST=localhost
SECRET_KEY=your-secret-key

Layer 2: Settings Classes

Pydantic BaseSettings classes in src/infrastructure/config/settings.py validate and structure config:

class DatabaseSettings(BaseSettings):
    POSTGRES_USER: str = config("POSTGRES_USER", default="postgres")
    POSTGRES_PASSWORD: str = config("POSTGRES_PASSWORD", default="postgres")
    POSTGRES_SERVER: str = config("POSTGRES_SERVER", default="localhost")
    POSTGRES_PORT: int = config("POSTGRES_PORT", default=5432)
    POSTGRES_DB: str = config("POSTGRES_DB", default="postgres")

A single composite Settings class combines them all.

Layer 3: Application Use

Pull settings anywhere in the app via get_settings():

from src.infrastructure.config.settings import get_settings

settings = get_settings()
print(settings.DATABASE_URL)

Key Configuration Areas

Application Settings

APP_NAME=Your App Name
VERSION=1.0.0
ENVIRONMENT=development  # development | staging | production | local
DEBUG=false

Database

POSTGRES_USER=your_user
POSTGRES_PASSWORD=your_password
POSTGRES_SERVER=localhost   # use "db" with Docker Compose
POSTGRES_PORT=5432
POSTGRES_DB=your_database
CREATE_TABLES_ON_STARTUP=true

Security & Sessions

SECRET_KEY=your-super-secret-key-here

SESSION_TIMEOUT_MINUTES=30
SESSION_SECURE_COOKIES=true
SESSION_BACKEND=redis
CSRF_ENABLED=true
LOGIN_MAX_ATTEMPTS=5
LOGIN_WINDOW_MINUTES=15

Cache (Redis or Memcached)

CACHE_ENABLED=true
CACHE_BACKEND=redis           # or "memcached"
CACHE_REDIS_HOST=localhost    # use "redis" with Docker Compose
CACHE_REDIS_PORT=6379
CACHE_REDIS_DB=0
DEFAULT_CACHE_EXPIRATION=3600

Background Tasks (Taskiq)

TASKIQ_ENABLED=true
TASKIQ_BROKER_TYPE=redis      # or "rabbitmq"
TASKIQ_REDIS_HOST=localhost   # use "redis" with Docker Compose
TASKIQ_REDIS_PORT=6379
TASKIQ_REDIS_DB=3

Rate Limiting

RATE_LIMITER_ENABLED=true
RATE_LIMITER_BACKEND=redis
RATE_LIMITER_REDIS_HOST=localhost
RATE_LIMITER_REDIS_DB=1
DEFAULT_RATE_LIMIT_LIMIT=100
DEFAULT_RATE_LIMIT_PERIOD=60

Admin User (Initial Setup)

Read by python -m scripts.setup_initial_data on first run:

ADMIN_NAME=Admin User
ADMIN_EMAIL=admin@example.com
ADMIN_USERNAME=admin
ADMIN_PASSWORD=secure_password

Environment-Specific Configurations

Development

ENVIRONMENT=development
DEBUG=true
POSTGRES_SERVER=localhost
CACHE_REDIS_HOST=localhost
TASKIQ_REDIS_HOST=localhost
RATE_LIMITER_REDIS_HOST=localhost

Staging

ENVIRONMENT=staging
DEBUG=false
POSTGRES_SERVER=staging-db.example.com
CACHE_REDIS_HOST=staging-redis.example.com
SESSION_SECURE_COOKIES=true

Production

ENVIRONMENT=production
DEBUG=false
POSTGRES_SERVER=prod-db.example.com
CACHE_REDIS_HOST=prod-redis.example.com
PRODUCTION_SECURITY_VALIDATION_ENABLED=true
PRODUCTION_SECURITY_STRICT_MODE=true
ENABLE_DOCS_IN_PRODUCTION=false

Docker Configuration

Docker Compose loads variables from .env automatically. With Compose, services reach each other by service name:

POSTGRES_SERVER=db
CACHE_REDIS_HOST=redis
RATE_LIMITER_REDIS_HOST=redis
TASKIQ_REDIS_HOST=redis

Service Overview

services:
  web:    # FastAPI application
  db:     # PostgreSQL
  redis:  # Cache, rate limiting, sessions, taskiq broker

To run a Taskiq worker, add a worker service to your Compose file with the command taskiq worker infrastructure.taskiq.worker:default_broker.

Common Configuration Patterns

Feature Toggles

The boilerplate already exposes toggles like CACHE_ENABLED, RATE_LIMITER_ENABLED, TASKIQ_ENABLED, ADMIN_ENABLED, and CSRF_ENABLED. You can add your own in a settings class:

class FeatureSettings(BaseSettings):
    ENABLE_ANALYTICS: bool = config("ENABLE_ANALYTICS", default=False, cast=bool)

Then use it:

from src.infrastructure.config.settings import get_settings

if get_settings().ENABLE_ANALYTICS:
    track_event(...)

Environment Detection

from src.infrastructure.config.settings import EnvironmentOption, get_settings

if get_settings().ENVIRONMENT == EnvironmentOption.PRODUCTION:
    ...

Generate Secret Key

python -c "import secrets; print(secrets.token_urlsafe(64))"

Best Practices

Security

  • Never commit .env to version control
  • Use a unique strong SECRET_KEY per environment
  • Disable debug mode in production
  • Set ENVIRONMENT=production to enable the security validator
  • Restrict CORS_ORIGINS to specific domains

Performance

  • Tune POSTGRES_POOL_SIZE and POSTGRES_MAX_OVERFLOW for your workload
  • Use separate Redis databases for cache (CACHE_REDIS_DB=0), rate limiting (RATE_LIMITER_REDIS_DB=1), and taskiq (TASKIQ_REDIS_DB=3)
  • Set sensible SESSION_TIMEOUT_MINUTES and MAX_SESSIONS_PER_USER

Maintenance

  • Document custom environment variables in .env.example
  • Add validation in settings classes (Pydantic types catch most issues)
  • Test configurations in staging before production

Getting Started

  1. Environment Variables - Complete reference of every variable
  2. Settings Classes - How config is organized in Python
  3. Docker Setup - Compose files and overrides
  4. Environment-Specific - Per-environment best practices

The boilerplate ships with sensible defaults — only override what you need.