Architecture Decision Records
What an ADR is here
An Architecture Decision Record captures one significant, hard-to-reverse choice: the context that forced the decision, the decision itself, the consequences we accepted, and the alternatives we rejected. They are the “why” behind the platform. If you are taking over MVS Pay, read these before you change anything load-bearing — most of the surprising shapes in the codebase trace back to one of these eleven records.
The source of truth for each ADR is the markdown under docs/architecture/adrs/ in the repo. The pages linked from this index (./adrs/adr-XXX) are the published copies of those same files. This page is the index and the cross-reference map; the linked pages are verbatim.
Every ADR below was Accepted on 2026-05-28 except where the table says otherwise. Several carry an explicit “revisit when…” trigger — those are not closed decisions, they are decisions with a known expiry condition. The triggers are listed in the Revisit triggers section.
The index
If you only read three, read ADR-007 (the bias that explains why so little is rebuilt MVS-side), ADR-010 (the auth gap you will hit immediately), and ADR-002 (the MoR posture that shapes onboarding and compliance).
How the decisions hang together
ADR-001 is the root: choosing to self-host the open-source Hyperswitch is what makes every downstream decision possible (and necessary). The native-bias principle in ADR-007 is the lens through which most feature work is decided; ADR-011 is the first concrete application of that lens to a feature MVS partly owns.
The grouping by concern:
- Why Hyperswitch at all / how much of it we use: ADR-001, ADR-007, ADR-011. See The Hyperswitch Pivot for the narrative.
- Shape of the extensions service: ADR-006 (separate app), ADR-003 (Hono), ADR-008 (sidecar schema). See Extensions Service.
- Data + infra: ADR-004 (Neon), ADR-005 (Argo CD). See GitOps & Kubernetes and the Data Model.
- Trust + compliance posture: ADR-002 (MoR), ADR-010 (auth). See Authentication & Tenancy.
- Client surface scope: ADR-009 (web-only). See The SDK and Checkout UI Components.
Per-ADR summary
Things these ADRs leave open
This is internal documentation, so the honest version: several ADRs are decisions to defer, not decisions that are done. Treat the items below as known gaps, not finished features.
The following are explicitly deferred or stubbed by the ADRs above. Do not assume they are implemented just because a toggle, column, or webhook exists.
- Per-user auth is not implemented (ADR-010). Everything authenticates with a single shared secret. PHI audit rows are written with
userId: null. The full integration is blocked on the separate mvs-auth plan. See Authentication & Tenancy. - Platform Organization tier is a toggle only (ADR-002).
MerchantExtension.isPlatformOrgMemberexists from Phase 1, but the Platform Organization KYC / sub-merchant onboarding API is deferred until upstream surfaces it stably and product confirms the tier ships. The simple per-tenant connector flow is the only onboarding path live today. - No cross-region database replica (ADR-004). Neon is single-region today; cross-region replication is deferred. DR for the extensions DB rests on PITR, not a hot replica.
- No mobile SDK (ADR-009). Web only. If you are integrating a mobile consumer, that is net-new work governed by a future plan, not an existing wrapper.
- Revenue Recovery is native and flag-gated (ADR-011). The retry engine is Hyperswitch’s, live behind a feature flag. If it under-performs an MVS baseline (the documented revisit threshold is “recovery rate < industry baseline by 5+ points sustained for 30 days”), the implementation can be swapped under the stable SDK contract. The
BillingSubscriptionrecovery columns are written by exactly one writer — the webhook handler atapps/mvs-pay-extensions/src/routes/webhooks-revenue-recovery.ts.
ADR-007’s corollary is procedural: if you find yourself rebuilding a Hyperswitch capability MVS-side, the expectation is that you write a counter-ADR in docs/architecture/adrs/ explaining why upstream can’t carry it, and add a published copy under ./adrs/. The bias is the default, not a hard prohibition.
Revisit triggers
Some ADRs carry an explicit condition under which they should be reopened. Track these — they are the most likely sources of future architecture churn.
Authoring a new ADR
Take the next number
ADRs are sequential. The next record is ADR-012. Numbers are never reused, even if an ADR is superseded.
Write the markdown in the repo
Create docs/architecture/adrs/adr-0NN-short-slug.md. Keep the canonical sections: Status, Context, Decision, Consequences, Alternatives considered. ADR-011 also uses a Rationale section where the decision needs more justification — that is fine for substantial decisions.
Where the ADRs live in the repo
Canonical source: docs/architecture/adrs/adr-001-*.md … adr-011-revenue-recovery.md.
Published copies (rendered in these docs): fern/pages/concepts/adrs/adr-001-*.mdx … adr-011-revenue-recovery.mdx.
Navigation registration: fern/docs.yml, under Core Concepts → Architecture Decision Records.
The published .mdx files are verbatim copies of the source markdown with a Fern frontmatter title added. Keep them in sync — if you edit the source ADR, update the published copy.
Related reading
- Architecture — the system overview these decisions implement.
- The Hyperswitch Pivot — narrative context for ADR-001, ADR-007, ADR-011.
- Extensions Service — the service shaped by ADR-003, ADR-006, ADR-008.
- Authentication & Tenancy — the current state of the gap in ADR-010.
- Revenue Recovery — the feature governed by ADR-011.
- API Reference — the HTTP contract that ADR-003 chose over tRPC.