Requirements and the get/put API
Why this matters: every mechanism in the rest of this chapter exists because of one of these requirements. Getting them stated precisely is what makes the design defensible instead of arbitrary.
Key takeaway
Standard key-value stores offer get and put. This design adds three specific characteristics — configurable consistency, the ability to always write, and hardware heterogeneity — and each one forces a concrete architectural decision.
Functional requirements
| Requirement | What it means | What it forces |
|---|---|---|
| Configurable service | Applications trade strong consistency for higher availability; the system must support configurable consistency models balancing availability, consistency, cost, and performance | Tunable r/w/n quorums (Lesson 7) |
| Ability to always write | Applications must always be able to write to storage — prioritizing availability over consistency, choosing A over C in CAP | Peer-to-peer replication, sloppy quorums, hinted handoff, and conflict reconciliation |
| Hardware heterogeneity | New servers with different capacities integrate seamlessly without upgrading existing ones; workload distribution aligns with server capacity | A peer-to-peer design with no distinguished nodes, and virtual nodes proportional to capacity (Lesson 4) |
Non-functional requirements
- Scalability — the system must support tens of thousands of servers globally. Incremental scalability is essential: servers can be added or removed with minimal service disruption.
- Fault tolerance — the system must operate uninterrupted despite server or component failures.
"Incremental scalability with minimal disruption" is the phrase that kills modulo hashing in the next lesson. Read it as a hard constraint, not an aspiration.
Assumptions
Three simplifications, stated so the interviewer can challenge them:
- Data centers hosting the service are trusted (non-hostile).
- Authentication and authorization are handled externally.
- User requests and responses use HTTPS.
The first is the interesting one — it lets us assume crash faults rather than Byzantine faults, which is what makes gossip and quorums sufficient. In an adversarial setting the whole design would need 3f+1 replicas and signed messages.
API design
Like hash tables, key-value stores provide exactly two primary operations.
The get function
get(key)
Returns the value associated with key. In replicated environments the system locates the object replica, hidden from the user. If configured for weaker consistency — eventual consistency — the system may return multiple values (versions) for a single key.
| Parameter | Description |
|---|---|
key | The key against which we want to get a value |
The put function
put(key, value)
Stores the value associated with key. The system automatically determines data placement and maintains metadata such as the object version.
| Parameter | Description |
|---|---|
key | The key against which we store the value |
value | The object to be stored against the key |
Data type
The key serves as the unique identifier; the value can be any arbitrary binary data.
Why we start with the non-functional requirements
The next lesson begins with scalability rather than with features, because the chosen scalability strategy shapes how the functional requirements are implemented. Consistent hashing determines where data lives; where data lives determines how it is replicated; how it is replicated determines what conflicts are possible.
Key takeaway
Two operations, three functional requirements, two non-functional ones. The API is deliberately tiny — and get() returning multiple values is the crack through which the entire distributed-systems problem enters.
Interview signal by level
| Level | What a strong answer sounds like |
|---|---|
| L4 | Lists get and put as the API and moves on. |
| L5 | States the CAP posture: "always-writable means we're choosing availability over consistency, so writes never get rejected." |
| Staff+ | Traces requirements to mechanisms: "always-write forces conflict reconciliation, so get() has to be able to return multiple versions — which means the API needs a context token. And heterogeneous hardware rules out uniform partitioning, so virtual nodes proportional to capacity." |
Next: making it scale, and why the obvious approach fails.