Deployment
Deploying a FastAPI service means running Uvicorn (or Gunicorn with Uvicorn workers) behind a reverse proxy, usually in a container. The shape is the same everywhere: a slim image, a health check, a process supervisor, and TLS terminated at the edge.
Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
docker build -t shop-api:1 .
docker run -d -p 8000:8000 --name shop-api shop-api:1
curl http://127.0.0.1:8000/openapi.json -o /dev/null -w "%{http_code}\n"
Health Check Endpoint
@app.get("/healthz", include_in_schema=False)
def healthz():
return {"status": "ok"}
Orchestrators (Kubernetes, Docker healthcheck) probe /healthz to decide when the container is ready.
Reverse Proxy (Caddy example)
api.example.com {
reverse_proxy localhost:8000
}
Caddy handles TLS automatically. With nginx you add the standard proxy headers (Host, X-Forwarded-For, X-Forwarded-Proto) and long read timeouts for WebSockets.
Process Management
- Small services: one Uvicorn process with 2-4 workers is plenty; workers scale CPU-bound work.
- Async-heavy services: a single worker often handles high concurrency; add workers only if the CPU is the bottleneck.
- Kubernetes: set liveness/readiness probes to /healthz, scale horizontally instead of adding workers.
- Environment: pass configuration via environment variables (pydantic-settings), never hard-code secrets in the image.
Deployment Checklist
- requirements pinned; image built and pushed to a registry.
- Workers and resource limits tuned; /healthz present.
- Reverse proxy terminates TLS and forwards headers; WebSocket upgrades work.
- Logs go to stdout/stderr for the platform's log collector.
- Docs URLs disabled or protected in production.
Summary
Deploy FastAPI as a container running uvicorn with a worker count matched to your workload, expose /healthz for orchestrators, put a TLS-terminating reverse proxy in front, and configure through environment variables. The pattern is identical from a single VM to Kubernetes - only the scaling strategy changes.