Day 99 of 100·System Design Day·1289 words

The 60-minute whiteboard loop, and how to grade yourself

A repeatable time-boxed structure for any design prompt, plus a six-dimension rubric and the failure modes that cost offers.

Concept → your projects

You have 100 days of content in your head. This article is about delivery: a fixed structure you can run under pressure so that knowledge shows up as signal. The structure is time-boxed, and the time-boxing is not decoration — it is what stops you from spending 25 minutes on the data model and never mentioning failure modes.

The clock

0:00–0:05 — Clarify. Ask 3–5 questions and write the answers on the board. Good ones: who are the users and roughly how many? What is the read/write mix? Is consistency or availability the priority when they conflict? What is the latency target? What is explicitly out of scope? Do not ask questions whose answers you would not use.

0:05–0:12 — Requirements and NFRs. Write two columns: functional (the 4–6 things it must do) and non-functional (latency target, availability target, durability, consistency, scale, security/compliance). This is the step where most candidates lose the plot by skipping it. Day 3's NFR vocabulary is your script here.

0:12–0:20 — Estimation, with numbers. DAU → requests/sec (peak = 2–3× average) → storage/year → bandwidth. Round aggressively and say so. The point is not precision; the point is that your design decisions later must be traceable to a number you wrote here. "10M DAU × 20 reads/day ÷ 86,400 ≈ 2,300 rps average, call it 7,000 peak — that is why I need a cache and a read replica."

0:20–0:28 — API surface. 5–8 endpoints, REST or gRPC, with the request/response shape for the important one. Include pagination, idempotency keys on writes, and the error contract. You have opinions here from Day 17 (idempotency) and Day 18 (versioning).

0:28–0:40 — Data model. Tables or collections with keys and indexes, and the access patterns that justify each index. Then the storage choice and why (Day 26 relational modelling, Day 41 partitioning, Day 53 storage engines). Say out loud which fields are immutable — that determines what you can cache forever.

0:40–0:50 — Deep dive. The interviewer usually picks one; if they do not, pick the hardest thing and volunteer it. Good candidates: the hot path's latency budget, the consistency boundary, the queue and its failure modes, the cache invalidation story, the tenancy isolation model. This is where Days 43–64 pay off.

0:50–0:58 — Failure, scale, and operations. What breaks at 10×? What happens when the cache dies, the queue backs up, the DB replica lags, a dependency is slow? How do you deploy this without downtime (expand/contract, Day 85)? What are you alerted on (Day 83)? What is the backup and restore story (Day 87)? Candidates who reach this unprompted are rare and memorable.

0:58–1:00 — Wrap. Two sentences: the design, and the one trade-off you would revisit with real numbers. Then stop talking. Do not keep adding.

The rubric: score yourself 1–4 on six dimensions

  1. Requirements discipline — did you separate functional from non-functional, and did you revisit them?
  2. Quantitative reasoning — did you produce numbers and use them, or did you estimate and forget?
  3. Data model quality — keys, indexes, and access patterns that match the queries; immutability identified.
  4. Trade-off articulation — every choice stated as "X because Y, at the cost of Z". A choice with no cost is a choice you have not understood.
  5. Failure literacy — did you discuss what happens when components die, not just when they work?
  6. Communication — did you drive, or did you wait to be led? Did you name patterns?

Anything scoring 1 or 2 becomes next week's study target. Score honestly; the rubric is worthless if you grade generously.

A worked walkthrough: "design an access governance platform"

Use Zoth as the worked example so the loop is muscle memory tied to a system you own.

Clarify: enterprise tenants, hundreds to low thousands of employees each; reads (policy checks, dashboards) outnumber writes (grant requests) ~50:1; availability over strict consistency for reads, but the decision path must be strictly consistent — you cannot allow access based on a stale read; p99 latency target of a few hundred milliseconds for a check.

Requirements: manage identities and entitlements; evaluate policy; run a request/approve/activate/expire/revoke lifecycle; provision and deprovision in external systems; produce tamper-evident audit. NFRs: multi-tenant isolation, auditability, no advisory component can bypass policy, and access changes must never block user-facing API calls.

Estimate: 1,000 tenants × 500 users = 500k identities; 50 reads per user per day = 25M checks/day ≈ 300 rps average, ~1k peak; grants are rare — thousands per day, not millions; audit grows unboundedly (millions of rows/year) → partition and archive.

