A read-only preset, like block_sizeSHOW data_checksums tells you whether the cluster has page checksums, and that’s the only interaction the GUC offers. But unlike block_size, this one has a thirteen-year history that’s still being written, and the history is the post.

When checksums are on, every data page carries a checksum that’s written when the page is written and verified every time it’s read back. A mismatch means the page changed underneath PostgreSQL — bit rot, a failing disk, a storage layer that lied about a write — and the server raises an error instead of handing you silently corrupted data. Only data pages are covered; internal structures and temp files aren’t. A failed verification bumps checksum_failures in pg_stat_database, which is the column you should be alerting on whether or not you remember turning checksums on.

The thirteen-year switch-flip

Checksums arrived in PostgreSQL 9.3 (2013), off by default. The hesitation was performance: verifying a checksum on every page read and recomputing it on every write isn’t free, and in 2013, with the hardware and the WAL machinery of the day, the overhead was deemed too much to impose on everyone.

The default stayed off for a decade while two things happened. The hardware got faster, and every serious PostgreSQL operator turned checksums on anyway. The major managed providers enabled them. pgBackRest came to depend on them for backup verification. By the time Greg Sabino Mullane proposed flipping the default in 2024, his argument was essentially that the project was the last holdout against its own de-facto standard — you’d be hard-pressed, he noted, to find a production system that didn’t already have them on. PostgreSQL 18 flipped it. A fresh initdb now enables checksums; you opt out with --no-data-checksums if you have a specific reason, and almost nobody does.

The capability to change the setting after initdb arrived incrementally too. Originally checksums were an initdb-only, forever decision. PostgreSQL 12 added pg_checksums, which can enable or disable them on an offline cluster. And PostgreSQL 19 is bringing online enable/disable — flipping checksums on a running cluster via a background worker that dirties every page so it gets a checksum on its next write, no downtime required. The thirteen-year arc runs from “decide at initdb and live with it forever” to “toggle it whenever you like on a live system.”

What this means for you in practice

If you’re initializing a new PG 18 cluster, you already have checksums; leave them on. If you’re on 14 through 17 and your cluster predates someone thinking about this, check SHOW data_checksums — if it says off, schedule a maintenance window and run pg_checksums --enable, because the overhead on modern hardware is in the low single digits of percent and the protection against silent corruption is worth vastly more than that.

The one place this actively bites is pg_upgrade. The source and target clusters must agree on their checksum setting — both on or both off. Upgrade a pre-18 cluster that has checksums off onto a freshly-initialized PG 18 cluster that has them on, and pg_upgrade refuses. The fix is to make them match first: either enable checksums on the old cluster with pg_checksums --enable before upgrading, or initialize the new one with --no-data-checksums and turn them on afterward. Knowing this before you start the upgrade saves you a confusing failure halfway through.

There are two developer-only escape hatches worth naming so you recognize them: ignore_checksum_failure, which tells the server to proceed past a failed verification (for recovering data off a corrupted page, at the risk of propagating the corruption), and the broader caution that both belong only in a deliberate recovery operation, never in normal running.

SHOW data_checksums should say on. On PG 18 it does by default. On anything older, if it doesn’t, the project spent thirteen years concluding you want it on — and you can now have it on without the all-or-nothing-at-initdb bargain that made the decision feel heavy in the first place.