From Docker Compose to Production: The Deployment Checklist I Follow

Most projects start the same way: a docker-compose.yml that works perfectly on your laptop. Then someone says "let's deploy this" and suddenly you're dealing with SSL certificates, health checks, secrets management, and cost optimization. Here's the checklist I follow.

1. Separate Configuration from Code

Every environment-specific value — database URLs, API keys, feature flags — lives in environment variables, not config files. I use pydantic-settings in Python and $env/dynamic/private in SvelteKit. The same container image runs in dev, staging, and production with different env vars.

2. Health Checks and Graceful Shutdown

Every service gets a /health endpoint. Not just "is the process running" but "can this service actually handle requests" — database connectivity, external API reachability, memory availability. The orchestrator (whether it's Docker Compose, App Platform, or Kubernetes) uses this to route traffic only to healthy instances.

3. Database Migrations as a Deployment Step

Migrations run before the application starts, guarded by a flag (RUN_MIGRATIONS=1). This prevents race conditions when running multiple replicas — only one instance should run migrations. I use Alembic for Python projects with idempotent migrations that are safe to re-run.

4. SSL and Security Headers

In production, every response includes security headers: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin. For Cloudflare deployments, these go in a _headers file. For traditional setups, Caddy or nginx handles them.

5. Connection Pooling for Managed Databases

Serverless databases like Neon close idle connections aggressively. Your connection pool needs pool_pre_ping=True to verify connections before use, and pool_recycle=1800 to refresh connections before the server-side timeout hits. Without this, you'll get intermittent "connection reset" errors that are maddening to debug.

6. Cost Optimization from Day One

Cloud costs compound quickly. My rules: use the smallest instance that passes load testing, start with shared/burstable CPU (most services are idle 95% of the time), and monitor actual resource usage before scaling up. A $12/month Digital Ocean app platform instance runs most small-to-medium services without breaking a sweat.

Production doesn't have to be complicated. It just has to be intentional.