During its operation, PostgreSQL records changes to transaction log files, but it doesn't immediately flush them to the actual database tables. It usually just keeps the changes in memory, and returns them from memory when they are requested, unless RAM starts getting full and it has to write them out.

This means that if it crashes, the on disk tables won't be up to date. It has to replay the transaction logs, applying the changes to the on-disk tables, before it can start back up. That can take a while for a big, busy database.

For that reason, and so that the transaction logs do not keep growing forever, PostgreSQL periodically does a checkpoint where it makes sure the DB is in a clean state. It flushes all pending changes to disk and recycles the transaction logs that were being used to keep a crash recovery record of the changes.

This flush happens in two phases:

  • Buffered write()s of dirty shared_buffers to the tables; and
  • fsync() of affected files to make sure the changes really hit disk

Both of those can increase disk I/O load. Contention caused by these writes can slow down reads, and can also slow down flushing of WAL segments that's required in order to commit transactions.

It's been a longstanding challenge, but it's getting worse as we see systems with more and more RAM so they can buffer more data and take longer to write it out. There's discussion between the Linux and PostgreSQL communities on how to deal with this at the moment, as discussed in this LWN.net article. (LWN.net won't be able to keep writing this sort of great work if people don't subscribe. I'm a subscriber and sharing this link because it's useful and informative. Please consider subscribing if you want to see more of this sort of thing.)

The main thing you can do to reduce the impact of checkpoints at the moment is to spread checkpoint activity out by increasing checkpoint_completion_target so that more of the data has been written out by the time the final checkpoint arrives. This has a cost, though - if you update a page (say) ten times, it might be written to disk multiple times before the checkpoint with a high completion target, even though it only strictly had to be written out once for crash safety. A higher completion target makes for smoother I/O patterns but more overall I/O overhead.

The other thing you can do to help is tell your operating system to immediately start writing data when it gets buffered writes. This is like the kernel side of setting checkpoint_completion_target and has a similar trade-off. See the linux vm documentation, in particular dirty_background_bytes, dirty_background_ratio, dirty_expire_centisecs.

Answer from Craig Ringer on Stack Exchange
🌐
PostgreSQL
postgresql.org › docs › current › sql-checkpoint.html
PostgreSQL: Documentation: 18: CHECKPOINT
February 26, 2026 - ... Unsupported versions: 13 / ... / 7.2 / 7.1 ... A checkpoint is a point in the write-ahead log sequence at which all data files have been updated to reflect the information in the log....
🌐
CYBERTEC PostgreSQL
cybertec-postgresql.com › home › postgresql: what is a checkpoint?
PostgreSQL: What is a checkpoint? | CYBERTEC
April 16, 2025 - The purpose of a checkpoint is to ensure that all the dirty buffers created up to a certain point are sent to disk so that the WAL up to that point can be recycled. The way PostgreSQL does that is by launching a checkpointer process which writes ...
Top answer
1 of 2
40

During its operation, PostgreSQL records changes to transaction log files, but it doesn't immediately flush them to the actual database tables. It usually just keeps the changes in memory, and returns them from memory when they are requested, unless RAM starts getting full and it has to write them out.

This means that if it crashes, the on disk tables won't be up to date. It has to replay the transaction logs, applying the changes to the on-disk tables, before it can start back up. That can take a while for a big, busy database.

For that reason, and so that the transaction logs do not keep growing forever, PostgreSQL periodically does a checkpoint where it makes sure the DB is in a clean state. It flushes all pending changes to disk and recycles the transaction logs that were being used to keep a crash recovery record of the changes.

This flush happens in two phases:

  • Buffered write()s of dirty shared_buffers to the tables; and
  • fsync() of affected files to make sure the changes really hit disk

Both of those can increase disk I/O load. Contention caused by these writes can slow down reads, and can also slow down flushing of WAL segments that's required in order to commit transactions.

It's been a longstanding challenge, but it's getting worse as we see systems with more and more RAM so they can buffer more data and take longer to write it out. There's discussion between the Linux and PostgreSQL communities on how to deal with this at the moment, as discussed in this LWN.net article. (LWN.net won't be able to keep writing this sort of great work if people don't subscribe. I'm a subscriber and sharing this link because it's useful and informative. Please consider subscribing if you want to see more of this sort of thing.)

The main thing you can do to reduce the impact of checkpoints at the moment is to spread checkpoint activity out by increasing checkpoint_completion_target so that more of the data has been written out by the time the final checkpoint arrives. This has a cost, though - if you update a page (say) ten times, it might be written to disk multiple times before the checkpoint with a high completion target, even though it only strictly had to be written out once for crash safety. A higher completion target makes for smoother I/O patterns but more overall I/O overhead.

