Why FastAPI on Kubernetes
FastAPI has become my go-to framework for building production APIs. Combined with Kubernetes, it provides a robust foundation for scalable services.
Project Structure
A typical FastAPI project I work with follows this layout:
app/
├── main.py # FastAPI app entry point
├── api/
│ ├── routes/ # Route handlers
│ └── deps.py # Dependencies (DB sessions, auth)
├── core/
│ ├── config.py # Settings via pydantic-settings
│ └── security.py # JWT / auth utilities
├── models/ # SQLAlchemy models
├── schemas/ # Pydantic request/response schemas
└── services/ # Business logic layerHealth Checks
Every service needs proper health endpoints for Kubernetes liveness and readiness probes:
from fastapi import APIRouter
router = APIRouter()
@router.get("/health/live")
async def liveness():
return {"status": "ok"}
@router.get("/health/ready")
async def readiness():
# Check DB connection, external dependencies
return {"status": "ready"}Pod Template
The Kubernetes pod template includes resource limits, probes, and environment configuration:
spec:
containers:
- name: api
image: registry/api:latest
ports:
- containerPort: 8000
livenessProbe:
httpGet:
path: /health/live
port: 8000
initialDelaySeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8000
initialDelaySeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Lessons Learned
- Always use async database drivers —
asyncpgfor PostgreSQL, notpsycopg2 - Pydantic settings for config — Environment variables validated at startup, not runtime
- Separate business logic from routes — Services layer makes testing straightforward
- Structured logging — JSON logs with correlation IDs for distributed tracing