Durable Writes, Journals, and Recovery Boundaries

LESSON

Storage and Filesystems

005 30 min intermediate

Durable Writes, Journals, and Recovery Boundaries

By the end of this lesson, you will be able to...

  • Trace a multi-step write through intent recording, durable decision, page writeback, and checkpoint.

  • Predict what recovery may replay, discard, or trust after a crash at a named point.

  • State what an acknowledgement promises locally and which signals reveal pressure on that promise.

Idea in one sentence: A durable write is not just bytes reaching a device; it is a recovery rule that ensures a crash leaves either a known old state or a known new state, not an unexplained mixture.

The publish button during a power cut

An editor changes a course title and presses Publish. The platform must update two pieces of durable state:

course record:      title = "Storage Paths"
publication index:  course-42 is visible

The editor sees success. At that moment the host loses power.

After restart, what is allowed to happen? It would be confusing if the index says the course is public but the course record still has the old title. It would be worse if the platform cannot tell which parts of the operation reached storage at all.

The naive model says that write() changes the file or database page in one indivisible moment. Actual storage paths are usually staged. The process changes memory, queues writes, records intent, asks the operating system or service to make some state durable, writes data pages later, and eventually records a checkpoint. A power cut can interrupt any boundary.

The system needs a story that survives the interruption. A journal or write-ahead log records enough ordered intent and decision information for recovery to make the state coherent again. The goal is not that every page was already in its final place at the instant of acknowledgement. The goal is that restart can determine which outcome it must produce.

Core Insight

Plain meaning:

Write down a recoverable plan before relying on scattered final updates, so a restart knows whether to finish the plan or leave it out.

In this scenario:

Before the course record and publication index are both written back, the storage system records that change J81 intends to update both and later records whether J81 became durable enough to count.

Technical name:

A journal or write-ahead log (WAL) is an ordered durable record used to recover a consistent state. A recovery boundary is the rule that separates changes recovery must honor from changes it must discard or undo.

This lesson uses a small generic model. A filesystem journal, a database WAL, and a copy-on-write system use different data structures and ordering rules. They share a foundational pressure: final state is often materialized in several places, while a crash needs one reliable answer about what happened.

Four pieces of a recoverable write

Keep four pieces separate. They may be close together in one product, but they are not the same job.

Piece Role What it lets recovery know
Intent record Describes the change that is being attempted. What must be replayed, completed, or checked.
Decision or commit record Says the operation crossed the chosen durable boundary. Whether the new outcome belongs to the accepted history.
Materialized pages The ordinary data and metadata pages used for fast reads. Current state when they are fully and validly written.
Checkpoint Records that earlier durable work is reflected in stable materialized state. How far recovery can start without replaying the entire history.

The journal is not a magical duplicate of all data. In some designs it records metadata changes, in others it records logical changes or page-level information, and in others it helps switch from an old root to a new one. The portable model is simpler: the journal provides a trustworthy ordering and decision boundary while final state may be written later.

A worked crash-and-restart trace

Use a simplified publication operation J81. The system wants the editor to see success only after the decision record is durably stored. Its ordinary pages may be written back later. That is one valid contract; real systems must document their own ordering and flush behavior.

J81 = set title "Storage Paths"; mark course-42 visible
Phase Journal state Materialized course record and index Meaning
0. Before write checkpoint through J80 old title; not visible Old state is authoritative.
1. Prepare intent for J81 exists in memory or a queue still old A crash may lose J81; no promise was made.
2. Persist intent durable intent for J81 still old Recovery knows the proposed change, but not yet whether to accept it.
3. Commit durable decision for J81 still old The new outcome is now part of the recovery boundary; success may be acknowledged in this model.
4. Write back J81 still durable title page new; index page may still be old Pages can be temporarily uneven because recovery has the journal.
5. Checkpoint J81 is covered by a durable checkpoint both pages new Recovery no longer needs J81 to reconstruct this operation.

The input is the editor’s publish request. The transition is from the old pages to a durable journal decision and then to page writeback. The intermediate state at phase 4 is important: one page can be new while another is old. The output after a clean run is a visible course with its new title. The naive failure would be to treat phase 4 as a finished operation without a journal; after a crash, the system could expose a half-published course with no reliable way to choose an outcome.

Now walk through three crashes.

Crash A: after durable intent, before the durable decision

The restart sees that J81 was being prepared but finds no durable record that it crossed the commit boundary. In this simple model, recovery discards or undoes the incomplete work and keeps the old title and visibility state. The editor did not receive a success acknowledgement, so this outcome matches the promise.

Crash B: after the durable decision, before any page writeback

The pages still look old. Recovery reads the committed journal entry, replays or completes J81, and materializes both required updates. The editor may have seen success before the power cut, and the restart now makes that success true in the ordinary queryable state.

Crash C: after one page writes back, before checkpoint

The title page may already be new while the visibility index is old. Recovery does not trust the pages as a complete story by themselves. It uses the committed journal entry to finish or validate the operation, then reaches the same coherent new state as Crash B. The checkpoint was not yet durable, so the journal remains the recovery source for J81.

