Section 2: Every Guarantee Has a Price Tag - Requirements (Functional & Non-Functional)
Executive Summary: This section converts Section 1's clarified scope into the written contract a platform lives or dies by. We state the functional requirements as sentences you could demo on day one, name the non-goals explicitly — each with the future door it leaves ajar — and then build the non-functional requirements table the way infrastructure demands it: every guarantee annotated with the mechanism that pays for it and the latency or availability it costs. The section closes by answering the question the interviewer left hanging in Section 1 — "what consistency would you offer?" — with the move that defines this entire design: consistency is not a constant the platform imposes; it is a dial the platform sells.
For an app, requirements are features: a user can do X. For infrastructure, requirements are semantics: when a tenant calls put and gets back 200, what exactly has the universe promised them? The checkout team doesn't read your architecture diagrams. They read your contract, build revenue on top of it, and page Mira when reality diverges from it. This section is not a formality on the way to the fun parts — it is the product.
Functional Requirements: Sentences You Can Demo
State each one as something you could demo on a laptop; if you can't, it isn't a requirement yet.
- FR1 — Get:
get(key)returns the value most recently written to that key, subject to the consistency level chosen (we'll earn the right to that clause below). The checkout team callsget("cart:8842")and receives the 2KB cart blob. - FR2 — Put:
put(key, value)durably stores a value up to 400KB (the cap is a product decision we'll defend in Section 3 — oversized blobs belong in object storage, with a pointer here). A successful response means the write survives failures we'll quantify in the NFR table. - FR3 — Delete:
delete(key)removes the key. Deceptively simple-sounding; Section 9 reveals why deletion in a replicated store is one of the hardest requirements on this list. - FR4 — TTL: A
putmay carry a time-to-live, after which the key expires without a client ever calling delete. Session tokens and ephemeral locks make this table stakes for a platform store. - FR5 — Conditional put (CAS):
put_if(key, value, expected_version)succeeds only if the key's current version matches. This is the escape hatch for tenants who need read-modify-write safety — and Section 4 will explain why it's a separate, slower endpoint rather than the default. - FR6 — Tenant namespaces: Every key lives in a tenant namespace. The flags team's
config:flagsand the checkout team'scart:8842can never collide, and per-tenant accounting hangs off this boundary.
Key Insight: Notice what FR1 does not say: "returns the latest write, always, everywhere." For a single-node store that sentence is free. For a replicated store it is one of the most expensive sentences in computer science, and writing it down casually is how the Single-Node Thinker fails this interview. The honest version carries a consistency clause — and that clause is where the platform's value lives.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson