Senior and Staff candidates get the same system design prompt. The level is decided by what you do with it: which questions you ask, which two or three decisions you choose to spend time on, whether numbers drive those decisions, and whether you raise failure, migration, cost and ownership before anyone asks. This chapter answers one prompt (a notification system for a fintech app) three times, at L4, L5 and L6, phase by phase, so you can hear the difference, then gives you a rubric to score your own mocks.
How a design round sets your level
Takeaway: the interviewer levels you on what you raised yourself, not on how much you drew.
You are rarely told which level a round is aimed at. The interviewer writes down what you did and what they had to prompt, and the debrief or hiring committee maps that onto a level. The same moment, said two ways:
Senior
Interviewer: "What if the SMS provider is down?" You: "We retry with backoff and fall back to a second provider."
good answer, after a prompt
Staff
Before anyone asks: "The SMS provider is our weakest link, so OTPs get a second provider and a 5-second timeout, and I would alert on the delivery rate per provider."
same knowledge, raised unprompted
Three consequences:
- Unprompted beats prompted. Raising a failure mode yourself is Staff evidence; handling it well when asked is Senior evidence; missing it after a hint is below bar.
- Coverage is not the goal. A Staff answer often has fewer boxes on the board than a Senior one. The time goes into the two or three parts that decide whether the system works, and you say aloud what you are leaving out and why ("I am skipping template authoring; it does not change the design").
- Level is set per loop, then reviewed. Each round gives a view; a debrief or committee then weighs all of them together, and may place you one level lower than you applied for. In practice: Google L6 loops commonly include two design rounds; Meta's E6 loop has two design rounds as well, and a down-level to E5 after the debrief is common. Amazon down-levels SDE III candidates to SDE II often. A design round that reads Senior in a Staff loop is the usual cause.
| Shorthand used here (rough match, not exact) | Meta | Amazon | Microsoft | |
|---|---|---|---|---|
| L4 (mid) | L4 | E4 | L5 SDE II | 61–62 |
| L5 (senior) | L5 | E5 | L6 SDE III | 63–64 |
| L6 (staff) | L6 | E6 | L7 Principal | 65–66 |
The five things interviewers score
Every company has its own rubric wording. Underneath, they assess roughly the same five things. The descriptions below are in plain terms, with what moves each one from Senior to Staff.
| Dimension | What it means | L4 | L5 | L6 |
|---|---|---|---|---|
| Navigating the problem | Turning a vague prompt into a scoped problem with the constraints that matter | Asks generic questions (users? QPS?), accepts the first scope | Asks questions that change the design; writes functional and non-functional requirements with numbers | Identifies the one or two properties that make this problem hard, scopes to them, and states what is deliberately out |
| Solution design | A coherent architecture that meets the requirements | A reasonable diagram from memory; components unjustified | Each component justified by a requirement or a number; clean data model and API | The simplest design that meets the numbers, with explicit evolution paths; boundaries drawn by ownership and failure domain |
| Technical depth | Knowing how the parts actually behave | Names technologies | Explains mechanisms: why this index, this partition key, this consistency level | Goes deep where the risk is: failure semantics, contention, data correctness, and the costs of each option |
| Communication | Collaborating, structuring, listening | Answers questions; long silences or long monologues | Thinks out loud, checks in, adapts to hints | Sets and runs the agenda, summarises decisions, makes the interviewer's job easy, recovers cleanly from redirection |
| Operational maturity | Running it in production | Mentions monitoring when asked | Covers failure modes, retries, alerts | Raises SLOs, rollout and migration, cost, on-call ownership and blast radius before being asked |
The same five dimensions show up in behavioural rounds as scope, ambiguity, influence and impact. Your design round and your project deep-dive should tell a consistent story about the level you operate at.
The worked prompt
"Design a notification system for a fintech app. It sends users things like OTPs, payment and order confirmations, price alerts and marketing messages, over push, SMS and email."
Takeaway: at Staff level you name what makes the problem hard, and let numbers choose the design.
Each phase below shows what a typical L4, L5 and L6 candidate says. The L6 excerpts are not longer; they pick fewer things and give numbers. Read them aloud. Two terms first: a lane is a separate path through the system for one kind of message (OTP, alerts, marketing), with its own queue and capacity; an SLO is a target you promise, such as "99.9% of OTPs handed to the SMS provider within 2 s". The provider is the outside company that actually delivers SMS or email.
L5 sentence
"Say 20M notifications a day, about 230 a second, with 10x peaks at market open."
L6 sentence
"Throughput is not the problem. Isolation and cost are: a marketing blast must not delay an OTP, and SMS at 4M a day is ₹8 lakh."
Why only three numbers? A design cannot be built to fit twenty numbers. Pick the few that would change a decision, and say which decision each one changes.
HLD 1 · Requirements
L4
"How many users? Should it support push, SMS and email? Do we need retries? OK, so we need to send notifications reliably to users on three channels. Let me draw the architecture."
generic questions no priorities
L5
"Functional: services submit a notification for a user; we pick channels from user preferences, render templates, deliver, and track status. Non-functional: 5M users, OTPs delivered within a few seconds, at-least-once delivery, no duplicates visible to users if we can help it, marketing respects opt-outs. Out of scope: building our own SMS gateway."
numbers explicit scope
L6
"Before I list features: the hard part here is that these messages are not equal. An OTP that arrives in 40 seconds is a failed login; a marketing push that arrives an hour late is fine. So the defining requirement is isolation by priority: a marketing blast to 5M users must never delay an OTP. Second, some of these are regulatory: trade confirmations must be delivered and provable. Third, SMS costs real money per message, so channel choice is a cost decision. I'll scope to those three and treat template authoring and analytics as out. Does that match what you want to explore?"
names what makes it hard checks in
HLD 2 · Estimation
L4
"5M users, maybe 10 notifications each a day, that's 50M a day, about 580 per second. We'll need a scalable queue."
number computed, then ignored
L5
"Say 2M daily actives, 10 notifications each: 20M a day, about 230 a second on average. Peaks are at market open, maybe 10× for a few minutes, so plan for 2–3k a second. Storage for status: 20M rows a day at ~500 bytes is 10 GB a day; keep 90 days hot."
peak vs average storage
L6
"Three numbers drive this design. First, the market-open spike: if 300k price alerts trigger in the first minute, that's 5k a second on the alert lane alone, so lanes need separate capacity. Second, OTP volume is small, maybe 20 a second, but its latency budget is a few seconds end to end, and the SMS provider takes 1–3 s of that. Third, SMS cost: at an assumed ₹0.20 per SMS, sending 4M of the daily 20M by SMS would be ₹8 lakh a day, so SMS is reserved for OTPs and critical fallbacks. Throughput itself is not the problem; isolation and cost are."
numbers choose the design
# the L6 arithmetic, written on the board (all assumptions)
DAU 2M × 10 notifications = 20M/day ≈ 230/s average
price-alert burst at open = 300k in 60 s ≈ 5,000/s
OTPs ≈ 20/s, p99 budget ~5 s, provider 1–3 s
SMS at ₹0.20 × 4M/day = ₹8 lakh/day → OTP/critical only
status rows 20M × 500 B = 10 GB/day → 90 days hot ≈ 0.9 TB
LLD 3 · API and data
L4
"POST /notify with user id and message. A table of notifications."
L5
"POST /v1/notifications with user_id, type, template_id, params, and an idempotency key from the producer. Tables: notifications, per-channel delivery attempts, user preferences, device tokens. Partition by user id."
L6
"Producers send an event, not a message: {type: order.filled, user, dedup_key: order_id+fill_seq, priority: transactional}. The notification service owns templates, channel choice and preferences, so product teams cannot accidentally SMS 5M people. dedup_key makes producer retries harmless. The delivery log is append-only and keyed by notification id, because for trade confirmations it is evidence."
HLD 4 · High-level design
L4
"API → Kafka → worker → APNs/FCM, Twilio, SES. Add a database and a cache. Add a load balancer."
boxes from memory
L5
"API validates and writes the notification, publishes to a queue; workers resolve preferences, render, and hand off to per-channel senders; senders call providers and record status; retries with backoff; a dead-letter queue."
complete happy path
L6
"Same pipeline, with two structural choices. Separate queues and worker pools per priority lane, so the marketing lane can be saturated or paused without touching OTPs. And per-provider senders behind a circuit breaker with a secondary provider for SMS, because the provider is the least reliable component we depend on. Everything else is deliberately boring."
two decisions, justified
producers ──► notification API ──► notifications DB (dedup_key unique)
│ outbox
┌───────────┼──────────────────────┐
[lane: otp] [lane: transactional] [lane: bulk/marketing]
│ │ │ rate-limited, pausable
workers: prefs → template → channel choice
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────────┐ │
│SMS send │ │push send│ │email │◄─────┘
│A ⇄ B │ │APNs/FCM │ │sender │ circuit breaker per provider
└────┬────┘ └────┬────┘ └───┬────┘
└──── delivery_attempt log (append-only) ◄── provider callbacks
HLD 5 · Deep dive
L4
Waits to be asked. When asked about duplicates: "Kafka has exactly-once, so we're fine."
buzzword answer
L5
"Kafka gives at-least-once to our workers, so a worker crash after calling the provider but before recording it resends. I'd record an attempt before calling the provider and check it on retry; an attempt with no provider reference means the outcome is unknown, so I'd ask the provider's status API before resending. For push, a collapse id (APNs apns-collapse-id, FCM collapse_key) makes a resend replace the earlier notification on the device instead of showing twice."
correct mechanism
L6
"I'd like to go deep on the one place correctness and user trust meet: duplicates and losses at the provider boundary. Exactly-once delivery to a phone is not achievable; the provider call is a side effect outside our transaction. So I aim for at-least-once with deduplication where the cost of a duplicate is high. For OTPs a duplicate is harmless; a lost one is not, so retry aggressively and fail over to provider B after 3 s. For 'withdrawal processed', a duplicate generates support calls, so record an attempt with a provider reference before retrying and reconcile against provider delivery reports. For marketing, drop rather than duplicate. Different semantics per lane, chosen by the cost of each failure."
chooses the deep dive semantics per cost
HLD 6 · Trade-offs
L4
"We could use RabbitMQ or Kafka. Kafka is more scalable."
L5
"Separate queues per priority cost more infrastructure but give isolation. Storing every attempt costs storage but helps debugging. A second SMS provider costs integration work but improves availability."
names costs
L6
"What I'm choosing not to build: our own push infrastructure, send-time optimisation, and a rich preference centre. Each is a quarter of work that doesn't change OTP latency or confirmation reliability. The decision I'm least sure of is a second SMS provider: it roughly doubles template and compliance work, and in India our sender headers and templates live on the operators' DLT registry, so they carry over, but onboarding the second aggregator still means confirming its operator connectivity for our registered headers and testing every OTP template through it end to end. I'd take it only if the primary's measured availability misses our OTP SLO."
says what not to build flags uncertainty
HLD 7 · Operations
L4
"We'd add monitoring and alerts."
L5
"Metrics: queue depth per lane, send latency, provider error rates, DLQ size. Alert when OTP p99 exceeds 5 s. Dashboards per channel."
L6
"SLOs per lane: 99.9% of OTPs handed to a provider within 2 s, confirmations within 60 s, marketing best effort. A kill switch for marketing campaigns that on-call can flip. Invalid device tokens pruned from APNs/FCM feedback so we don't pay to send to dead devices. Cost per notification by channel on a dashboard. Ownership: a platform team owns the pipeline; product teams own their templates and types through a self-serve registry with review for any new SMS type. Migration: existing services sending SMS directly move behind the API one type at a time, OTP last, with shadow sends to compare."
SLOs cost ownership migration
The L6 answer did not cover more ground. It identified the property that makes the problem hard (unequal messages), let three numbers pick the design, spent the deep dive on the boundary where correctness breaks, said what not to build, and raised SLOs, cost, ownership and migration without being asked.