Production

June 7, 2026 ยท View on GitHub

Prerequisites

Create .deploy.env with the desired NGINX_TAG.

cat <<EOF > .deploy.env
NGINX_TAG=8ca8d5b59b50
EOF

Create the runtime nginx config files.

cp ./nginx/production/runtime/geo.conf.example ./nginx/production/runtime/geo.conf
cp ./nginx/production/runtime/upstream.conf.example ./nginx/production/runtime/upstream.conf

Start the shared production services.

docker compose -f docker-compose.prod.yaml --env-file .deploy.env up -d postgres nginx certbot

Blue/Green deployment

We support blue/green deployments when running decomp.me in production. This allows us to release the majority of our changes with zero downtime.

deploy.py deploys the requested image tag to the inactive slot, waits for the backend and frontend containers to become healthy, smoke-tests the inactive slot from nginx, then reloads nginx to switch traffic.

Standard deployments

python3 deploy.py deploy githash

The old slot is left running after a successful deploy so rollback remains quick.

Rollback

python3 deploy.py rollback

Migrations

Schema-changing deploys may require maintenance time. The migration flow stops both app slots, runs migrations using the new backend image, starts blue, then points nginx at blue.

python3 deploy.py migrate githash

Status

python3 deploy.py status

Health checks

Production backend containers use GET /api/healthz. This verifies Django can connect to the database without doing user-facing work.

Production frontend containers use GET /healthz. This verifies the Next.js server is responding without rendering the homepage.