Defending a design decision

System Design · lesson 32 of 32 · 6 min read

What separates a senior answer from a confident one.

Open this lesson in the learning hub

Key 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.