Status: Accepted
Date: 2026-05-06 UTC
Refs: #649, docs/architecture/new-surface-convention.md
Every new Raxx surface was placed on a hosting platform through ad-hoc judgment. The same decision — "does this go on CF Pages or Heroku?" — was made independently for getraxx.com, the console, internal docs, the status page, and the ticketing system. There was no written decision tree, so each surface owner re-derived the answer from scratch.
We need a durable classification so future surfaces default to the right tier
without debate, and so scaffold-new-surface.sh can generate the correct
boilerplate without guessing.
Four tiers, decided by a two-question tree:
Q1: Is the output stateless/static? - Yes → Tier A (Cloudflare Pages)
Q2 (if No): Does it need a persistent VM / self-hosted third-party app? - Yes → Tier C (Lightsail + Terraform) - No → Tier B (Heroku)
A fourth tier A+ applies when Tier A output needs edge persistence (D1/KV) without SSR — this is the CF Worker pattern (status-worker, velvet-worker).
Tier C is closed to new surfaces unless the workload is a third-party app (FreeScout, Infisical) that explicitly requires a VM. New first-party server code goes on Tier B.
scripts/scaffold-new-surface.sh) uses this
classification to generate the correct workflow template and Terraform stub.Single-tier (everything on Heroku): Rejected. Static sites on Heroku incur unnecessary dyno cost and lose automatic preview URLs.
Railway / Render as Tier B alternative: Rejected at this time. Heroku is the current standard; introducing a second PaaS creates operational split. If Heroku cost exceeds threshold, a separate ADR should gate the migration.
Fly.io as Tier C alternative: Fly.io can run containers but cannot match Lightsail's cost/simplicity for the two existing Tier C workloads. Tracked as a future option if a containerised Tier C workload is needed.