Write-ahead logging
Should we trade durability for speed?
The idea in 30 seconds
Two settings make writes much faster and are not the same thing. synchronous_commit = off can lose the last fraction of a second of commits in a crash, but never corrupts anything, and can be set per transaction. fsync = off can corrupt the whole database beyond repair after a power failure. The first is a business decision; the second almost never is.
Helps to know first: How a table is stored on disk
On this page
The situation
An event-ingestion service writes one row per incoming event, each in its own transaction, and it is falling behind at peak. An AI assistant opened a pull request.
Review taskSpeed up ingestion
Pull request: “Commits are the bottleneck. Turn off the disk syncing.”
# postgresql.conf
fsync = off
synchronous_commit = offWould you approve it? Write the review you would leave.
Your call
Model review
Request changes. These are two very different risks, and one of them is not acceptable for a database that holds anything you cannot rebuild.
1. fsync = off can destroy the database. With it off, PostgreSQL no longer forces anything to permanent storage: not the log, not the data files. After a power failure or operating system crash, the data files can be left inconsistent in ways the log cannot repair, and the documentation’s word is “unrecoverable”. It is meant for databases you can recreate from scratch, like a one-off bulk load, and the documentation says good hardware alone does not justify it.
2. synchronous_commit = off risks something smaller and well defined. A commit returns before its log record is flushed. If the server crashes, the last fraction of a second of commits can be lost, but recovery replays the log in commit order up to the last flushed record, so the database is always consistent. On our test machine it made a single-row commit about 14 times faster (31 µs down to 2.2 µs).
3. It does not need to be server-wide. Asynchronous commit can be set per session or per transaction. Use it only for the ingestion path, where losing the last few events in a crash is acceptable, and keep everything else (orders, payments, accounts) fully durable:
BEGIN;
SET LOCAL synchronous_commit = off;
INSERT INTO events (...) VALUES (...);
COMMIT;4. Batching is often the bigger win. The cost here is one log flush per event. Inserting 100 events per transaction pays that flush once per 100, with no change to durability at all.
What I would ask for: remove fsync = off. Batch inserts if the producer allows it. If that is not enough, use SET LOCAL synchronous_commit = off for event inserts only, and write down that a crash can lose the most recent events.
Compare it with yours. Did your review catch the main problems?
How to decide
Never turn off fsync on a database you cannot recreate from scratch. It risks corruption, not just loss.
Use synchronous_commit = off where losing the last moments of data is acceptable, and set it only where that is true: per transaction or per session, not for the whole server.
Try batching first. Fewer, larger transactions reduce flushes without weakening any guarantee.
Know what your storage really does on a flush. Measure commit latency on the production hardware; on our laptop the honest flush cost 145 times the default.
Check yourself
What is the worst case after a crash with
synchronous_commit = off, and withfsync = off?Show answer
With asynchronous commit, the most recent transactions are lost but the database is consistent. With
fsyncoff, the data files can be corrupted beyond repair.How would you make only the ingestion inserts asynchronous?
Show answer
SET LOCAL synchronous_commit = offinside those transactions, orSET synchronous_commit = offin the ingestion service’s sessions. Other work keeps the server default.Why does batching help without risking any data?
Show answer
The commit cost is a log flush per transaction. Putting many inserts in one transaction pays one flush for all of them, and each commit is still fully durable.
Finished reading?
Saved in this browser only.
Sources
Where each claim on this page comes from.
- 1.PostgreSQL documentation: 28.4 Asynchronous CommitPrimary· §28.4 Asynchronous Commit
Asynchronous commit risks losing the most recent transactions in a crash, not data corruption; recovery replays WAL up to the last flushed record in commit order; it can be chosen per transaction.
- 2.PostgreSQL documentation: 19.5 Write Ahead LogPrimary· §19.5 Write Ahead Log: fsync
Turning fsync off can cause unrecoverable data corruption after a power failure or system crash; it is only advisable when the whole database can easily be recreated; high-quality hardware alone is not a justification.
Go further
What to read next, and why it is worth the time.
- 1.PostgreSQL documentation: 28.4 Asynchronous CommitPrimary· §28.4
Explains exactly how much can be lost with asynchronous commit and why it can never leave the database inconsistent.
Applies to PostgreSQL 18. Draft: not yet fact-checked end to end.