Versioned store

Keep every snapshot, never the eraser — a write adds a new page instead of rubbing out the old one.

The idea

A normal store overwrites: put(key, value) replaces the old bytes and the previous version is gone. A versioned store never destroys; each write appends a new immutable version under the same key. The key always resolves to the latest version, but every past version is still addressable by its number.

That history buys two things you can't get from overwrite-in-place: you can diff any two versions to see exactly what changed, and you can restore an old version by writing its content forward as a brand-new version. Nothing is mutated; restore is just another append.

Version history for key “config.json” Latest content
Press Play to write four versions, then diff or restore.

How it works

Each key maps to an append-only list of versions. put appends and returns the new version id; get returns the last one. diff(a, b) compares two stored contents. restore(n) reads version n and writes it as a fresh version — so the history grows and you can even undo the restore.

class VersionedStore:
    def __init__(self):
        self.history = {}              # key -> [v1, v2, ...]

    def put(self, key, value):
        self.history.setdefault(key, []).append(value)
        return len(self.history[key])  # 1-based version id

    def get(self, key, version=None):
        vs = self.history[key]
        return vs[-1] if version is None else vs[version - 1]

    def diff(self, key, a, b):
        old = set(self.get(key, a).items())
        new = set(self.get(key, b).items())
        return {"added": dict(new - old), "removed": dict(old - new)}

    def restore(self, key, version):
        return self.put(key, self.get(key, version))  # append, never mutate

Real systems add content-addressed dedup (identical versions share storage) and retention policies so history doesn't grow without bound.

Cost

OperationCostNote
put / appendO(1)New immutable version
get latestO(1)Tail of the list
get version nO(1)Indexed lookup
diffO(size)Compares two contents
restoreO(size)Append of an old version
StorageO(versions × size)Dedup & retention to bound it

Watch out for

Worked example

A teammate ships a config change in v4 that breaks production. With overwrite-in-place, v3's content is gone — you reconstruct it from memory. With a versioned store, you diff(v3, v4), see the single bad key that changed, and restore(v3). That restore appends a v5 identical to v3. The system is healthy again, and the whole timeline — including the mistake and the rollback — is preserved for the post-incident review.

Check yourself

You have versions v1…v4 and run restore(v2). What is the latest version afterwards?