Deploying FastAPI to production requires the right configuration for performance, security, and reliability. This guide covers deployment to the most popular cloud platforms.
Pre-Deployment Checklist
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from contextlib import asynccontextmanager
from app.config import settings
@asynccontextmanager
async def lifespan(app: FastAPI):
await engine.connect()
yield
await engine.dispose()
app = FastAPI(
title=settings.APP_NAME,
lifespan=lifespan,
docs_url="/docs" if settings.ENVIRONMENT != "production" else None,
)
app.add_middleware(GZipMiddleware, minimum_size=1000)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)Production Dockerfile
FROM python:3.12-slim as builder
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN adduser --disabled-password appuser
USER appuser
COPY --chown=appuser:appuser . .
EXPOSE 8000
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000"]AWS Deployment
AWS Lambda with Mangum
from fastapi import FastAPI
from mangum import Mangum
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello from Lambda!"}
handler = Mangum(app, lifespan="off")ECS Fargate with CDK
from aws_cdk import aws_ecs_patterns as ecs_patterns
ecs_patterns.ApplicationLoadBalancedFargateService(
self, "FastAPIService",
cluster=cluster,
cpu=512,
memory_limit_mib=1024,
desired_count=2,
task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions(
image=ecs.ContainerImage.from_asset("./"),
container_port=8000,
),
)Google Cloud Run
# Build and deploy
gcloud builds submit --tag gcr.io/PROJECT_ID/fastapi-app
gcloud run deploy fastapi-app \
--image gcr.io/PROJECT_ID/fastapi-app \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--memory 512Mi \
--min-instances 0 \
--max-instances 10Azure Container Apps
az containerapp create \
--name fastapi-app \
--resource-group myResourceGroup \
--environment fastapi-env \
--image myregistry.azurecr.io/fastapi-app:latest \
--target-port 8000 \
--ingress external \
--min-replicas 1 \
--max-replicas 10DigitalOcean App Platform
# .do/app.yaml
name: fastapi-app
services:
- name: api
github:
repo: username/fastapi-app
branch: main
dockerfile_path: Dockerfile
http_port: 8000
instance_count: 2
health_check:
http_path: /healthRailway and Render
Railway
# Simply connect your repo - Railway auto-detects FastAPI
railway upRender
# render.yaml
services:
- type: web
name: fastapi-app
env: docker
healthCheckPath: /health
autoDeploy: trueCI/CD with GitHub Actions
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and Push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ secrets.REGISTRY }}/fastapi-app:${{ github.sha }}Health Check Endpoint
@app.get("/health")
async def health_check():
try:
async with engine.connect() as conn:
await conn.execute("SELECT 1")
return {"status": "healthy"}
except Exception:
return Response(status_code=503)Conclusion
Choose the platform matching your team's expertise. Start with Docker for consistency and automate deployments with CI/CD pipelines.
ForgeAPI templates come with production-ready Dockerfiles and CI/CD configs for all major platforms.
Related Resources: