TSTier SlateAll templates

Payments & ledgers

Currency exchange - a rate that is only true for a few seconds

Why a quoted FX rate is a short-lived promise with an expiry, and how rounding is a ledger decision.

  • System design
  • core
  • 8 step walkthrough
  • 5 tables

Share

  • Facebook
  • X

What this board gets wrong on purpose

The tension

EVERY QUOTE IS A FREE 30-SECOND OPTION, AND THE BOARD ONLY PRICES IT FOR A CALM MARKET. The customer sees a frozen rate and may execute at any point before expiry - so a customer who watches the market can request a quote, wait, and accept only if the mid has moved against the house. The 35 bp spread covers that comfortably on a normal day: EUR/USD moves about 1 bp in 30 seconds, one thirty-fifth of the margin. It does not cover a gap. When a central bank surprises the market a pair can move 2% in under a second (EUR/CHF moved 30% in minutes in January 2015), and every live quote for that pair becomes a guaranteed loss the instant it is accepted. The aggregator rejects STALE rates but nothing on this board watches VOLATILITY: there is no breaker that widens spreads or withdraws outstanding quotes when the mid moves more than the spread within a quote lifetime, and the hedge only runs once the net position crosses $250,000 - so the loss is booked before treasury has even been told it exists.

Practise this as an interview

Take Currency exchange - a rate that is only true for a few seconds as a timed system design interview on a blank board - on your own, with the requirements to check yourself against, or with a candidate you invite.

Practise this as an interview

Start here

Why this design

Any product that lets money cross a border - a wallet, a remittance app, a marketplace paying sellers abroad, a card spending in a foreign currency - has to answer "how much will I get?" with a number it will honour. The naive design reads a rate at the moment of execution and multiplies; the customer sees one number and receives another. Interviewers use this question to see whether you model the quote as a stored, expiring promise, whether you know a cross-currency movement must balance per currency, and whether you can say exactly where a rounding fraction goes. Treasury teams care about the next layer: every executed quote leaves the company holding currency risk until it is hedged.

What you will learn

  • Why a quote is a row with a frozen rate, both amounts already rounded, and an expires_at - and why execution spends a quote id, never "the current rate".
  • How a mid rate is built from three feeds, and why staleness is a reject, not a warning.
  • How the spread and the rounding rule are applied in that order, in integers, per currency’s minor units (USD 2, JPY 0, KWD 3).
  • Why a conversion is four ledger entries in two currencies through FX position accounts, and each currency sums to zero.
  • How the company’s resulting exposure flows to treasury and is netted before it is hedged.
  • The honest weakness: a 30-second quote is a free option, and nothing here withdraws quotes when the market gaps.

How to read this board

  1. Diagram, left to right: RATES (a number that decays), QUOTE (a promise with an expiry), EXECUTE (only a live quote can be spent), TREASURY (the risk you kept). Press play for the walkthrough.
  2. Below it, RECONCILIATION: quoted vs executed vs hedged, and where rounding went.
  3. Then the DATA MODEL: five tables. Note conversions is UNIQUE on quote_id.
  4. Pages 1-3 · Requirements, Capacity and Storage: 5 M quotes a day, 1,170 ticks a second in.
  5. Page 4 · Availability - why a stale rate stops quoting rather than guessing.
  6. Page 5 · How it works - 1,000 USD to EUR end to end, then Page 6 · Deployment.

1 · Requirements

The service quotes and executes currency conversions for customers holding balances in several currencies. It does not set the market price - it buys rates from liquidity providers - but it sets its own spread, owns the rounding rule, and holds the resulting position until treasury covers it.

Ask these before designing

  • Firm quotes or indicative? A firm quote is honoured if accepted before expiry. An indicative one is re-priced at execution. Firm is what customers expect and what this board does; it is also what creates the free option.
  • How long is a quote alive? 30 s is common for retail. Longer helps conversion rate and costs margin; shorter annoys people on slow phones.
  • Which side is the customer fixing? "Send exactly 1,000 USD" and "receive exactly 900 EUR" are different calculations and round on different sides.
  • Which way does rounding go, and where does the remainder land? Half-even on the received amount, with the difference absorbed by the FX position account, is one defensible answer. "Always in our favour" is another, and is a regulatory conversation.
  • Do we hold the risk or pass it through? Matching every conversion one-for-one with a provider trade removes risk and adds 200 ms and a fee to each. Netting and hedging above a threshold is cheaper and leaves the company exposed in between.

Functional

  • Build a mid rate per pair from multiple providers; reject a pair whose freshest good rate is older than 2 s.
  • Issue a firm quote: sell amount, buy amount, all-in rate, expiry.
  • Execute a conversion against a quote id, once, before expiry, by the customer who requested it.
  • Post the conversion to the ledger as balanced entries per currency.
  • Track net position per currency and hedge it above a threshold.
  • Reconcile daily: quoted margin vs realised margin vs hedge cost.

Non-functional

  • Quote p99 under 80 ms; execution p99 under 200 ms.
  • A rate older than 2 s is never quoted. Better to refuse than to quote a number the market has left.
  • Every executed conversion is reproducible from the stored quote - rate, rounding, amounts - years later.
  • Integer minor units in the ledger, always; rates stored as NUMERIC(18,8), never floats.

Out of scope

Payment rails, KYC, card-scheme FX, the provider contracts and treasury’s hedging strategy itself.

The rest of this board

Board preview

Available on Tier Slate

This page publishes the question. The answer — 5 more written pages, an 8-step narrated walkthrough and a 5-table schema — is the board itself, and it opens in Tierslate.

  • 5written pages
  • 8walkthrough steps
  • 5tables30 columns

5 pages behind this one

  • Capacity estimation
  • Storage estimation
  • Availability
  • How it works
  • Deployment plan
Open this board in TierslateBrowse every board

More boards

Systems where losing a write is losing money.

  • Double-entry ledger - the balance is not a column
  • Fraud detection - a decision that must fit in 120 milliseconds
  • Payment gateway - what a timeout means when the card may already be charged
  • Matching engine - price-time priority, and why the clock cannot decide who was first
  • Wallet transfers - the state machine, the hold that expires, and the reversal that cannot
  • OTP verification - six digits and a clock
  • Subscription billing - the invoice is computed, not typed
  • Loyalty points - a currency you print yourself
All 100 templatesOpen Tierslate
Tierslate

tierslate.com

HomeTemplatesPrivacyTerms