Build an S3-style distributed object store (12 scenes)
Scene 06 · Two planes: the index says where, storage holds what
Index plane vs data plane; trace a GET (read k, reconstruct, verify, stream) and a PUT's atomic index commit.
Previously

Fragments are now spread across failure domains for safety — so something has to remember which storage node holds which fragment. That something is the index plane, and wiring it to the storage nodes gives us the whole read path.

Scene 06
Two planes: the index says where, storage holds what
Diagram
Left to right: a Frontend that takes a request, an index plane (a keymap from each object key to the list of storage nodes holding its fragments — the WHERE), and a data plane (a row of dumb storage nodes, each holding one fragment — the WHAT). A GET walks the top ribbon: authenticate, look up the index, read k fragments, reconstruct if any are missing, verify a checksum, stream.
GET PATH1. authenticate2. index lookup3. read k fragments4. reconstruct5. verify checksum6. stream bytesFrontendGETauthenticatedindex planekey → fragment locations · WHEREphotos/cat.jpgsn1:d1 sn2:d2 sn3:d3 sn4:p1logs/2026-06-03sn2:d1 sn3:d2 sn4:p1db/backup.tarsn1:d2 sn3:d4 sn4:d1read kdata planedumb storage nodes hold fragments · WHATnode-1d1node-2d2node-3d3node-4p1authenticate
A GET arrives. The Frontend authenticates the request, asks the index plane where this key's fragments live, reads k fragments from the storage nodes in parallel, verifies a checksum, and streams the bytes back. Watch the ribbon walk the path.
Implementation
Frontend.get
resolve the key, read k fragments, rebuild if any are missing
1def get(bucket, key):
2 authenticate(request)
3 # ask the index plane WHERE the fragments live
4 meta = index.lookup(bucket, key)
5 if meta is None:
6 return 404 # nothing points at any bytes
7 frags = read_parallel(meta.locations) # data plane
8 if any_missing(frags):
9 # degraded read: pull parity, solve for the gap
10 frags = reconstruct(frags, meta.parity)
11 obj = concat(frags)
12 verify(checksum(obj), meta.checksum)
13 return stream(obj)
IndexPlane.lookup
the keymap: key → fragment locations, scaled apart from bytes
1# the index plane — one tiny row per object
2# rows scale with OBJECT COUNT, not byte volume
3def lookup(bucket, key):
4 shard = route_by_key(bucket, key) # flat keyspace
5 row = shard.get(key)
6 if row is None:
7 return None # source of truth for existence
8 return row # locations, parity, checksum, size
Not sure what to ask? Tap a question — the staff engineer answers in the chat panel.