Defending a design decision
What separates a senior answer from a confident one.
Open this lesson in the learning hubKey points
- Every architectural choice buys something and pays for it elsewhere. An answer that names only the benefit is incomplete, and an interviewer or reviewer will test exactly that.
- State the trade explicitly: what this gains, what it costs, and the condition under which you would choose differently. That last part is what demonstrates judgement rather than recall.
- Anchor decisions to the requirements, not to what is fashionable. "We need read-your-writes for the profile page, so those reads go to the primary" is a reason; "we use microservices" is not.
- Be willing to choose the boring option. A single well-indexed relational database serves an enormous range of systems, and proposing it when it fits is a stronger signal than proposing a distributed one.
- Quantify where you can. "Roughly 350 writes per second, which one Postgres instance handles comfortably" ends a debate that "it should scale fine" only starts.
- Name what you are not solving. Explicitly deferring multi-region, or accepting a known limit, shows the scope is deliberate rather than overlooked.
Example
/*
* A DECISION, STATED PROPERLY:
*
* "Order events go through Kafka rather than a synchronous call.
*
* GAINS: billing can be down for minutes without failing checkout;
* new consumers attach with no change to the producer;
* the log can be replayed to rebuild a consumer.
*
* COSTS: billing is eventually consistent, so the UI must not
* promise an invoice immediately;
* duplicate delivery is possible, so consumers need
* idempotency keys;
* a broker to run, monitor and upgrade.
*
* I WOULD CHOOSE DIFFERENTLY IF: the caller needs the invoice id in
* the response. Then it is a synchronous call with a timeout and a
* circuit breaker, and we accept the coupling."
*
* That third paragraph is the one that signals seniority.
*/
/*
* TRADES WORTH BEING FLUENT IN:
*
* SQL vs NoSQL
* SQL joins, transactions, mature tooling, one node scales far
* NoSQL horizontal scale, flexible schema; you give up joins and
* usually multi-key transactions
* choose NoSQL when the ACCESS PATTERN is known and uniform
*
* normalise vs denormalise
* normalised one source of truth, expensive reads
* denormalised fast reads, and every write must fan out
* choose by the read:write ratio, not by taste
*
* sync vs async
* sync immediate result, coupled availability
* async decoupled, eventually consistent, needs idempotency
* choose by whether the caller NEEDS the result now
*
* cache vs not
* cache fast reads; now you own invalidation and staleness
* none always correct, always pays full cost
* do not cache what is cheap or what must never be stale
*/
/*
* ANSWERS THAT SIGNAL EXPERIENCE:
*
* "One Postgres handles this volume. I would not shard until we see
* a reason to, and here is the number I would watch."
*
* "Eventually consistent is fine for the feed and not for the balance,
* so those take different paths."
*
* "I am not solving multi-region today. Here is what would have to
* change if we did."
*/
Name the gain, the cost, and the condition that would change your mind - and be willing to choose the boring option when it fits.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the System Design course, and every lesson in it is listed on the System Design contents page.