Knowledge Guide
HomeSystem DesignScalable Systems (Advanced Topics)

hard Group Commit & fsync Durability

Why durability is a disk-flush problem

A database calls a transaction durable the moment its commit record in the write-ahead log (WAL) is safely on stable storage — not merely written, but fsync'd, so it survives an OS crash or power loss. That single guarantee sets a hard physical ceiling on how fast you can commit: a durable commit cannot be acknowledged until a disk flush completes. Everything about commit performance is a fight against the cost of that flush.

The problem: one fsync per commit is brutally slow

A single fsync to durable storage costs roughly 0.5–10 ms depending on the device (a 7200-rpm disk pays about a rotation; a consumer SSD without power-loss protection a few ms; an enterprise SSD or a battery-backed cache far less). If every transaction does its own fsync before returning, commit throughput is capped at one commit per flush:

ceiling = 1 / fsync_time
  fsync = 10 ms  → ~100   commits/sec
  fsync =  5 ms  → ~200   commits/sec
  fsync =  1 ms  → ~1000  commits/sec
  fsync = 0.5ms  → ~2000  commits/sec

So a naive per-transaction-fsync database tops out around ~100–2000 commits/sec regardless of how many CPU cores or client connections you throw at it. The bottleneck is not compute; it is the serialized wait on the disk. A hundred threads each doing their own 5 ms fsync still only get ~200 durable commits/sec between them, because the flushes queue up.

The fix: group commit batches many commits into one fsync

The insight: an fsync flushes everything currently in the WAL buffer, not just one transaction's record. So while one fsync is in flight, let other committing transactions append their commit records to the same buffer. When the flush returns, it has made all of them durable at once — and every one of them can be acknowledged. This is group commit.

Forty concurrent transactions append their commit records to one WAL buffer; a single fsync makes all of them durable at once
Forty concurrent transactions append their commit records to one WAL buffer; a single fsync makes all of them durable at once

Traced throughput arithmetic (fsync = 5 ms)

Per-transaction fsyncGroup commit
fsyncs per second1000 ms / 5 ms = 2001000 ms / 5 ms = 200
commits per fsync1~40 (whatever accumulated during the 5 ms window)
commit throughput200 × 1 = 200 / sec200 × 40 = 8,000 / sec
latency per commit~5 ms (one fsync)~5 ms (still one fsync)

The crucial property: group commit raises throughput without raising latency. Each transaction still waits about one fsync — it just no longer waits alone. And it is self-tuning: the busier the system, the more transactions pile into each batch, so throughput climbs exactly when you need it while latency stays pinned near one flush. This is why real databases (PostgreSQL, MySQL/InnoDB, and others) do group commit automatically — it is close to a free lunch, trading a few ms of extra commit latency under light load for order-of-magnitude throughput under heavy load.

The durability knob: trading a data-loss window for speed

Group commit keeps full durability. If even one fsync of latency per commit is too much, the next lever is to relax when the flush must happen. In PostgreSQL that is synchronous_commit=off: the commit returns to the client before the WAL is flushed, and the WAL writer flushes shortly after (within a small, bounded delay). The commit-side fsync disappears from the critical path, so throughput and latency both improve dramatically.

What you give up is precisely defined: a crash loses only the transactions committed in the last few hundred milliseconds — the ones acknowledged but not yet flushed. Critically, the database is not corrupted. The WAL is still written in order and recovery still produces a fully consistent database; you have simply lost the most recent tail of commits. This is a bounded data-loss window, and for many workloads (analytics ingest, metrics, "I can replay the last second") it is a fine trade.

Three durability settings: fsync-per-commit loses nothing; synchronous_commit=off loses a bounded window but stays consistent; fsync=off risks corruption
Three durability settings: fsync-per-commit loses nothing; synchronous_commit=off loses a bounded window but stays consistent; fsync=off risks corruption

fsync = off is a completely different, dangerous setting

Do not confuse relaxed sync with turning fsync off entirely. synchronous_commit=off still fsyncs the WAL — just slightly later — so ordering and consistency hold. Setting fsync=off tells the engine to never force pages to disk at all. The OS is then free to reorder and delay writes, so a crash can leave the data files and the WAL in mutually inconsistent states. The failure mode is no longer "lose the last second of commits" — it is a corrupted database that may not recover at all. The rule of thumb: relaxed sync risks recent-commit loss; fsync=off risks the whole database.

The same knob in MySQL/InnoDB

innodb_flush_log_at_trx_commit exposes the identical trade-off with three settings:

ValueBehaviorWhat a crash costs
1 (default)Write + fsync WAL at every commitNothing — full durability
2Write to OS cache at commit; fsync once per secondmysqld crash: nothing (OS still has it). OS/power crash: ~1 s of commits
0Write + fsync only once per secondAny crash, including mysqld: ~1 s of commits

Settings 0 and 2 are the bounded-loss analogues of synchronous_commit=off; all three keep the database consistent. None of them is the "corruption" knob — that would be disabling innodb_flush_method's durability or lying hardware caches.

Pitfalls

Judgment — durability vs throughput/latency

These are three levers on one trade-off, and they are not mutually exclusive — the senior move is to reach for the free one first:

The decision: start with group commit (always on). If commit latency still hurts, the fork is can I lose the last few hundred ms? If yes → relaxed sync (cheap, software-only). If no → buy durable-cache hardware (keeps the guarantee, costs money). Reaching for fsync=off is never the answer — it trades a durability guarantee for a corruption risk, which is not a trade a serious system makes.

Takeaways


Synthesized from the PostgreSQL documentation (WAL Configuration, synchronous_commit, fsync), the MySQL InnoDB reference (innodb_flush_log_at_trx_commit), Gray & Reuter, Transaction Processing (group commit), and Kleppmann, Designing Data-Intensive Applications (durability, replication). Re-authored and diagrams hand-authored (SVG) for this guide.

🤖 Don't fully get this? Learn it with Claude

Stuck on Group Commit & fsync Durability? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Group Commit & fsync Durability** (System Design) and want to truly understand it. Explain Group Commit & fsync Durability from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Group Commit & fsync Durability** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Group Commit & fsync Durability** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Group Commit & fsync Durability** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes