Architecture Decision Records — Index¶
This index lists every ADR in ftl-docs/architecture/decisions/.
An ADR captures one decision that shaped the system: what we chose, why, what we rejected,
and what we're now committed to maintaining. ADRs are append-only. Once accepted, only
status: and superseded-by: may change.
See CHANGE-MANAGEMENT.md at the repo root for the protocol, and _TEMPLATE.md for the
required structure.
All ADRs (newest first)¶
| # | Title | Status | Implementation | Date | Supersedes | Superseded by | Affects spec |
|---|---|---|---|---|---|---|---|
| 0034 | District standings rank by TOTAL member ROI (sum, not average) | accepted | implemented | 2026-06-10 | — | — | leaderboard |
| 0033 | Leaderboard ROI = cumulative per-trade realized ROI; single close-path writer | accepted | implemented | 2026-06-10 | 0014 | — | leaderboard |
| 0032 | Persistent instrument idx + lineup-sourced instrument universe | accepted | implemented | 2026-06-09 | — | — | amm-pricing, event-ingestion |
| 0031 | Event + stat ripple engine (role-weighted, both teams, all event/stat types) | accepted | implemented | 2026-06-09 | — | — | pricing-ripple-engine, amm-pricing, event-ingestion |
| 0030 | Noise engine + trading bot full removal (prices move only from events, stats, trades) | accepted | pending | 2026-06-08 | 0018, 0021 | — | amm-pricing, event-ingestion |
| 0029 | WS broadcast worker pool — Option C, W=16, heartbeat 30s/45s, drop-on-backpressure | accepted | pending | 2026-06-08 | — | — | realtime |
| 0028 | Position-aware 8-knob event propagation (team/opp × GK/DEF/MID/FWD) | accepted | pending | 2026-06-08 | 0019 | — | event-ingestion, amm-pricing |
| 0027 | persistencePct=100 / cooldownSecs=0 locked pricing model (every occurrence counts, no decay) | accepted | pending | 2026-06-08 | 0025 | — | event-ingestion, amm-pricing |
| 0026 | Event Type Registry + Impact Config (unified, registry-driven, hot-reload) | accepted | pending | 2026-06-08 | 0024, 0025 | — | event-ingestion, amm-pricing |
| 0025 | Per-event decay via persistence split (durable vs transient bump) | superseded | in-progress | 2026-06-07 | — | 0026, 0027 | event-ingestion |
| 0024 | Per-event admin config — enable / per-event cap / category | superseded | in-progress | 2026-06-07 | — | 0026 | event-ingestion |
| 0023 | Durable, lossless football-event capture (SP1 reliability layer) | accepted | in-progress | 2026-06-07 | — | — | event-ingestion |
| 0022 | Comprehensive event-bump coverage; key normalisation in EventBump | accepted | implemented | 2026-06-04 | — | — | amm-pricing |
| 0021 | Mean-reverting random-walk noise offset; near-real-time live-match ticks | superseded | implemented | 2026-06-03 | — | 0030 | amm-pricing |
| 0020 | Slippage measured against the published price; idempotency keys released on rejection | accepted | implemented | 2026-06-03 | — | — | amm-pricing, cfd-pricing-and-wallet |
| 0019 | Match-event propagation — team-fallback, opponent drop, durable event_score | superseded | implemented | 2026-06-03 | — | 0028 | amm-pricing, cfd-pricing-and-wallet |
| 0018 | Activity-gated, pattern-based synthetic noise | superseded | implemented | 2026-06-03 | — | 0030 | amm-pricing |
| 0017 | AMM permanent price impact — trades leave a decaying footprint | accepted | implemented | 2026-06-03 | — | — | amm-pricing, cfd-pricing-and-wallet |
| 0016 | Prevent and surface un-closeable zero-price CFD positions | accepted | implemented | 2026-06-03 | — | — | cfd-pricing-and-wallet, amm-pricing |
| 0015 | Durable wallet credit on position close — synchronous absolute PG snapshot | accepted | implemented | 2026-06-03 | — | — | wallet-and-margin |
| 0014 | Leaderboard ROI feed and read repoint — equity-based ROI% via evaluator + close path | superseded | in-progress | 2026-06-03 | — | 0033 | leaderboard |
| 0013 | Minimum hold (anti-flip) — 180 s hold set on OPEN, not post-CLOSE cooldown | accepted | implemented | 2026-06-02 | — | — | cfd-pricing-and-wallet |
| 0013 | Drop the lineupDetailTypes filter on livescores/latest polling |
accepted | implemented | 2026-06-02 | — | — | amm-pricing |
| 0012 | Retire POST /api/trade; CFD as sole trading mechanism | accepted | implemented | 2026-06-01 | — | — | amm-pricing, cfd-pricing-and-wallet |
| 0011 | FT freeze must span both legacy auto-sell and CFD close-out steps | accepted | implemented | 2026-06-01 | — | — | amm-pricing |
| 0010 | Phone number policy — format + uniqueness, no SMS OTP | accepted | implemented | 2026-05-22 | — | — | signup-and-onboarding |
| 0009 | Referral attribution — codify v2 economics + wire per-invite tracking | accepted | implemented | 2026-05-22 | — | — | referrals |
| 0008 | Registration profile policy (single-name, age 18+, pre-login referral validation) | accepted | implemented | 2026-05-22 | — | — | signup-and-onboarding, referrals |
| 0007 | Coming-soon enforced as backend hard gate (not frontend-only) | accepted | implemented | 2026-05-22 | — | — | signup-and-onboarding |
| 0006 | Honest washout via backend tick-replay (online == offline outcome) | accepted | implemented | 2026-05-22 | — | — | amm-pricing, wallet-and-margin |
| 0005 | Close all open CFD positions at current_price at Full Time | accepted | implemented | 2026-05-22 | 0003 | — | amm-pricing |
| 0004 | Adopt CFD-style margin trading model (replace buy-and-hold AMM) | accepted | implemented | 2026-05-22 | 0001 | — | amm-pricing, wallet-and-margin |
| 0003 | FT freeze + drain wait + system-sell at flat price | superseded | implemented | 2026-05-22 | — | 0005 | amm-pricing |
| 0002 | Redis Lua for atomic trade execution (vs Service Bus FIFO) | accepted | implemented | 2026-05-22 | — | — | amm-pricing |
| 0001 | Linear bonding-curve AMM (price = base + k × net_shares_sold) |
superseded | implemented | 2026-05-22 | — | 0004 | amm-pricing |
Implementation column added 2026-05-22 to distinguish decision accepted from code shipped. See ../../PENDING.md for the un-implemented index and ../../CHANGE-MANAGEMENT.md §"Implementation status" for the convention.
Status legend¶
- proposed — drafted, under review, not yet binding.
- accepted — approved and in force as a decision. (See Implementation column for whether the code reflects it yet.)
- superseded — replaced by a later ADR. The
superseded-by:field links forward. - rejected — considered and declined. Kept in the directory as a record so the same proposal isn't re-litigated.
Implementation legend¶
- pending — code change not yet shipped. ADR-as-build-guide. Listed in
PENDING.md. - in-progress — paired code PR is open / merging.
- implemented — code shipped; ADR matches live behavior.
Adding a new ADR¶
- Find the next number:
ls architecture/decisions/ | grep -E '^[0-9]{4}-' | sort | tail -1. - Copy
_TEMPLATE.mdtoNNNN-<kebab-slug>.md. Use a descriptive slug (0004-amm-formula-add-volatility-damper.md, not0004-changes.md). - Fill in every YAML field.
affects-specs:andaffects-code:are required. - If this ADR supersedes an older one: set
supersedes: NNNNhere, AND open the older ADR and set bothstatus: supersededandsuperseded-by: <this number>. - Add a row to the All ADRs table above (newest first).
- Update the affected spec's
decisions:frontmatter list and rewrite the relevant section.
Numbers are never reused. Skipping a number (e.g. for a rejected proposal) is fine — keep the
rejected file in place with status: rejected.