Separate client commit acknowledgement from the storage guarantees underneath it, and test only reversible transaction-level durability tradeoffs while treating fsync as a cluster-safety boundary.
synchronous_commit, fsync, wal_sync_method, and Durability/Latency Tradeoffs
Match transaction criticality to the correct commit acknowledgement contract while keeping storage crash-safety settings separate from per-transaction latency choices.
Learning outcomes
ServiceHub has two transaction classes: customer payment
capture, where losing an acknowledged commit is unacceptable,
and disposable telemetry batches that can be regenerated. An
engineer proposes fsync=off for both because a
benchmark became faster. That collapses two very different
tradeoffs into one dangerous switch.
Distinguish synchronous_commit from fsync and wal_sync_method.
Explain local, off, remote_write, on, and remote_apply acknowledgement points and when remote modes matter.
Use SET LOCAL synchronous_commit for a transaction-scoped asynchronous-commit lab without changing cluster-wide safety.
Inspect configuration context/source before attempting any durability setting change.
Explain why fsync=off is qualitatively riskier than synchronous_commit=off and why wal_sync_method is platform-specific.
This lesson never asks you to disable fsync on the established ServiceHub cluster. synchronous_commit can be changed per transaction; fsync and wal_sync_method are operator-level storage settings. If you benchmark dangerous durability settings at all, use a separate throwaway cluster that can be rebuilt from external data.
1. synchronous_commit controls when success is reported
synchronous_commit asks: how far must WAL
processing progress before PostgreSQL returns success for this
transaction? With no synchronous standby configured, the most
important local distinction is on versus
off. With off, PostgreSQL may
acknowledge before the commit WAL record is durably flushed. A
crash can therefore lose a recent acknowledged transaction, but
recovery remains internally consistent—as though that
transaction had aborted.
SHOW synchronous_commit;SHOW synchronous_standby_names;SELECT name, setting, context, source, pending_restartFROM pg_settingsWHERE name IN ('synchronous_commit','fsync','wal_sync_method','wal_writer_delay')ORDER BY name;
2. Remote modes describe synchronous-replication acknowledgement points
When synchronous standbys are configured, PostgreSQL can wait
for progressively stronger remote states.
remote_write waits for the standby to write WAL to
its filesystem, on waits for durable standby flush,
and remote_apply waits until replay has made the
change visible to queries on the synchronous standby.
local waits only for local durable flush and does
not wait for synchronous replication.
| Mode | Primary local flush | Synchronous standby requirement | Typical implication |
|---|---|---|---|
off |
No wait | No wait | Small acknowledged-loss window after crash; cluster consistency preserved |
local |
Wait | No wait | Local durability without synchronous-replication wait |
remote_write |
Wait | Written to standby OS | Protects against standby PostgreSQL crash, not necessarily standby OS crash |
on |
Wait | Durably flushed by synchronous standby | Default synchronous-replication durability point |
remote_apply |
Wait | Flushed and replayed | Also waits for standby query visibility |
If synchronous_standby_names is empty, the remote
distinctions do not create remote guarantees; all non-off values
provide the same local synchronization level.
Do not confuse a synchronous commit with “one fsync per transaction.” PostgreSQL can group concurrently committing transactions so that one WAL flush satisfies several waiters. This is one reason commit latency and throughput change with concurrency, even when no durability GUC changes. It is also why a single-client microbenchmark does not predict a busy production service.
With synchronous_commit=off, PostgreSQL's WAL
writer eventually flushes the commit record. The server
documentation bounds the possible delay in terms of the
WAL-writer cadence rather than promising immediate durability.
That makes asynchronous commit a business-loss-window decision,
not simply a faster flavor of the same guarantee.
3. Reversible lab: asynchronous commit for regenerable events
Create a disposable telemetry table and compare commit paths
using SET LOCAL. Do not publish benchmark numbers
from this lab as universal results: storage, group commit,
client latency, batching, and concurrent load dominate commit
behavior.
DROP TABLE IF EXISTS app.ch12_telemetry;CREATE TABLE app.ch12_telemetry ( sample_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, work_order_id bigint NOT NULL, sample jsonb NOT NULL, created_at timestamptz NOT NULL DEFAULT clock_timestamp());
BEGIN;SET LOCAL synchronous_commit = on;INSERT INTO app.ch12_telemetry (work_order_id, sample)SELECT g, jsonb_build_object('temperature', 20 + (g % 15), 'source', 'replayable-demo')FROM generate_series(1, 1000) AS g;COMMIT;
BEGIN;SET LOCAL synchronous_commit = off;INSERT INTO app.ch12_telemetry (work_order_id, sample)SELECT 1000 + g, jsonb_build_object('temperature', 20 + (g % 15), 'source', 'replayable-demo')FROM generate_series(1, 1000) AS g;COMMIT;
With psql, enable \timing and repeat
controlled batches if you want a local observation. A one-run
difference proves little. The important semantic difference is
the acknowledgement point, not the benchmark.
\timing onSHOW synchronous_commit;SELECT count(*) FROM app.ch12_telemetry;
4. fsync protects crash consistency of the cluster
fsync=on makes PostgreSQL request durable storage
of data and WAL through fsync() or equivalent
mechanisms. Turning it off can leave data files and WAL in an
ordering/state from which a power or operating-system crash
cannot be recovered safely. This is not merely a wider
acknowledged-loss window; it can produce unrecoverable
corruption.
Disabling fsync on a durable production cluster because “we have enterprise SSDs” is not a sound safety argument. PostgreSQL specifically warns that high-quality hardware alone is not sufficient justification. If the data can be recreated, benchmark on a throwaway cluster; otherwise leave the durability contract intact.
If fsync has been off and you later turn it back
on, PostgreSQL documentation requires an explicit step that
forces previously modified kernel buffers to durable storage
before you rely on crash safety again. That transition is an
operational procedure, not a casual reload.
5. wal_sync_method is how PostgreSQL asks the OS to force WAL
wal_sync_method selects the operating-system
mechanism used to force WAL updates to durable storage.
Available methods vary by platform. PostgreSQL documents them as
intended to provide the same reliability except for
platform/cache subtleties; their performance can differ. The
server utility pg_test_fsync exists specifically to
compare methods on the host.
SHOW wal_sync_method;SHOW fsync;
pg_test_fsync
Do not run storage microbenchmarks on a saturated production volume and then change the sync method without validating crash-safety assumptions for the filesystem, device cache, hypervisor, and storage controller.
6. WAL I/O statistics can separate write from sync work
PostgreSQL 18 records WAL write and fsync counts in
pg_stat_io. If WAL I/O timing collection is
enabled, timing fields can help explain where commit latency
accumulates. Timing counters are meaningful only for the
interval in which timing was enabled.
SELECT backend_type, object, context, writes, write_time, fsyncs, fsync_time, stats_resetFROM pg_stat_ioWHERE object = 'wal'ORDER BY backend_type, context;
7. Production decision matrix
Use transaction criticality to choose the acknowledgement contract. Financial state, authorization changes, and irreversible external side effects usually need durable acknowledgement. Regenerable telemetry, caches, or ephemeral progress markers may tolerate asynchronous local commit if the business explicitly accepts a small crash-loss window. Keep the setting as narrow in scope as possible and ensure application retry/idempotency logic matches that choice.
DROP TABLE IF EXISTS app.ch12_telemetry;
Check your understanding
- Why is synchronous_commit=off safer than fsync=off?
- When does remote_apply differ meaningfully from on?
- Why use SET LOCAL synchronous_commit instead of a global change for one workload?
- What does wal_sync_method control?
- Why should commit-latency numbers from this lab not be copied into a capacity plan?
Review the answers
Asynchronous commit can lose recent acknowledged transactions but preserves cluster consistency; disabling fsync can make crash recovery unsafe. remote_apply matters when synchronous replication is configured and adds a wait for replay/visibility on the standby. SET LOCAL limits the durability tradeoff to one transaction. wal_sync_method selects the OS mechanism used to force WAL. Commit latency depends strongly on storage, group commit, client concurrency, batching, and topology, so local numbers are not portable constants.
Authoritative references
Durability behavior depends on PostgreSQL version, storage semantics, configuration source, replication topology, and the exact failure mode. The references below are the primary source for the mechanisms used in this lesson.