Immutable objects: overwrite is a new version, not an edit — delete markers and the atomic pointer flip
Bytes at a storage location never change — an overwrite writes brand-new bytes and atomically flips the index pointer to them, and a delete just inserts a zero-byte delete marker, so the old bytes persist (and keep billing) behind it.
The index points at an object's current bytes — so we need to pin down what those bytes are: they turn out to be immutable, and 'overwrite' is not what you think.
Scene 04
Immutable objects: overwrite is a new version, not an edit
- Watch
- Try it
- Predict
- Capture
One key, one blob. Watch a PUT to the SAME key: it drops a brand-new blob on top, the index pointer flips up to it, and the old blob greys out but stays. Then watch an attempt to edit a byte in place — it's refused.
Highlighted lines are the ones running in the diagram right now.
def put(key, body):# bytes are sealed at write time; allocate a fresh blobversionId = newVersionId()storage.writeImmutable(versionId, body)if versioning.enabled(key):# keep the old blob as a recoverable versionindex[key].versions.prepend(versionId)else:old = index[key].currentindex[key].versions = [versionId]storage.free(old) # old bytes discardedindex[key].current = versionId # atomic pointer flip
def delete(key):if not versioning.enabled(key):storage.free(index[key].current)del index[key]return# versioning on: nothing is erasedmarker = newDeleteMarker() # 0 bytes, not billedindex[key].versions.prepend(marker)index[key].current = marker # GET will now 404# prior versions still sit on disk, still billing
def get(key):cur = index[key].currentif cur.isDeleteMarker:return 404 # marker is current; bytes live behind itreturn storage.read(cur) # newest sealed bytesdef reapVersion(key, versionId):# the ONLY op that frees bytes and stops their billindex[key].versions.remove(versionId)storage.free(versionId)
Where this sits in Build an S3-style distributed object store
Scene 04 of 12, in the Name & shape act — The flat keyspace, its index, and immutable objects.. Bytes never change: overwrite = new version + atomic pointer flip; delete drops a marker the old bytes hide behind.
Up next. If a stored object is a sealed, never-changing blob, we can finally store it durably against weekly disk death — and the cheapest safe way to do that is not what most people reach for.
All 12 scenes in Build an S3-style distributed object store · Every curriculum