The other thing you can do to help is tell your operating system to immediately start writing data when it gets buffered writes. This is like the kernel side of setting checkpoint_completion_target and has a similar trade-off. See the linux vm documentation, in particular dirty_background_bytes, dirty_background_ratio, dirty_expire_centisecs.

2 of 2
1

Flushing the dirty OS file system buffers caused by exceeding dirty_bytes or dirty_ratio is a foreground blocking operation!

The kernel tunables dirty_bytes, dirty_background_bytes, dirty_ratio, dirty_background_ratio and dirty_centisecs control flushing of dirty OS file system buffers to disk. dirty_bytes is the threshold in bytes, dirty_ratio is the threshold as a ratio of total memory. dirty_background_bytes and dirty_background_ratio are similar thresholds, but flushing happens in the background and does not block other read/write operations until it completes. dirty_centisecs is how many centiseconds can pass before a flush is initiated.

Recently the defaults for these tunables was lowered in Linux, as memory size for modern machines has increased dramatically. Even ratios of 5 and 10% for dirty_background_ratio and dirty_ratio on a 256GB machine can flood an I/O system.

Tuning dirty_background_bytes or dirty_background_ratio to start flushing dirty buffers in the background is tricky. Fortunately you can tune these settings without having to stop either PostgreSQL or the host by echoing new values to the appropriate files:

$ sudo echo [int value of bytes] > /proc/sys/vm/dirty_background_bytes

