Skip to main content

Backend deploys (Render Mongo + ECS Postgres)

Drape ships two FastAPI backends from Drape-AI-LLC/Drape-:

CodeHostTrigger
backend/ (Mongo monolith)RenderGitHub Actions deploy hooks (this page)
backend-postgres/ECS Fargate cluster drapeDev: push to develop (backend-postgres/**); prod: workflow_dispatch only (confirm=deploy-prod)

The Postgres path is not Render. Live AWS resources (ALB host rules, ECR drape-backend-postgres, RDS classifications) are on Infrastructure and the AWS system map. The 2026-08-31 cutover record is Production cutover.

The rest of this page is the Mongo / Render pipeline. The rationale for gating that path is ADR-0001. Postgres env split (dev vs prod, no staging) is ADR-0002.

This is a different pipeline from the web tier (Web deploys, AWS Amplify) and the mobile app (EAS).

Postgres on ECS (summary)

EnvServiceTriggerWorkflow / gate
Devdrape-devpush to develop with path filter backend-postgres/**.github/workflows/deploy-dev.yml — AWS auth via OIDC role drape-github-deploy-role
Proddrape-prodworkflow_dispatch onlyrequired confirmation input confirm=deploy-prod
  • Images: ECR drape-backend-postgres (tags prod / dev).
  • Cluster name drape (not drape-prod). Services drape-prod and drape-dev.
  • api.drape.to → ALB host rule → prod TG. dev-api.drape.to and the ALB default action → dev TG.
  • Secrets inject from Secrets Manager (drape/backend/prod-keys, drape/backend/shared-keys) — names only; DATABASE_URL host mapping is docs-supported, not secret-read proven. RDS instance classes stay on the AWS system map: drape-postgres-prod-live ACTIVE PROD (docs-supported); drape-postgres probable ACTIVE DEV (not API-verified); drape-postgres-prod LEGACY CANDIDATE, not approved for deletion.

Mongo on Render — the two GitHub Actions workflows

GitHub · Drape-AI-LLC/Drape-

checks pass

manual + checks pass

push to staging

deploy-staging.yml

manual run on main

deploy-production.yml

staging deploy hook

prod deploy hook

Render: drape-backend-staging

Render: drape-backend

EnvironmentTriggerGateWorkflow
Stagingpush to staging (backend/**)checks pass (auto)deploy-staging.yml
Productionmanual — Actions → Run workflow on mainthe manual trigger + checksdeploy-production.yml

Production is manual because GitHub Environment required-reviewer protection needs GitHub Team/Enterprise for a private repo, which this org isn't on. The manual trigger is the human gate. See ADR-0001 for the rationale and the upgrade path.

Both workflows: install deps → syntax check → critical-import check → validate_env.py (warn-only in CI) → fire the Render deploy hook → poll /api/health until the live commit equals the pushed short SHA (so a green result means the new code is live, not the old instance).

One-time setup

Repo side — already done (Aug 2026): the PROD_BACKEND_URL variable is set, and production is a manual workflow_dispatch workflow (no environment protection needed on the current plan). Nothing else is required in GitHub for production.

Render side — the remaining step (Kenji). Until the deploy-hook secret exists, the deploy job fails fast with a clear "secret not set" message.

  1. Render dashboard → drape-backend → Settings → Deploy Hook → copy the URL.
  2. Repo → Settings → Secrets and variables → Actions → add secret RENDER_DEPLOY_HOOK_URL (paste the hook). (Or, from a machine with gh: gh secret set RENDER_DEPLOY_HOOK_URL --body "<hook-url>".)

For staging CD (later). Create a drape-backend-staging Render service tracking the staging branch with its own database, then add:

TypeNameValue
SecretRENDER_STAGING_DEPLOY_HOOK_URLstaging deploy hook
VariableSTAGING_BACKEND_URLthe staging service URL

Day-to-day flow

  1. Branch from main, make the backend change, open a PR into main. CI (backend-checks.yml, predeploy.yml) runs on the PR.
  2. Apply Supabase migrations first if the change needs them — schema leads code.
  3. Merge to staging to exercise it: deploy-staging.yml auto-deploys on green. Smoke-test against STAGING_BACKEND_URL.
  4. Merge to main. Before deploying, confirm Supabase migrations are applied and backend/scripts/predeploy_check.sh passed locally.
  5. Deploy production: Actions → Deploy Production (manual) → Run workflow → branch main. It runs the checks, fires the deploy hook, and verifies the new commit is live in /api/health. (From CLI: gh workflow run deploy-production.yml --ref main.)

Rollback

Deploys are just the deploy hook pointed at a commit. To roll back:

  1. git revert the bad commit on main (or check out the last good SHA), and push.
  2. Approve the resulting deploy-production.yml run.
  3. The health poll confirms the restored commit is live.

Render's dashboard also offers "Rollback to this deploy" on a prior successful deploy as a faster path in an incident; follow it with the git revert so the repo and the live service don't diverge.

  • Decision & rationale: ADR-0001
  • Local pre-push gate: backend/scripts/predeploy_check.sh, backend/scripts/validate_env.py
  • Health endpoints: /api/health (liveness + commit), /api/health/deep (read/write checks)