</> MAANG.io

Expert

Design landmark systems in depth, from Dynamo, GFS, Bigtable and Kafka to payments and ads pipelines.

0 of 232 solved 0%

Section 2: A Contract for Throughput, Not Latency - Requirements (Functional & Non-Functional)

Executive Summary: Section 1 reframed the prompt as a storage fleet that serves a handful of internal batch applications, where machines fail every day. This section turns those assumptions into a contract. Functionally, the system offers a hierarchical namespace, reads and writes at an offset, an atomic record append whose offset the system chooses, and a cheap snapshot. Non-functionally, it promises about 520 GB/s of peak aggregate reads, at least 100 MB/s on a single stream, survival of any two machine failures or one whole rack, and full replication restored within about 30 minutes. The consistency promise is deliberately weaker than POSIX, and the non-goals list is as important as the feature list.

The interviewer caps the marker. "You've told me the workload. Now tell me what you're promising, in numbers I could test, and what you're refusing to build."

You: "Three lists. What it does, which I can demo. What it guarantees, which I can measure. What it won't do, which I can defend. The headline: this is a throughput contract. I'll give you a latency number where an operation needs one, but no requirement here is about microseconds."

Six workload assumptions, each forcing a requirement: daily machine failures force automatic re-replication and per-block checksums; multi-GB files force large files first-class; streaming reads force aggregate bandwidth over latency; hundreds of appenders force atomic at-least-once record append; changeable internal clients force a library API with relaxed consistency and no POSIX; cheap checkpoints force copy-on-write snapshots

Functional requirements: the demo list

Each item is shown through the running example: 500 crawlers appending 1 MB records to /crawl/2026-11-02/hour-09.rec, read later by an indexing MapReduce job.

  • Hierarchical namespace: create, delete, open, close, rename and list over paths like /crawl/2026-11-02/. Every namespace operation is atomic. A job that writes hour-09.rec.tmp and renames it on completion never exposes a half-finished file.
  • Read at an offset: read(file, offset, length). The indexer's map task asks for byte 2,700,000,000 and gets bytes back from a replica, without the read passing through any central server.
  • Write at an offset: write(file, offset, data). It's supported, but it's the rare case. Section 1 established that overwrites are uncommon in this workload.
  • Record append: recordAppend(file, data) → offset. The system chooses the offset, places the record atomically as one contiguous run of bytes, and returns where it went. 500 crawlers can append to the same file at the same time without any lock between them. Records are capped at 16 MB, a quarter of a chunk.
  • Snapshot: snapshot(src, dst) copies a file or a whole directory tree almost instantly, so a team can branch a dataset or checkpoint it before a risky job. Section 9 shows it's copy-on-write, so the cost is paid only when a chunk is later written.

Interviewer: "Why is append its own operation? Give each crawler a lock and let it write at the end."

You: "A lock would serialize 500 writers through one holder, and one file per producer would shatter the hourly file into 500 pieces. Section 4 makes both arguments in full. Record append moves the ordering into the storage system, where one replica (the primary) already sees every append to a chunk."

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

Sign in to MAANG.io

Use your Google or Microsoft account — no password to remember.

Continue with Google Continue with Microsoft

Please accept the terms above to continue.