Check: In this model, why is a durable intent record alone not enough to show the editor a successful publish?

Think first, then reveal.

Answer: Intent says what the system planned, not that it chose to make the new state part of its accepted history. A crash after intent but before the durable decision should be allowed to leave the old state in place. The acknowledgement must match the stronger boundary, not the earliest record written.

The acknowledgement is a local promise

The previous lesson treated a replicated acknowledgement as evidence about several nodes. Here, zoom in on one node. Its acknowledgement should still mean something precise: under the stated local storage contract, recovery will honor this operation after a process or host crash.

This does not mean every layer has finished work. Page caches can still contain dirty data, a filesystem may still queue writes, and replicas can still be catching up. It means the system has placed enough information across its trusted durability boundary to recover a coherent result.

That phrase—trusted durability boundary—deserves care. A call returning to application code is not automatically proof that data survived power loss. The promise depends on the API used, whether writes were flushed or synchronized as required, the device or remote service contract, and the software’s journal ordering. Treat “acknowledged” as a sentence that needs a subject and a condition:

Acknowledged by whom?
Durable where?
Recoverable after which failure?

For example, “the application handed bytes to the kernel” is weaker than “the storage system durably recorded a committed journal decision.” Both can be useful events, but they justify different user-facing promises.

Check: A monitoring system says dirty pages are high and checkpoint age is growing, yet writes are still acknowledged. Does that automatically prove a bug?

Think first, then reveal.

Answer: Not automatically. If committed journal records are durable, delayed page writeback can be an expected part of the design. But growing dirty-page and checkpoint pressure can increase recovery work and consume journal space. Check that the intended journal durability and checkpoint progress remain healthy rather than assuming pages must be clean for every acknowledged write.

Checkpoints make recovery bounded

Without checkpoints, a correct system could replay a very long history after every crash. A checkpoint records that a prefix of durable work is now safely represented in stable materialized state. Recovery can start after that boundary, using the journal only for later entries.

journal:    [J78] [J79] [J80] | checkpoint | [J81] [J82]
recovery:                         start here ────────→

Checkpoints improve restart time and manage journal growth. They have a trade-off: making data pages stable can create background I/O, contention, and latency pressure. Rushing a checkpoint cannot violate the ordering rules that make recovery correct; delaying it too long creates more work after a crash. The interesting question is not “should we checkpoint?” but “how much unfinished durable history can this system safely and economically carry?”

Trade-offs and limits

Journaling and write-ahead logging improve crash consistency by turning a scattered update into a recoverable sequence. They cost additional writes, ordering barriers, storage space, and recovery or checkpoint work. They do not fix every problem:

Useful signals reveal the boundary under pressure:

The goal is not zero recovery work. The goal is known recovery work that leads to a coherent state.

Common confusions

Confusion: A journal is only a performance optimization

Why it is tempting:

Journal writes are often discussed alongside batching and sequential I/O, which can improve performance.

Better model:

Its central role is correctness after interruption. It gives recovery an ordered record and a decision boundary when final pages are incomplete or uneven.

Confusion: A returned write means every final page is already durable

Why it is tempting:

The application sees one success result and naturally imagines one completed physical action.

Better model:

The success can be backed by a durable journal decision while ordinary pages remain dirty. The valid promise is recoverability, not necessarily that all representation layers are already clean.

Confusion: Crash recovery and replica agreement are the same problem

Why it is tempting:

Both use ordered history and durable records.

Better model:

Local recovery asks what one node can reconstruct after a crash. Replication asks which history several nodes may jointly promise. A system often needs both, but each has its own boundary and signals.

Practice: choose the recovery boundary

A course editor uploads a new package and changes the course manifest to point to it. The package object is stored separately from the manifest. The product must never show a manifest that points to a missing package; it is acceptable for a completed upload to remain hidden after a crash until the editor retries publishing.

Describe a small recoverable publication plan. State:

  1. what intent and decision you would record;
  2. when the editor may receive success;
  3. what recovery does if the host crashes before or after that decision; and
  4. one trade-off and one signal to monitor.

Model answer: First make the package object durably available under a versioned key. Record an intent to move the manifest from its old package key to the new key, then durably record the publication decision only after the new object’s availability has been verified. Acknowledge the editor after that decision crosses the local durability boundary. If the host crashes before it, recovery leaves the old manifest active and the uploaded object may remain unreferenced for later cleanup. If it crashes after it but before the manifest page is written back, recovery replays or completes the manifest change. This trades extra journal and verification work for no dangling manifest. Monitor journal flush failures, manifest/object verification errors, checkpoint age, and orphaned uploaded-object count.

Resources

Key Takeaways

  1. Intent, durable decision, materialized pages, and checkpoints are separate stages of a recoverable write.
  2. An acknowledgement should name a recovery boundary: after a crash, the system can honor the accepted outcome even if page writeback was incomplete.
  3. Journals make recovery coherent, not effortless; checkpoint and writeback pressure reveal the cost of carrying unfinished history.
PREVIOUS Replication, Logs, and Storage Consistency NEXT The Storage I/O Path from Syscall to Device or Service