The Interview Delivery Playbook System design, chapter 10

Follow-up question bank

The second half of every round.

The first fifteen minutes are the design. The rest is follow-ups, and this is where rounds are actually won or lost. These are the questions that recur regardless of the prompt, with answers built on one running example: the backend of a retail trading app, where orders go to an executing broker over the FIX protocol and every fill lands in a ledger. Swap in your own system's components as you practise. Read the question, answer it out loud, then open the answer.

What if traffic grows 10x overnight?

Name the first thing to break, not a generic answer. Here it's the FIX gateway, because it's the one stateful, non-horizontally-scalable component — everything else is behind autoscaling. The fix is sharding sessions by account range across gateway instances, and I'd want the ordering guarantee preserved within each shard.

Then say what you'd watch: queue depth on the order stream, and the age of the oldest unprocessed record. Those two tell you whether you're keeping up before customers do.

The broker is down for two hours at market open. What happens?

Orders keep being accepted and persisted — the event log is durable and independent of the broker — but nothing routes. The critical decision is what the client sees: 'accepted, pending routing' is honest; showing 'placed' is not.

I'd add a circuit breaker so we stop attempting and stop timing out, plus a product decision on whether to keep accepting or refuse new orders with a clear message. When the session recovers, we drain in order and reconcile order status before assuming anything about what filled.

How do you know your ledger is correct?

Three independent checks. First, an invariant: every entry group must sum to zero, enforced at write time. Second, daily reconciliation against the broker's statement, with breaks classified and rate-monitored. Third, periodic recomputation — fold the event log from scratch and compare against the snapshot balances.

The third one is the strongest and people skip it. If a replay disagrees with the snapshot, either the fold logic or the snapshot is wrong, and you want to find that before an auditor does.

A user says their balance is wrong. Walk me through the investigation.

Start from the correlation ID if they came through support with a specific action, otherwise from the account and date. Pull the audit events for that account in the window — every state change with before and after state. Then fold the ledger entries for the account to the disputed moment and compare to what was displayed.

The three usual causes, in order: traded-versus-settled confusion (they're seeing one and expecting the other), an unapplied corporate action, or an identifier-mapping break attributing someone else's trade. The append-only ledger makes all three provable rather than a matter of opinion.

Why not just use one database for everything?

For this scale, honestly, you could get a long way with Postgres alone, and I'd say that rather than pretend otherwise. The reasons to split are specific: holdings reads are key-value by account at high volume, which DynamoDB does more cheaply and predictably; audit is write-heavy and queried rarely, which suits S3 plus Athena at a fraction of the cost of keeping it in Aurora; and prices are ephemeral, which is Redis.

Each split has to earn itself. The cost is keeping them consistent, which is why the event log is the source of propagation.