for example to set the number of dirtied bytes to trigger a background flush. If you are using a battery-backed, capacitor-backed, or flash memory RAID card (you do want to keep your data in case of a crash, don't you?) start by tuning dirty_background_bytes to 1/2 the write cache buffer size and dirty_bytes to 3/4 that size. Monitor your I/O profile with iostats and if you are still seeing latency issues that means your database write load is still overwhelming the file buffer cache flushes. Turn the values down until latency improves or consider upgrading your I/O subsystem. FusionIO cards and SSDs are two possibilities for extreme I/O throughput.

Good luck!

🌐
Medium
medium.com › @jramcloud1 › 04-postgresql-17-performance-tuning-checkpoints-explained-4972e78f4e56
04 - PostgreSQL 17 Performance Tuning: Checkpoints Explained | by Jeyaram Ayyalusamy | Medium
August 30, 2025 - Even if the database crashes before dirty buffers are written, PostgreSQL can replay WAL to recover changes. Think of dirty buffers like unsaved work in a text editor: You type changes (update rows) → they go into memory (dirty buffers). The program writes a small autosave log (WAL) → so your edits aren’t lost if the computer crashes. The file on disk (the actual table file) is only updated when you hit Save (checkpoint).
🌐
postgreshelp
postgreshelp.com › postgresql-checkpoint
PostgreSQL Checkpoint Demystified - postgreshelp
June 22, 2023 - PostgreSQL Checkpoint: Database blocks are temporarily stored in Database shared buffers. As blocks are read, they are stored in DB shared buffers so that if
🌐
CYBERTEC PostgreSQL
cybertec-postgresql.com › home › checkpoint distance and amount of wal
Checkpoint distance and amount of WAL
January 10, 2017 - To ensure that the WAL will not grow infinitely, PostgreSQL creates checkpoints. These are a perfect opportunity to recycle WAL. The size of your transaction should be more or less constant, so cleaning up WAL from time to time is an absolute must.
🌐
PostgreSQL
postgresql.org › docs › 9.2 › sql-checkpoint.html
PostgreSQL: Documentation: 9.2: CHECKPOINT
November 9, 2017 - You may want to view the same page ... instead. ... A checkpoint is a point in the transaction log sequence at which all data files have been updated to reflect the information in the log....
🌐
EnterpriseDB
enterprisedb.com › blog › basics-tuning-checkpoints
Basics of Tuning Checkpoints | EDB
July 11, 2024 - This post is about how to configure the two other cases, affecting regular periodic checkpoints. Those time/size limits are set using two configuration options: ... With these (default) values, PostgreSQL will trigger a CHECKPOINT every 5 minutes, or after writing about 1/2 GB of WAL, whichever happens first.
Find elsewhere
🌐
Interdb
interdb.jp › hironobu suzuki @ interdb › 9. write ahead logging (wal) › 9.7. checkpoint processing in postgresql
9.7. Checkpoint Processing in PostgreSQL :: Hironobu SUZUKI @ InterDB
January 1, 2024 - To summarize the description above from the perspective of database recovery, checkpointing creates a checkpoint record that contains the REDO point, and stores the checkpoint location and other information in the pg_control file. This allows PostgreSQL to recover itself by replaying WAL data from the REDO point (obtained from the checkpoint record) provided by the pg_control file.
🌐
PostgreSQL
postgresql.org › docs › 15 › sql-checkpoint.html
PostgreSQL: Documentation: 15: CHECKPOINT
February 26, 2026 - ... Unsupported versions: 13 / ... / 7.2 / 7.1 ... A checkpoint is a point in the write-ahead log sequence at which all data files have been updated to reflect the information in the log....
🌐
PostgreSQL
postgresqlco.nf › en › doc › param › checkpoint_timeout
PostgreSQL Documentation: checkpoint_timeout parameter
Maximum time between automatic WAL checkpoints. If this value is specified without units, it is taken as seconds. The valid range is between 30 seconds and one day. The default is five minutes (5min). Increasing this parameter can increase the amount of time needed for crash recovery. This parameter can only be set in the postgresql.conf file or on the server command line.
🌐
pgPedia
pgpedia.info › c › checkpoint-sql-command.html
CHECKPOINT - pgPedia - a PostgreSQL Encyclopedia
PostgreSQL documentation PostgreSQL ... ... CHECKPOINT is an SQL command which forces PostgreSQL to carry out an immediate checkpoint, after which the on-disk datafiles are guaranteed to be up-to-date as of the point the command was executed....
🌐
Highgo Software Inc.
highgo.ca › home › 2020 › december › 29 › checkpoints in postgresql
Checkpoints In PostgreSQL - Highgo Software Inc.
August 3, 2023 - The checkpoint is a process that ensures that all the information that has not made it to the data files, is flushed onto the disk at some regular intervals while ensuring that the database system is not put under a lot of pressure and compromises ...
🌐
Postgres Professional
postgrespro.com › blog › pgsql › 5967965
WAL in PostgreSQL: 3. Checkpoint : Postgres Professional
April 23, 2021 - This is where the startup process finishes its work, and the checkpointer process immediately performs the checkpoint in order to secure the restored state on disk. We can simulate a failure by forcing the server shutdown in the immediate mode. student$ sudo pg_ctlcluster 11 main stop -m immediate --skip-systemctl-redirect · (The --skip-systemctl-redirect option is needed here since we use PostgreSQL installed on Ubuntu from the package.
🌐
PostgreSQL
postgresql.org › docs › current › wal-configuration.html
PostgreSQL: Documentation: 18: 28.5. WAL Configuration
February 26, 2026 - The server's checkpointer process automatically performs a checkpoint every so often. A checkpoint is begun every checkpoint_timeout seconds, or if max_wal_size is about to be exceeded, whichever comes first.
🌐
Percona
docs.percona.com › percona-monitoring-and-management › 3 › reference › dashboards › dashboard-postgresql-checkpoints-buffers-wal-usage.html
PostgreSQL Checkpoints, Buffers and WAL Usage - Percona Monitoring and Management
July 9, 2025 - This dashboard monitors PostgreSQL’s checkpoint behavior, buffer management, and Write-Ahead Log (WAL) activity to help you identify I/O bottlenecks and optimize your database performance.
🌐
PostgreSQL
postgresqlco.nf › en › doc › param › checkpoint_completion_target
PostgreSQL Documentation: checkpoint_completion_target parameter
checkpoint_completion_target: Min: 0, Max: 1, Default: 0.9, Context: sighup, Needs restart: false • Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval.
🌐
PostgreSQL
postgresql.org › docs › devel › sql-checkpoint.html
PostgreSQL: Documentation: devel: CHECKPOINT
2 weeks ago - A checkpoint is a point in the write-ahead log sequence at which all data files have been updated to reflect the information in the log. All data files will be flushed to disk.
🌐
Stormatics
stormatics.tech › home › checkpoints, background writer and how to monitor it using pg_stat_bgwriter
Checkpoints, Background Writer and how to monitor it using pg_stat_bgwriter - Stormatics
February 17, 2026 - For example, with a checkpoint_timeout of 5 minutes (300 seconds) and a checkpoint_completion_target of 0.9, the objective is to finish the checkpoint within the initial 270 seconds. ... This means PostgreSQL has 150 seconds to write all dirty pages to disk.