In a versioned document structure, what distinguishes full persistence from partial persistence for a user editing an old version?
answer
- both let you read old versions
- the difference is who may be extended
- partial keeps history a line
- full makes history a tree
- merging is a third, harder rung
basics
~20 sPartial persistence lets every version be read but only the newest be updated, so history is a straight line. Full persistence lets any version be updated too, so editing an old one forks history into a tree of versions.
solid answer
~40 sBoth degrees keep every version readable; they differ on which version may be *extended*. Under partial persistence, updates apply only to the newest version, so the history is a line and reopening yesterday's document gives a read-only view. Under full persistence, an update may be applied to any version, so editing an old one creates a sibling of what came after it and the history becomes a tree. A third degree, confluent persistence, additionally allows two versions to be combined into one, turning the history into a graph with merges - which is what a branch-and-merge workflow needs. Partial is the cheaper guarantee and covers plain linear undo; a user who branches from an old version needs full.
code
pseudocode · 12 lineslet v0 = emptyDocument
let v1 = edit(v0, "add heading")
let v2 = edit(v1, "add paragraph")
// partial persistence: v0 and v1 may be READ; only v2 may be extended
// full persistence: extending v1 again is allowed
let v3 = edit(v1, "add table") // v2 and v3 are now siblings
// history is no longer a line:
// v0 -> v1 -> v2
// \-> v3go deeper
Recall the one-line split: both let you read old versions, only full persistence lets you make a new edit starting from an old one.
Explain the resulting shapes - a line under partial, a tree under full - and why the linear case is cheaper and admits a simple increasing version number.
Recognise the degree from observed behaviour: redo silently discarded after an edit means the linear model, and no amount of tuning makes it branch. Name what full persistence adds in bookkeeping and what merging adds on top.
Decide the degree from the product promise, not the implementation: whether users may depart from history and whether branches must ever be reconciled. Merge semantics are a domain decision to own before any structure is chosen.
## Three degrees of the same guarantee "Persistent" says earlier versions stay valid. It does not say what you may *do* with them, and the standard classification separates exactly that. | degree | may read old versions | may update old versions | may combine two versions | history shape | |---|---|---|---|---| | partial | yes | no - newest only | no | a line | | full | yes | yes | no | a tree | | confluent | yes | yes | yes | a graph with merges | Every degree keeps the reading guarantee. The ladder is about *writing*. ## Partial persistence Updates apply to the newest version only. Because there is exactly one version that can be extended at any moment, the versions form a linear sequence, and each one can be labelled with a version number that only ever increases. That is enough for a large class of real needs: - **Linear undo and redo.** Walking back through the line and forward again requires only reading old versions. - **Snapshot reads.** A long-running export takes a version and reads it to completion while edits continue on the newest. - **Auditing and diffing.** Reconstructing what the document looked like at a point in time is a read. And it is cheaper. Implementations can exploit the linearity - for example by recording changes against nodes in version order and reconstructing an old version on demand - which full persistence cannot do, because there is no single "latest" to append to. ## Full persistence An update may be applied to **any** version, new or old. The moment a user reopens yesterday's version and types into it, that version has two successors: the one that already existed and the new one. The history is therefore a tree, and a version number no longer describes it - versions need identity, not order. What this enables: - **Branching from a point in history.** Explore an alternative from an old state without discarding the state that came after it. - **Undo that does not destroy the redo path.** Stepping back and editing does not have to truncate the forward history; it can fork instead. - **Independent exploration from one shared ancestor**, with every branch a first-class document. What it costs: more bookkeeping per version, and a user-facing question the linear model never has to answer - if two branches exist, which one is *the* document? A tree with no merge is a tree the user has to reconcile by hand. ## Confluent persistence The third rung allows an operation that takes **two** versions and produces one - a merge. That turns the tree into a directed graph, and it is a genuinely harder problem than either rung below it, for two reasons. Structurally, the merged result can share with both ancestors, so the cost analysis no longer follows the tree. Semantically, two versions that changed the same region need a rule for what the combination means, and no data structure can supply that rule - it is a domain decision about which change wins or how the two compose. ## Choosing for a real editor The test is one question: **can a user make an edit that departs from an old version while keeping what followed it?** - If undo just walks a line and an edit after undoing discards the forward history, partial persistence is the honest model and the cheaper one. - If reopening an old version and editing it must leave the later version intact and usable, full persistence is required. A partial implementation cannot fake it - not because it refuses, but because extending an old version is exactly the operation it does not offer. - If two independently edited versions must be brought back together, confluence is required and the merge semantics are a product decision before they are an implementation one. ## Where teams get this wrong The common error is shipping a linear model and then discovering the product wanted a tree: the undo stack is a list, someone undoes three steps and types, and the three forward states are silently thrown away because the list has no room for a second successor. That behaviour is a consequence of the degree of persistence chosen, and users experience it as lost work. The opposite error is paying for full persistence in a workflow that only ever moves forward, where the extra identity and bookkeeping buy a capability nothing in the product exposes.
- Why can a linear version number stop working under full persistence?Because a number encodes a total order, and full persistence produces siblings. Once one version has two successors, there is no consistent answer to which of them is 'next'. Versions need identities and a parent link instead, and the ordering that survives is ancestry - one version precedes another only if it is on the path to it.
- What makes merging two versions harder than extending one?Two things at once. Structurally the result shares with two ancestors, so it no longer sits in a tree and the cost reasoning changes. Semantically, if both versions changed the same region, something must decide what the combination means - and that is a domain rule about which change wins, which no structure can supply.
- Which degree does an undo stack that discards redo after a new edit actually implement?Partial persistence in effect: old versions are readable, but an edit always extends the newest state, so the forward states are dropped rather than kept as a sibling branch. If users complain about losing redone work after undoing, that is the degree of persistence showing through, not a bug in the list.
saying these in an interview costs you the question
- Thinks partial persistence means some versions are unreadable
- Says full persistence keeps history linear
- Assumes any persistent structure supports merging versions
- Believes version numbers still totally order a branching history
- Treats merge conflicts as a structural problem rather than a domain rule