Historical decision text is preserved. Accepted describes the decision, not deployment of every capability discussed. Consult the Architecture and Infrastructure tabs for the verified running system.
Supersedes or amends: ADR-010
Successors or amendments: ADR-013, ADR-017
Date: 2026-05-20
Status: Superseded by ADR-013 (2026-05-25)
Supersedes: ADR-010 (3-Branch Gitflow)
Deciders: Daniel Meza
Superseded. This ADR's single-env model was reversed by ADR-013, which re-introduces a
stagingenvironment plus an explicit promotion step toproduction. The trunk-based branching philosophy is preserved; only the environment count and deploy trigger change. Read this ADR for the rationale that led to the single-env experiment and the cost/benefit analysis that justified reversing it.
Context and Problem Statement
ADR-010 (May 2026) prescribed a 3-branch Gitflow (feature/* → develop → staging → main) with three Railway environments (develop, staging, production) and a GitHub Actions–driven CI/CD pipeline. That decision was made anticipating a team of 3+ engineers and a need for staged integration testing.
In practice, the project is operated by a single developer (with AI-assisted development via Claude Code skills) and has no test traffic to differentiate environments. The staging environment was provisioned but never used; the develop environment was used briefly but added overhead without measurable benefit. GitHub Actions has not been wired up — every push has to pass through Railway's native GitHub integration regardless. The branch-and-env multiplicity adds operational cost (3× Railway env config, 3× secret sets, branch sync chores, "is staging up to date" mental tax) with no offsetting benefit at the current team size and traffic level.
This ADR re-decides the branch and environment strategy with the current realities in mind.
Decision Drivers
- Team size = 1 (plus AI assistance). Gitflow's value comes from coordinating multiple humans against a shared trunk; a single-developer project gets no benefit from branch handoffs.
- No production traffic yet. Staging's value is catching integration issues before users see them. There are no users.
- No GitHub Actions. The Gitflow pipeline assumed CI-gated merges; that pipeline was never built. Local checks (
pnpm typecheck,pnpm test, manual review) are the de facto CI. - Railway billing is per-environment. Three environments → roughly 3× hosting cost for no incremental value.
- Speed of iteration matters more than safety nets right now. The product is pre-launch; the cost of a broken deploy is "redeploy in 5 minutes," not "broken for paying customers."
- Architecture must remain forward-compatible. When team size or traffic grows, re-introducing
staging(ordevelop) must be a Terraform change, not an application change.
Considered Options
- Keep 3-branch Gitflow (status quo from ADR-010). Continue with
develop+staging+mainand three Railway environments. Cost: ongoing branch sync overhead, 3× Railway env spend, mental tax of "is staging fresh." - Trunk-based with a single
mainbranch and a singleproductionenvironment. Feature work on short-livedfeature/*branches cut frommain; merge tomaintriggers Railway deploy toproduction. Nodevelop, nostaging, no per-branch environment. - 2-branch flow (main + staging). Drop
developbut keepstagingas a final pre-prod check. Slightly lighter than option 1 but still pays the staging cost. - Trunk-based with PR preview environments. Single
mainbranch but Railway PR-preview environments per open PR. Adds Railway preview cost but provides per-PR isolated testing.
Decision Outcome
Option 2: Trunk-based development with a single production environment.
Branch structure
| Branch | Lifetime | Purpose | Deploys to |
|---|---|---|---|
main |
Permanent | The trunk — always deployable | Production (Railway) |
feature/{FEAT-id}-{slug} |
Short-lived (target: < 5 days) | Feature development, cut from main, PR'd back to main |
— (no auto-deploy in v1) |
fix/{description} |
Short-lived | Bug fixes against main |
— |
hotfix/{description} |
Same as fix/* in this model |
Urgent production fix — same flow, no separate ceremony | — |
Promotion path
feature/FEAT-XXX-name ──► main ──► Railway production environment
(PR review + local CI) (auto-deploy via Railway GitHub integration)Cutting and merging
Cutting a feature branch:
git checkout main
git pull origin main
git checkout -b feature/FEAT-XXX-short-slugMerging back:
- Push the feature branch.
- Open a PR to
main. - Run
/code-reviewerlocally (or in conversation) — diffs againstmain. - Run
pnpm lint && pnpm typecheck && pnpm testlocally. - Merge the PR (squash or merge commit — your call).
- Railway's native GitHub integration redeploys
productionfrom the newmaintip.
Environment count
| Environment | Branch | Purpose |
|---|---|---|
production (Railway) |
main |
The only live environment in v1 |
There is no develop Railway environment. There is no staging Railway environment. There are no PR preview environments in v1.
CI/CD in v1: local + Railway native
- No GitHub Actions workflows. No
.github/workflows/*.ymlfiles; no hosted CI runs. - Pre-merge gates are local-only and discipline-based:
pnpm lint && pnpm typecheck && pnpm testbefore pushing/code-reviewerskill diffs againstmainand surfaces issues- PR review (human, even if just self-review)
- Deploy trigger is Railway's native GitHub integration: every push to
mainbuilds and deploys. Seedocs/infrastructure/05-deploying-production.md. - Migration command is the same manual one-liner (
railway run --service api --environment production pnpm --filter @urza/db migrate:up) documented in the deploy guide.
Forward compatibility — re-enabling staging or GitHub Actions
This decision is reversible. The re-enablement path:
- Re-add
staging: uncomment thestagingresources ininfra/terraform/railway/environments.tf, re-create thestagingbranch on GitHub, re-add thestagingdeploy token variable, re-link the Railway service to thestagingbranch in the dashboard. - Re-add GitHub Actions: add
.github/workflows/{ci,deploy,preview}.ymland switch Railway from "auto-deploy on push" to "deploy from CI". The CI structure described in ADR-010 (preserved as historical context) is the playbook. - Re-add
develop: same pattern asstaging.
The decision triggers for re-enablement:
- Team grows to ≥ 3 engineers regularly pushing changes
- Production traffic reaches a level where a 5-minute regression hurts paying customers
- Bank partners require pre-prod validation environments for affiliate integration testing
Positive Consequences
- Lower operational cost. One Railway environment, one branch, one secret set. No "is staging up to date" overhead.
- Faster iteration. Cutting a feature branch and shipping a small change is two PRs of ceremony, not four (no develop → staging → main daisy chain).
- Aligned with team size. Single developer + AI assist doesn't benefit from inter-environment handoffs.
- Cheaper to run. Roughly 1/3 the Railway hosting cost vs. three envs.
- Simpler mental model. Newcomers (human or AI) see one branch and one env — no surprise mismatches.
Negative Consequences / Trade-offs
- Production gets every merge. A broken merge is a broken production deploy. Mitigation: small PRs, local CI checks, code-reviewer skill, Railway's instant-rollback (last 5 deployments are one-click revert).
- No staging integration testing. Bank affiliate integration that needs a non-prod environment will require either local dev or re-enabling
staging. Mitigation: track this as a re-enablement trigger; flag in onboarding-future-bank-integrations docs. - No PR preview environments. Visual / design review happens against local dev, not a deployed PR URL. Mitigation: acceptable while the design audience is one person; revisit when design review gets multi-stakeholder.
- No environment-scoped secrets in GitHub. Since there's only one env, secret scoping is moot. Re-introducing multiple envs means re-introducing GitHub-environment-scoped secrets (Terraform commented blocks make this a one-config change).
Pros and Cons of the Options
| Option | Iteration Speed | Safety net | Cost | Fits team-of-1 |
|---|---|---|---|---|
| 1. Keep 3-branch Gitflow | Low | High (in theory) | High | No |
| 2. Trunk + single env (chosen) | High | Low (mitigated by small PRs + local CI) | Low | Yes |
| 3. 2-branch (main + staging) | Medium | Medium | Medium | Marginal |
| 4. Trunk + PR previews | Medium-high | Medium-high | Medium-high | Marginal |
Option 4 was attractive but adds the cost of preview infra that the single-developer review loop doesn't need today. Worth revisiting when team grows.
Migration from ADR-010
Concrete changes accompanying this ADR (all on the same PR):
CLAUDE.md: branch model section rewritten; SDLC workflow updated.docs/architecture/Architecture reference: §10.1 Railway layout reduced to single env; §10.3 deployment strategy rewritten; §10.4 secrets table updated.docs/archive/legacy-sdlc/handbooks/sdlc-handbook.md: stages 5 and 6 collapsed to a single "merge to main" stage.docs/infrastructure/:05-deploying-develop.mdrenamed to05-deploying-production.mdand rewritten formain → production; README table updated; multi-env references in 02/03/04 trimmed..claude/skills/feature-implementor/SKILL.md: cuts feature branch frommainnotdevelop..claude/skills/code-reviewer/SKILL.md: diffs againstmainnotdevelop.infra/terraform/railway/environments.tf:developandstagingresources removed.infra/terraform/github/branches.tf:developandstagingbranch resources removed.infra/terraform/variables.tf:railway_deploy_token_developandrailway_deploy_token_stagingvariables removed.docs/archive/legacy-sdlc/plan/features/FEAT-000-sdlc-foundation/: phase docs updated to reflect the new model.
After this PR merges:
- Delete the
developandstagingbranches on the GitHub remote (manualgit push origin --delete develop staging). - Delete the
developandstagingRailway environments via the Railway dashboard. - Connect the
webandapiRailway services in theproductionenvironment to themainbranch (Source → Branch → main). - Re-run the migration command targeting
production.
References
- ADR-010 — the superseded 3-branch Gitflow decision
- Architecture reference §10 — current infra layout
- docs/archive/legacy-sdlc/handbooks/sdlc-handbook.md — operational SDLC guide
- docs/infrastructure/05-deploying-production.md — the deploy walkthrough this ADR aligns with
- Martin Fowler, "Trunk-Based Development" — https://martinfowler.com/articles/trunk-based-development.html