FastAPI / Chapter 7 of 8
Deployment and performance
Deploy FastAPI behind a reverse proxy, size worker processes and database pools, and handle timeouts, health checks, and blocking work.
2 topicsUpdated
25 / 28
Production deployment: process, proxy, and database#
Run an ASGI server without reload, put HTTPS at a trusted proxy, use environment-based secrets, migrate schemas during release, and monitor errors and latency.
ShellRun commands and proxy example
# Local development only
fastapi dev app/main.py
# Production: one process per container is a common choice
fastapi run app/main.py --host 0.0.0.0 --port 8000
# Or more processes on a larger machine
fastapi run app/main.py --workers 4 --host 0.0.0.0 --port 8000
# Behind a trusted proxy, configure forwarded headers AND
# restrict which proxy IPs may supply them.
uvicorn app.main:app --host 0.0.0.0 --port 8000 \
--proxy-headers --forwarded-allow-ips '10.0.0.10'
# For a path-prefix proxy, configure root_path as appropriate.
DockerfileMinimal container recipe
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
CMD ["fastapi", "run", "app/main.py", "--host", "0.0.0.0", "--port", "8000"]
# requirements.txt: pin compatible versions of fastapi[standard],
# sqlalchemy, psycopg, pydantic-settings, and auth libraries.
# Run database migrations as a separate release task.
ScaleOne process per container behind a load balancer, or several workers per machine.
DatabasePer-request sessions; size total connection pools across all processes.
ReleaseAlembic migration, readiness checks, graceful termination, rollback plan.
Worker math
Four app workers each with pool_size=5 can keep 20 database connections before overflow. Multiply by containers and background workers; set a deliberate pool budget for PostgreSQL.
26 / 28
Operational safeguards and performance#
Observe request latency, error rates, DB pool waits, and slow SQL. Validate at the edge and application, and keep costly I/O out of request paths when possible.
PythonSimple structured logging hook
import logging
from uuid import uuid4
from fastapi import FastAPI, Request
logger = logging.getLogger("api")
app = FastAPI()
@app.middleware("http")
async def request_id(request: Request, call_next):
rid = request.headers.get("X-Request-ID") or str(uuid4())
response = await call_next(request)
response.headers["X-Request-ID"] = rid
logger.info("request_complete", extra={
"request_id": rid,
"method": request.method,
"path": request.url.path,
"status": response.status_code,
})
return response
ShellAlembic release workflow
alembic init migrations # once
alembic revision --autogenerate -m "add books"
# Review the generated file: autogenerate is not infallible.
alembic upgrade head # separate release job
# Then deploy application version compatible with the schema.
# Prefer additive expand/contract changes for rolling releases.
Performance checklist
Bound pagination and upload sizes; avoid N+1 queries; cache with explicit invalidation where useful; set outbound HTTP timeouts; enforce per-process memory and request limits at the edge. Never log passwords or bearer tokens.
Help improve CodeRef
Allow Google Analytics to measure page visits and use of the guides? It uses cookies after you accept. Your choice won’t affect access to the site. Privacy notice