Skip to content

ADR-0002: Never queue the decision; fast retryable decline; stand-in built but off

Status: Accepted · Date: 2026-10-19

Context

The caller is a person at a till with a ~3 s timeout. A queue in front of the decision silently turns a synchronous approve/decline into an asynchronous one. The till cannot poll or receive webhooks, and the customer walks away. Card networks have handled "authoriser unreachable" for decades: either decline, or approve below a floor limit (stand-in) and accept bounded risk. A queue is not a third option. It is a decline with worse ergonomics.

Decision

  • When the wallet is unavailable (breaker open, bulkhead full, 503, refused), respond 201 DECLINED WALLET_UNAVAILABLE, retryable=true, Retry-After within milliseconds.
  • Implement the degradation policy as a separate table-driven component. Tier 0 (stand-in under a floor limit with exposure caps) is built and tested but disabled (stand-in.enabled=false, floor 0).
  • Queue only follow-ups that nobody waits for: capture, release, compensating credit, resolution of unknown outcomes.
  • Report technical declines as 201 plus a decision body, not as 5xx. The till gets one uniform shape, and 503 is reserved for "Transaction Service itself cannot accept work".

Consequences

  • + Honest, fast, measurable. An outage shows up as a spike in WALLET_UNAVAILABLE declines, not as hung tills.
  • − Lost sales during wallet outages, until the business opts into stand-in.
  • Enabling stand-in later requires: floor limit > 0, per-account and global exposure caps, a kill switch, reconciliation of every stand-in decision, and a business owner (OQ-3). Because of legacy debiters (C2) we cannot estimate balances conservatively, so every stand-in approval is real credit risk.