Skip to content

Production Launch Checklist

Info

Status (2026-07-01): The dev environment is fully live on AWS — all CDK stacks deployed, CI/CD green, HTTPS working, DB + Redis wired, admin reachable. Prod is not deployed (config is staged in .aws/iac/config/prod/ + buildspec-prod.yaml).

Items are split into phases. Phase 1 covers everything needed to go live. Later phases cover handoff / hardening and can follow. Boxes checked below are done at the architecture/dev level; prod-specific execution is unchecked. The full bring-up runbook is deployment.md.

Phase 1: Getting to Production

Infrastructure Setup

The prod bring-up mirrors the dev sequence, which is fully proven end-to-end.

  • IaC authored (AWS CDK) — shared / network / compute / storage, validated on dev
  • CI/CD pipeline built and proven (GitHub Actions → OIDC → CodeBuild → ECR → ECS)
  • CDK bootstrapped + shared (ECR/OIDC) + CodeConnections GitHub credential — account-wide, reused by prod
  • Client production domain confirmed (currently a placeholder cslewis.fueled.engineering; set SITE_DOMAIN in buildspec-prod.yaml + DJANGO_ALLOWED_HOSTS)
  • Deploy prod stacks: networkcomputestorage (multi-AZ Aurora min 1 / max 8 ACU + reader; ASG 2–4 × t3.small; Redis cache.t4g.small)
  • Push seed image, then first real prod deploy via a v*.*.* tag
  • Request prod ACM cert, DNS-validate (validation CNAME DNS-only), set acm_ssl_cert in config/prod/compute.yaml, redeploy compute (adds :443 + 80→443 redirect)
  • Cloudflare (prod): proxied DNS → prod ALB; SSL Full (strict) via a per-hostname Configuration Rule (not the zone default); ALB SG already locked to Cloudflare IPs
  • GitHub prod environment protection rules (required reviewers before a prod deploy)

Application Secrets

Populate the cslewis-app-prod Secrets Manager JSON (created empty by CDK). Generate prod-only values — do not reuse dev.

  • DATABASE_URL — from the prod Aurora writer endpoint + rds-credentials-prod
  • REDIS_URL — prod ElastiCache endpoint
  • DJANGO_SECRET_KEY — freshly generated, prod-only
  • SENTRY_DSN — prod Sentry project/environment (also still pending on dev)
  • AI tagging — via AWS Bedrock (task-role bedrock:InvokeModel, no API key); us-east-2 needs a cross-region inference profile. ANTHROPIC_API_KEY dropped (decided 2026-07-06)
  • ELEVENLABS_API_KEY — audio pre-generation
  • API_KEYS — the /api/ app-gate key (ADR-0005); generate a prod-only value and share it with the mobile client. Required before prod serves /api/ — the gate fails closed (403) with no key configured. (Dev value already set.)
  • FIREBASE_SERVICE_ACCOUNT_KEY — once Firebase auth lands (ADR-0003); add the key to the task-def secrets map + render-task-defs.sh whitelist

Initial Data Population (in order)

  • Migration flow proven (one-off ECS task runs migrate before each rollout)
  • Prod migrations run (automatic on first prod deploy)
  • Create prod superuser (one-off createsuperuser --noinput task; rotate the password afterward)
  • Configure the Wagtail Site record (hostname, root page) for the prod domain
  • Content migration — the biggest risk. No raw content exists yet; the importer + AI-tag drafting + editor QA loop must run and be reviewed before launch (see the content-migration risk assessment). This is the long pole, not infra.

Pre-launch Polish (non-blocking)

  • Rotate the temporary dev superuser password (was passed via a task override → recorded in CloudTrail)
  • Provision Celery worker + beat services (not yet in the stack) for Daily Drop scheduling, AI tagging, ElevenLabs, and Substack sync
  • Real legal copy (privacy policy, terms) — required for App Store review
  • Account-deletion endpoint built + production-tested (App Store mandate) once auth lands
  • Universal Links / App Links (CSL-55) — association files are served by interfaces/web on every env (/.well-known/apple-app-site-association, /.well-known/assetlinks.json, /finishSignIn). To go live in prod:
    • Add the prod Android signing fingerprint to ANDROID_SHA256_FINGERPRINTS in buildspec-prod.yaml (empty until then → prod assetlinks.json is intentionally []; confirm upload cert vs Play App Signing key). iOS AASA works without it.
    • Add the prod universal-link domain to Firebase Auth Authorized domains; set the mobile ActionCodeSettings.url to https://<prod-domain>/finishSignIn.
    • Verify no-redirect + application/json: curl -sSI https://<prod-domain>/.well-known/apple-app-site-association (and .../assetlinks.json); confirm via Apple's CDN + Google Digital Asset Links.
  • Decide + resolve the mobile API framework — DRF + Wagtail (ADR-0004)
  • Build the read API (DRF function-based views + drf-spectacular OpenAPI)

Capacity / Tuning (post-load-test)

  • Run a load test against the dive-deeper and today's-passage endpoints
  • Validate Aurora ACU floor/ceiling (1–8), ASG (2–4), and Redis sizing against results
  • Confirm p95 latency targets; right-size t3.small if the web tier is tight
  • Confirm the CI rollout has spare capacity on prod (2+ hosts → minHealthyPercent 100 keeps at least the desired task count healthy during rollouts; dev fits both tasks on a single t3.medium)

Phase 2: Hardening / Edge (optional, can defer)

Some of this is already in the baseline IaC/app; the rest is prod hardening.

  • Origin lockdown — ALB security group restricted to Cloudflare's published IP ranges (ports 80 + 443)
  • TLS + HSTS — Cloudflare Full (strict) + ALB 80→443 redirect; Django sets HSTS (1y, preload), secure cookies, SECURE_SSL_REDIRECT, nosniff
  • Deploy safety — ECS circuit breaker + auto-rollback; images retained in ECR; data stores RemovalPolicy.RETAIN (+ prod Aurora deletion protection)
  • Authenticated Origin Pulls (mTLS) between Cloudflare and the prod ALB (stronger than IP allow-listing alone)
  • Cloudflare WAF + rate limiting tuned (free-tier baseline today); rate-limit write endpoints (django-ratelimit) once the API exists
  • CDN for the API — deferred per ADR-0001 (Redis at origin is sufficient at MVP scale); revisit when telemetry warrants edge caching. CloudFront already fronts S3 media.
  • Dependency/CVE scanning in CI; review ECR scan-on-push findings
  • No PR CI gate exists yet — add lint/test checks required before merge to main

Phase 3: Repo / Ownership Handoff

Do these together with stakeholders after launch is stable.

  • Repo / ownership transfer to the client (if in scope)
  • Tighten the OIDC trust policy from repo:Fueled/cs-lewis-backend:* to specific environments/branches
  • Branch protection on main + required checks; tighten deploy triggers
  • Cost review against the ~$350/mo estimate; consider a reserved/savings plan
  • Backup/restore drill (Aurora PITR, Redis snapshot) and an on-call/runbook handoff
  • Revisit dev-only conveniences (single instance on t3.medium) so they don't leak into prod expectations