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.
Links¶
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; setSITE_DOMAINinbuildspec-prod.yaml+DJANGO_ALLOWED_HOSTS) - Deploy prod stacks:
network→compute→storage(multi-AZ Aurora min 1 / max 8 ACU + reader; ASG 2–4 × t3.small; Rediscache.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_certinconfig/prod/compute.yaml, redeploycompute(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
prodenvironment 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.dropped (decided 2026-07-06)ANTHROPIC_API_KEY -
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.shwhitelist
Initial Data Population (in order)¶
- Migration flow proven (one-off ECS task runs
migratebefore each rollout) - Prod migrations run (automatic on first prod deploy)
- Create prod superuser (one-off
createsuperuser --noinputtask; rotate the password afterward) - Configure the Wagtail
Siterecord (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/webon 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_FINGERPRINTSinbuildspec-prod.yaml(empty until then → prodassetlinks.jsonis 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.urltohttps://<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.
- Add the prod Android signing fingerprint to
-
Decide + resolve the mobile API framework— DRF + Wagtail (ADR-0004) - Build the read API (DRF function-based views +
drf-spectacularOpenAPI)
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.smallif the web tier is tight - Confirm the CI rollout has spare capacity on prod (2+ hosts →
minHealthyPercent 100keeps 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