Production readiness: workers, env vars, healthchecks

Running with reload is perfect for local dev, but production wants a different shape: multiple workers so you can use more than one CPU, environment variables for anything secret or deploy-specific, and a healthcheck route the platform can poll to know if you are alive.

terminal
bash
# Dev: one process, live reload on save
uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000

# Production: multiple workers, no reload
uv run uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

# Production with env-driven config
APP_PORT=8000 WORKERS=4 \
  uv run uvicorn main:app --host 0.0.0.0 --port "$APP_PORT" --workers "$WORKERS"

Reload is a dev-only feature. In production you run uvicorn with a fixed number of workers, driven by env vars so the same image runs in every environment.

The golden rule is simple: config that changes between dev, staging, and prod lives in environment variables, not in code. API keys, database URLs, worker counts, log levels. The image stays the same across environments, the env file changes. That is why we load dotenv at the top of main.py: it makes local dev feel the same as a managed platform.

Your /health route is not just for humans. Platforms like Kubernetes, ECS, and Fly poll it to decide whether to route traffic to your container. A good healthcheck returns fast, depends on nothing slow, and returns a non-2xx status when the app is broken. The /bedtime-story/health route we wrote already fits this shape.

Quiz: Quiz

Loading practice…