API: POST /grants (idempotency key, returns the workflow state), POST /grants/{id}/approve, POST /grants/{id}/revoke, GET /entitlements?user=, POST /policy/evaluate, GET /audit?...cursor. Error contract: 404 for both "not found" and "not yours" (Day 98).

Data model: tenants, identities, resources, entitlements, grants (with state, expires_at, and a unique constraint that makes double-activation impossible), approvals, audit (hash-chained, append-only), outbox. Indexes driven by the access patterns: entitlements by (tenant_id, user_id), grants by (state, expires_at) for the expiry ticker, audit by (tenant_id, created_at) with a cursor.

Deep dive: the expiry and provisioning path. An expiry ticker claims due grants with SKIP LOCKED and moves them to expired, emitting an outbox event; a relay publishes to the broker; a consumer performs the external revocation idempotently and marks the grant revoked. The transactional outbox is what makes "the access was revoked" and "the message was published" atomic — and the design accepts at-least-once delivery in exchange for never losing the side effect (Day 60).

Failure/scale: cache policy decisions with explicit invalidation on entitlement change and accept the staleness window, or do not cache the decision path at all — that is the trade-off to surface. A broker outage must not block writes (outbox absorbs it). A connector outage parks that grant in a retryable state with backoff rather than failing the workflow. Audit must be partitioned by time or the table becomes a tombstone. Deploy with expand/contract so a rolling update never sees an old writer against a new schema.

That is a complete 60-minute answer, and you can deliver it because you have debugged every part of it for real.

The failure modes that cost offers

  • Jumping to technology in the first minute. "I'd use Kafka and Cassandra" before knowing the access pattern.
  • No numbers. Estimation is not optional; it is how you prove the design is sized to reality.
  • Trade-offs with no cost. "I chose Postgres because it's reliable" is not a trade-off. "I chose Postgres because the access patterns are relational and I would rather scale vertically first than operate a second datastore — the cost is that a single-writer bottleneck is my ceiling" is.
  • Ignoring failure. A design that only works when everything is up is a design for a demo.
  • Not driving. Silence waiting for permission reads as uncertainty. Narrate: "I'm going to spend the next four minutes on the data model because the indexing decision drives everything else."
  • Overrunning. If you are at 45 minutes and have not mentioned failure, stop the deep dive and go there. Coverage of the rubric beats depth on one section.

How to practice this

One prompt, one timer, one recording, one rubric pass. Once a week is enough. Rotate the prompt type so you are not rehearsing one shape. And deliberately practice the interrupt: have a friend stop you mid-deep-dive with "what if that component is down" — recovering gracefully from an interruption is its own skill and it is what real interviews feel like.

Bulletproof your resume

Say these answers aloud before moving on

These are the follow-ups an interviewer will actually ask about your projects.

01

You have 60 minutes for a design question. What does your structure look like?

Six phases with a clock. First five minutes clarifying — users, scale, read/write mix, latency target, what is out of scope. Then seven minutes writing functional requirements next to non-functional ones, because NFRs drive every later decision. Then eight minutes of estimation with numbers I actually reuse: requests per second at peak, storage per year, bandwidth. Then eight minutes on the API surface including pagination, idempotency keys, and the error contract. Then twelve minutes on the data model with keys, indexes, and the access patterns that justify each index. Then ten minutes on the deep dive the interviewer cares about. Then eight minutes on failure, scale, and operations — what breaks at ten times the load, what happens when a component dies, how you deploy without downtime. Then a two-sentence wrap naming the design and the trade-off I would revisit.

02

How do you make sure you mention failure modes without running out of time?

By time-boxing the earlier phases and treating the failure phase as non-negotiable rather than as a bonus. The most common way to run out of time is over-investing in the data model, so I cap it and say so out loud: I will spend twelve minutes here and then move on. If I am at forty-five minutes and have not touched failure, I stop the current thread and go there — covering the rubric beats depth on one section. And I have a standing checklist so I do not have to think: what breaks at ten times load, what happens when the cache or the queue or a dependency fails, how do I deploy this without downtime, what am I alerted on, and what is my restore story. Five questions, three or four minutes.

03

What is the most common mistake candidates make in design interviews?

Stating choices without costs. Every design decision has a price, and a candidate who only names the benefit has not understood the decision — they have memorized it. The fix is a fixed sentence shape: I chose X because Y, at the cost of Z. The second most common mistake is jumping to technology in the first minute, naming Kafka and Cassandra before knowing the access pattern. And the third is silence: waiting to be led instead of narrating the plan. Interviewers are evaluating how you think, so the thinking has to be audible.