Enable data checksums online
PostgreSQL 19 enables and disables data checksums on a running cluster — steps, I/O cost, throttling, and progress monitoring
PostgreSQL 19 is still in Beta
As of 2026-08, PostgreSQL 19 has not reached GA. Function signatures, states, and view columns below follow the PostgreSQL 19 documentation; re-check the final release notes before relying on them in production.
Data checksums store a checksum value in every data page, written when the page is flushed and verified when it is read back — the primary mechanism for detecting storage and file-system corruption. Since PostgreSQL 18, initdb enables them by default for new clusters. Clusters initialized on older major versions often still run without them, which is exactly the gap this page covers.
Before PostgreSQL 19: pg_checksums required downtime
Through PostgreSQL 18, changing the checksum state of an existing cluster meant pg_checksums, and pg_checksums requires the server to be shut down cleanly. Enabling checksums rewrites every relation block in place, so on a multi-terabyte cluster the maintenance window is long, and the cluster must not be started mid-operation. For always-on systems this made retroactively enabling checksums nearly impossible to schedule.
Enabling checksums online
PostgreSQL 19 adds SQL functions that flip checksums on a running cluster while clients keep working, described in Section 28.2, Data Checksums:
-- check current state: off / inprogress-on / on / inprogress-off
SHOW data_checksums;
-- start enabling; cost_delay / cost_limit throttle the rewrite
SELECT pg_enable_data_checksums(cost_delay => 10, cost_limit => 1000);What happens after the call:
- The cluster state becomes
inprogress-on. From this point checksums are written on page flush but not yet verified on read. - A launcher starts one background worker per database, which walks every relation and marks each page dirty so it is rewritten with a checksum.
- When all databases finish, the state automatically switches to
onand read-time verification begins.
Prerequisites and stalls to know about:
- The process consumes two background worker slots — make sure
max_worker_processeshas headroom. - It waits for all open transactions to finish before starting, and for each database it waits for pre-existing temporary tables to be dropped. Applications with long-lived temp tables can block completion indefinitely; terminating those connections may be necessary.
- If the cluster stops while in
inprogress-on, there is no resume: after restart, re-runpg_enable_data_checksums()and the rewrite starts over. Plan it for a window without reboots or failovers.
I/O cost and progress monitoring
Enabling checksums rewrites every page in the cluster — dirty page flushes plus WAL for the rewrites — so the I/O impact is substantial. The cost_delay and cost_limit arguments of pg_enable_data_checksums() apply the same cost-based throttling model as vacuum; on production systems, start with conservative values and watch latency.
Progress is visible in pg_stat_progress_data_checksums: one row for the launcher (tracking databases_total / databases_done) and one row per worker (tracking relations_total / relations_done and blocks_total / blocks_done for the current relation):
SELECT pid, datname, phase,
databases_total, databases_done,
relations_total, relations_done,
blocks_total, blocks_done
FROM pg_stat_progress_data_checksums;The phase column distinguishes enabling, disabling, waiting on barrier (backends acknowledging the state change), and waiting on temporary tables — the latter two explain most "stuck" appearances. The processes also show up in pg_stat_activity with backend_type of datachecksums launcher / datachecksums worker.
Replication note from the documentation: when a standby receives the checksum state change in the WAL stream it forces a restartpoint, which blocks redo until finished and can induce replication lag — on synchronous standbys this also blocks the primary. Reducing max_wal_size before starting shortens that restartpoint.
Disabling checksums online
SELECT pg_disable_data_checksums();The state moves to inprogress-off (checksums still written, no longer verified) and settles to off once all backends acknowledge the change. No pages are rewritten, so there is no I/O surge, though checkpoints are still required. Disabling while an enable is in progress aborts the enable. If the cluster stops during inprogress-off, it comes back up with checksums off.
Hardware-accelerated checksum computation
The checksum stored in data pages is PostgreSQL's own FNV-1a-based algorithm rather than CRC — on x86-64 an AVX2-vectorized implementation is selected at runtime when available. CRC-32C protects WAL records instead, with runtime dispatch to SSE4.2 or AVX-512 instructions on x86 and the CRC32/PMULL extensions on ARMv8 (background on the implementation: digoal's commit walkthrough; WAL's use of CRC-32C is documented in Section 28.1, Reliability). On modern CPUs the steady-state CPU overhead of keeping checksums enabled is small; the dominant cost is the one-time rewrite when enabling, not day-to-day operation.
Interaction with backup verification
Checksums compose with the backup toolchain at two different layers:
pg_basebackupverifies page checksums while reading the cluster (unless--no-verify-checksumsis given); a checksum failure produces a non-zero exit status and is counted inpg_stat_database.checksum_failures. Enabling checksums therefore makes every base backup a full-cluster corruption scan for free.pg_verifybackupvalidates a finished backup against thebackup_manifestfile-level hashes. That catches corruption introduced in backup storage or transfer — a different failure domain from page checksums, which guard the live cluster.
Both belong in the verification routine described in backup, recovery, and PITR; surface checksum_failures in the dashboards from monitoring and logging.
When it is worth enabling
- Clusters initialized before PostgreSQL 18's default change that never had checksums on — now there is no downtime excuse.
- Compliance or integrity requirements that demand detection of silent storage corruption.
- Any system where
pg_basebackup's built-in verification doubles as a periodic corruption sweep.
Reasons to hold off are narrow: throwaway clusters, or storage stacks that already checksum end-to-end (e.g. ZFS) combined with a high risk tolerance. Note that only PostgreSQL-level checksums are verified by PostgreSQL's own tools. For more on PostgreSQL 19, see the release overview.
AI prompt: plan a checksum rollout
Help me plan enabling data checksums online on a PostgreSQL 19 production cluster. 1. Cluster facts: (fill in — data size, number of databases, max_worker_processes, synchronous standbys yes/no, typical write throughput) 2. Please: - Give exact commands: SHOW data_checksums, the pg_enable_data_checksums call with sensible cost_delay/cost_limit starting values for my size - List what can stall the process (long transactions, long-lived temp tables) and how to detect each with SQL - Write the pg_stat_progress_data_checksums monitoring query and explain launcher vs worker rows - Cover the standby restartpoint lag risk and whether I should lower max_wal_size first - Give the abort/rollback path, including what happens if the cluster restarts mid-way (inprogress-on does not resume) 3. Finish with a verification checklist: final SHOW data_checksums, pg_stat_database.checksum_failures baseline, and a pg_basebackup test run.
Last updated on