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.

Intermediate → Advanced180–240 minutesWAL/durability observability labCurrent patched PostgreSQL 18.xCore PostgreSQL only; host utilities used where explicitly labeledOwner connection for SQL labs; pg_monitor/superuser only where statedCrash injection uses a separate disposable local cluster on port 55433No managed-service or paid dependencyLast reviewed: August 2026

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.

01

Distinguish synchronous_commit from fsync and wal_sync_method.

02

Explain local, off, remote_write, on, and remote_apply acknowledgement points and when remote modes matter.

03

Use SET LOCAL synchronous_commit for a transaction-scoped asynchronous-commit lab without changing cluster-wide safety.

04

Inspect configuration context/source before attempting any durability setting change.

05

Explain why fsync=off is qualitatively riskier than synchronous_commit=off and why wal_sync_method is platform-specific.

Safety boundary

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.

sql · inspect the current commit mode and replication context
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.

sql · create disposable telemetry data
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());
sql · synchronous local commit
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;
sql · asynchronous acknowledgement for the next transaction only
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.

psql · psql timing is local observation only
\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.

Wrong approach

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.

sql · inspect method and host utility
SHOW wal_sync_method;SHOW fsync;
shell · optional host-level test on a disposable/test host
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.

sql · inspect WAL I/O accounting
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.

sql · cleanup
DROP TABLE IF EXISTS app.ch12_telemetry;

Check your understanding

  1. Why is synchronous_commit=off safer than fsync=off?
  2. When does remote_apply differ meaningfully from on?
  3. Why use SET LOCAL synchronous_commit instead of a global change for one workload?
  4. What does wal_sync_method control?
  5. 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.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.