FastAPI Production Stack
Production FastAPI with Uvicorn, Celery, PostgreSQL, and Redis.
Overview
FastAPI is a modern, high-performance web framework for building APIs with Python 3.7+ that leverages standard Python type hints for automatic API documentation and data validation. Created by Sebastian Ramirez in 2018, FastAPI combines the speed of NodeJS and Go with Python's ease of use, achieving performance comparable to NodeJS thanks to Starlette and Pydantic under the hood. It automatically generates OpenAPI (Swagger) documentation and supports async/await natively, making it ideal for I/O-bound applications that need to handle thousands of concurrent connections.
This production stack combines FastAPI with Uvicorn's ASGI server for async request handling, Celery for distributed task processing, PostgreSQL for ACID-compliant data persistence, Redis for caching and message brokering, and NGINX for reverse proxying and load balancing. The architecture separates concerns effectively: FastAPI handles API requests asynchronously, Celery workers process background jobs like email sending or data processing, PostgreSQL manages complex relational data with full transaction support, Redis provides sub-millisecond caching and serves as Celery's message broker, while NGINX terminates SSL and distributes traffic across multiple FastAPI workers.
This stack is perfect for startups building scalable SaaS platforms, enterprises migrating from Django/Flask to async Python, and teams developing data-intensive applications that need background processing capabilities. The combination delivers production-grade performance with FastAPI's 10,000+ requests per second capability, PostgreSQL's enterprise reliability, and Celery's proven distributed task management, making it suitable for applications ranging from financial APIs to machine learning pipelines that require both real-time responses and heavy background computation.
Key Features
- Automatic OpenAPI/Swagger documentation generation from Python type hints with interactive API testing interface
- Async/await native support with Uvicorn ASGI server for handling 10,000+ concurrent connections
- Celery distributed task queue with Redis broker for background job processing and scheduled tasks
- PostgreSQL with asyncpg driver for non-blocking database operations and ACID transaction support
- Redis-powered caching layer with sub-millisecond response times for frequently accessed data
- NGINX reverse proxy with HTTP/2 support and load balancing across multiple FastAPI workers
- Flower web interface for real-time Celery task monitoring and worker management
- Separate Celery Beat scheduler for cron-like periodic task execution
Common Use Cases
- 1SaaS platforms requiring user authentication, subscription management, and background email/notification processing
- 2Financial APIs handling real-time trading data with async PostgreSQL operations and Redis caching for market data
- 3E-commerce backends processing orders synchronously while handling inventory updates and payment processing asynchronously
- 4Machine learning platforms serving model predictions via FastAPI while training models in background Celery tasks
- 5IoT data collection systems ingesting sensor data through FastAPI endpoints and processing analytics in Celery workers
- 6Content management systems with async file uploads, image processing workflows, and PostgreSQL full-text search
- 7Multi-tenant applications requiring database-per-tenant isolation with Redis session management and background data synchronization
Prerequisites
- Minimum 2GB RAM for PostgreSQL database operations and Celery worker processes
- Docker Engine 20.10+ with Docker Compose V2 for proper async networking and health checks
- Available ports 80, 443 (NGINX), and 5555 (Flower) on the host system
- Understanding of Python async/await patterns and SQLAlchemy async sessions
- Familiarity with Celery task decorators and Redis data structure operations
- SSL certificate files if enabling HTTPS termination in NGINX configuration
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 postgres: 3 image: postgres:15-alpine4 environment: 5 - POSTGRES_USER=fastapi6 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}7 - POSTGRES_DB=fastapi_app8 volumes: 9 - postgres_data:/var/lib/postgresql/data10 networks: 11 - fastapi_net1213 redis: 14 image: redis:7-alpine15 volumes: 16 - redis_data:/data17 networks: 18 - fastapi_net1920 fastapi: 21 build: 22 context: .23 dockerfile: Dockerfile24 command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 425 environment: 26 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app27 - REDIS_URL=redis://redis:6379/028 - SECRET_KEY=${SECRET_KEY}29 depends_on: 30 - postgres31 - redis32 networks: 33 - fastapi_net3435 celery-worker: 36 build: 37 context: .38 dockerfile: Dockerfile39 command: celery -A app.worker worker -l info40 environment: 41 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app42 - REDIS_URL=redis://redis:6379/043 - SECRET_KEY=${SECRET_KEY}44 depends_on: 45 - postgres46 - redis47 networks: 48 - fastapi_net4950 celery-beat: 51 build: 52 context: .53 dockerfile: Dockerfile54 command: celery -A app.worker beat -l info55 environment: 56 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app57 - REDIS_URL=redis://redis:6379/058 - SECRET_KEY=${SECRET_KEY}59 depends_on: 60 - postgres61 - redis62 networks: 63 - fastapi_net6465 nginx: 66 image: nginx:alpine67 ports: 68 - "80:80"69 - "443:443"70 volumes: 71 - ./nginx.conf:/etc/nginx/nginx.conf:ro72 depends_on: 73 - fastapi74 networks: 75 - fastapi_net7677 flower: 78 build: 79 context: .80 dockerfile: Dockerfile81 command: celery -A app.worker flower --port=555582 ports: 83 - "5555:5555"84 environment: 85 - REDIS_URL=redis://redis:6379/086 depends_on: 87 - celery-worker88 networks: 89 - fastapi_net9091volumes: 92 postgres_data: 93 redis_data: 9495networks: 96 fastapi_net: .env Template
.env
1# FastAPI Production2POSTGRES_PASSWORD=secure_postgres_password3SECRET_KEY=your_very_long_secret_key_here45# FastAPI at http://localhost6# API docs at http://localhost/docs7# Flower at http://localhost:5555Usage Notes
- 1FastAPI at http://localhost
- 2Swagger docs at http://localhost/docs
- 3ReDoc at http://localhost/redoc
- 4Flower at http://localhost:5555
- 5Async PostgreSQL with asyncpg
Individual Services(7 services)
Copy individual services to mix and match with your existing compose files.
postgres
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=fastapi
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=fastapi_app
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- fastapi_net
redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
networks:
- fastapi_net
fastapi
fastapi:
build:
context: .
dockerfile: Dockerfile
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
environment:
- DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
depends_on:
- postgres
- redis
networks:
- fastapi_net
celery-worker
celery-worker:
build:
context: .
dockerfile: Dockerfile
command: celery -A app.worker worker -l info
environment:
- DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
depends_on:
- postgres
- redis
networks:
- fastapi_net
celery-beat
celery-beat:
build:
context: .
dockerfile: Dockerfile
command: celery -A app.worker beat -l info
environment:
- DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
depends_on:
- postgres
- redis
networks:
- fastapi_net
nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- fastapi
networks:
- fastapi_net
flower
flower:
build:
context: .
dockerfile: Dockerfile
command: celery -A app.worker flower --port=5555
ports:
- "5555:5555"
environment:
- REDIS_URL=redis://redis:6379/0
depends_on:
- celery-worker
networks:
- fastapi_net
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 postgres:5 image: postgres:15-alpine6 environment:7 - POSTGRES_USER=fastapi8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}9 - POSTGRES_DB=fastapi_app10 volumes:11 - postgres_data:/var/lib/postgresql/data12 networks:13 - fastapi_net1415 redis:16 image: redis:7-alpine17 volumes:18 - redis_data:/data19 networks:20 - fastapi_net2122 fastapi:23 build:24 context: .25 dockerfile: Dockerfile26 command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 427 environment:28 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app29 - REDIS_URL=redis://redis:6379/030 - SECRET_KEY=${SECRET_KEY}31 depends_on:32 - postgres33 - redis34 networks:35 - fastapi_net3637 celery-worker:38 build:39 context: .40 dockerfile: Dockerfile41 command: celery -A app.worker worker -l info42 environment:43 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app44 - REDIS_URL=redis://redis:6379/045 - SECRET_KEY=${SECRET_KEY}46 depends_on:47 - postgres48 - redis49 networks:50 - fastapi_net5152 celery-beat:53 build:54 context: .55 dockerfile: Dockerfile56 command: celery -A app.worker beat -l info57 environment:58 - DATABASE_URL=postgresql+asyncpg://fastapi:${POSTGRES_PASSWORD}@postgres:5432/fastapi_app59 - REDIS_URL=redis://redis:6379/060 - SECRET_KEY=${SECRET_KEY}61 depends_on:62 - postgres63 - redis64 networks:65 - fastapi_net6667 nginx:68 image: nginx:alpine69 ports:70 - "80:80"71 - "443:443"72 volumes:73 - ./nginx.conf:/etc/nginx/nginx.conf:ro74 depends_on:75 - fastapi76 networks:77 - fastapi_net7879 flower:80 build:81 context: .82 dockerfile: Dockerfile83 command: celery -A app.worker flower --port=555584 ports:85 - "5555:5555"86 environment:87 - REDIS_URL=redis://redis:6379/088 depends_on:89 - celery-worker90 networks:91 - fastapi_net9293volumes:94 postgres_data:95 redis_data:9697networks:98 fastapi_net:99EOF100101# 2. Create the .env file102cat > .env << 'EOF'103# FastAPI Production104POSTGRES_PASSWORD=secure_postgres_password105SECRET_KEY=your_very_long_secret_key_here106107# FastAPI at http://localhost108# API docs at http://localhost/docs109# Flower at http://localhost:5555110EOF111112# 3. Start the services113docker compose up -d114115# 4. View logs116docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/fastapi-production/run | bashTroubleshooting
- asyncpg.exceptions.InvalidCatalogNameError: Ensure PostgreSQL container starts before FastAPI by adding health checks or startup delays
- Celery workers not discovering tasks: Verify PYTHONPATH includes app directory and task modules are properly imported in worker.py
- FastAPI 422 validation errors: Check Pydantic model field types match incoming JSON data structure and required fields
- Redis connection refused in Celery: Confirm Redis container is running and REDIS_URL environment variable uses correct host 'redis' not 'localhost',
- NGINX 502 Bad Gateway: FastAPI container may not be ready; add upstream health checks or increase proxy timeouts in nginx.conf
- PostgreSQL connection pool exhaustion: Increase SQLAlchemy pool_size and max_overflow settings or implement connection pooling with pgbouncer
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
fastapiuvicorncelerypostgresqlredisnginx
Tags
#fastapi#python#uvicorn#async#production
Category
Full Web StacksAd Space
Shortcuts: C CopyF FavoriteD Download