{"post":{"slug":"write-ahead-logging-explained-2026","title":"Write-Ahead Logging Explained: How Databases Survive Crashes","excerpt":"Your database promised the write was durable, then the machine lost power. Write-ahead logging is the reason the data is still there when it comes back.","category":"code","date":"August 13, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">A</span> transaction commits. Your application gets an acknowledgement and moves on. Two seconds later the power fails. When the machine comes back, is the data there?\n\nIt should be, and the mechanism that makes it so is write-ahead logging — one of those ideas that sounds almost too simple to be the answer. Before modifying any data, write down what you are about to do. Make sure that record is genuinely on disk. Only then touch the data itself. If you crash at any point, the log tells you what was in progress and what to do about it.\n\n## What changed in 2026\n\n- **Managed databases hid the knobs but not the consequences.** Most teams no longer tune WAL settings directly, which makes it easier to be surprised by the behaviour they inherit — particularly around replication lag and storage growth.\n- **Change data capture went mainstream.** Reading the WAL to stream changes into other systems moved from a specialist technique to a default integration pattern, which means the log now has consumers beyond the database itself.\n- **Storage economics shifted the defaults.** Faster commit latency on modern SSDs made synchronous commit affordable for workloads that previously felt obliged to weaken it.\n- **Point-in-time recovery became an expectation.** Continuous archiving of log segments is standard in managed offerings, and \"restore to 14:32 yesterday\" is now a normal request rather than an exotic one.\n\n## The core mechanism\n\nThe ordering is the whole idea. Consider updating a row:\n\n1. Write a log record describing the change — the transaction, the page, the before and after.\n2. Flush that record to durable storage.\n3. Acknowledge the commit to the client.\n4. Modify the actual data page, whenever convenient. Often much later, in memory first.\n\nStep 2 before step 3 is what makes the promise true. Step 4 being lazy is what makes it fast.\n\nThe performance win is not obvious at first glance — you are writing more, not less. It works because log writes are sequential appends to one file, while data pages are scattered across the disk. Turning many random writes into one sequential write and deferring the random part is the trade, and it is a very good one.\n\nThe dirty pages get written out eventually, in the background, in an order the storage layer likes. If the machine crashes before that happens, the log has everything needed to redo the work.\n\n## Durability means fsync\n\nThe subtlety that catches people: writing to a file does not put data on a disk. It puts data in an operating system buffer, which is flushed on the OS's schedule. A crash between those points loses it, and your application already told the user the write succeeded.\n\nDurability requires an explicit flush — `fsync` or an equivalent — and waiting for it to return. That wait is real; it is the single largest contributor to commit latency in most transactional workloads.\n\nThis is what a \"synchronous commit\" setting controls. Turn it off and commits return as soon as the log record is in memory, which is dramatically faster and means a crash can lose the last fraction of a second of transactions. Whether that is acceptable is a business question, not a technical one. Losing analytics events is different from losing payments, and the honest version of this decision names the window and the data rather than treating it as a generic throughput setting.\n\nGroup commit softens the trade without weakening it: batch several transactions into one flush, amortising the expensive part across all of them. Most databases do this automatically under concurrent load, which is why write throughput often improves with more concurrent writers rather than less.\n\n## Checkpoints, replication, and recovery\n\n**Checkpoints** are what stop the log from being infinite. At a checkpoint the database flushes dirty pages and records that everything before this point is safely in the data files. Recovery then only needs to replay from the last checkpoint rather than from the beginning of time. Frequent checkpoints mean fast recovery and more steady I/O; infrequent ones mean less routine work and a longer restart. That is the entire tuning tradeoff.\n\n**Replication** falls out almost for free. A replica that receives the log stream and applies it ends up with an identical database — the WAL is already a precise, ordered description of every change. This is why physical replication is typically the cheapest form to operate, and why replication lag is measured in log position rather than in rows. [Read replicas explained](/blog/read-replicas-explained-2026) covers the consistency implications.\n\n**Point-in-time recovery** is the same trick with a time axis. Keep a base backup plus every log segment since, and you can replay to any moment. Recovering from an accidental `DELETE` at 14:31 means restoring the base and replaying to 14:30 — which is the only remedy for a mistake that replication faithfully copied to every replica.\n\n## Common mistakes\n\n- **Assuming replication is a backup.** It replicates your mistakes instantly. Backups plus archived logs are what let you go back.\n- **Disabling synchronous commit without naming the acceptable loss window.** A throughput decision quietly becoming a durability decision.\n- **Not monitoring log growth.** A stalled replica or an inactive replication slot prevents log recycling, and the volume fills. This is a common and entirely avoidable outage.\n- **Checkpointing too aggressively.** Constant flushing produces I/O spikes that show up as latency for everyone.\n- **Trusting storage that lies about flushes.** Some consumer drives and virtualised layers acknowledge a flush before it completes, which silently voids the guarantee.\n- **Forgetting the log needs its own headroom.** Bulk operations generate far more log than their data size suggests.\n\n## FAQ\n\n**Is SQLite's WAL mode the same thing?**\nSame principle, different scale. It brings sequential-append durability and lets readers proceed during writes, which is the main practical benefit — see [Postgres vs SQLite](/blog/postgres-vs-sqlite-2026) for where each fits.\n\n**Why is my log directory so large?**\nUsually a replication slot or archiving process that has stopped consuming. The database keeps segments until every consumer has them, so one stuck reader pins the whole series.\n\n**Does this apply to NoSQL databases?**\nBroadly yes. Most durable stores use a log-first design under some other name — commit log, journal, oplog. The ordering guarantee is the same idea.\n\n**How does it affect write performance?**\nIt improves it, counter-intuitively, by converting random writes to sequential ones. The flush wait is the cost, and group commit amortises it under concurrency.\n\n## Where to go next\n\nFor how the log feeds other systems, read [read replicas explained](/blog/read-replicas-explained-2026). For the storage layer that determines how expensive those flushes are, [database indexing explained](/blog/database-indexing-explained-2026) covers what else competes for the same I/O, and [database sharding explained](/blog/database-sharding-explained-2026) covers what happens to durability guarantees once one machine is no longer enough.","hue":312,"metaTitle":"Write-Ahead Logging Explained: Crash-Safe Databases","metaDescription":"How write-ahead logging makes database writes durable, why fsync is the real guarantee, and how the WAL powers replication and point-in-time recovery.","keywords":["write ahead logging","wal database","database durability","fsync durability","postgres wal","crash recovery database","checkpoint database","transaction log 2026"],"tldr":["**Log the intent before changing the data** — recording what you are about to do, and flushing that record, is what makes a crash recoverable.","**Durability is a disk flush, not a write** — an unflushed write sits in an OS buffer and disappears with the power.","**The WAL is why replication works** — a stream of changes is exactly what a replica needs, so the crash-safety mechanism doubles as the replication mechanism.","**Checkpoints bound recovery time** — without them the log grows forever and restart replays everything since the beginning.","**Skip:** disabling synchronous commit to chase write throughput unless you can genuinely afford to lose recent transactions."],"readTime":"5 min read","wordCount":1136},"related":[{"slug":"acid-transactions-explained-2026","title":"ACID transactions explained in 2026: what the guarantees really mean","excerpt":"ACID is four guarantees that make database transactions reliable, but each property has nuance that matters in distributed systems. Here is the real story.","category":"code","date":"April 8, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":322},{"slug":"mvcc-explained-2026","title":"MVCC Explained: How Readers Stop Blocking Writers","excerpt":"Your database serves a consistent snapshot to every transaction without locking anything. The trick is keeping several versions of every row, and it has a cost.","category":"code","date":"August 14, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":301},{"slug":"read-replicas-explained-2026","title":"Read Replicas Explained: Scaling Reads in 2026","excerpt":"Most applications are read-heavy long before they are write-heavy. Read replicas copy data to extra nodes so queries scale out without the complexity of sharding or touching the write path at all.","category":"code","date":"August 8, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":314}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"wifi-sensing-explained-2026","title":"Wi-Fi Sensing Explained: Your Router Sees Motion","excerpt":"Wi-Fi sensing detects movement and breathing by reading how bodies disturb radio signals. Here is how it works, what it can and cannot detect, and the privacy questions.","category":"tech","date":"August 13, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":246},"older":{"slug":"able-account-explained-2026","title":"ABLE Accounts: Saving Without Losing Benefits","excerpt":"ABLE accounts let people with disabilities save above the asset limits that would otherwise disqualify them from means-tested benefits.","category":"finance","date":"August 12, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":316}}