Course contentsShow
← Databases & SQL
Lesson 857 of 1,9538. PostgreSQL InternalsFree lesson

Commit Delay and Wait Algorithms

You will tune group commit parameters to optimize transaction throughput under heavy load.

In this lesson, you will learn how to tune PostgreSQL group commit parameters to balance latency and throughput during high-concurrency workloads.

The Problem: The Cost of Flushing

When a transaction commits, PostgreSQL must ensure the Write-Ahead Log (WAL) is physically flushed to stable storage. This is a slow operation. If 100 concurrent users commit at the same time, the system might perform 100 individual disk flushes, causing the I/O subsystem to bottleneck.

"Group commit" solves this by allowing one process to wait a tiny amount of time, hoping that other transactions will arrive so they can all be written to the disk in a single batch operation.

Tuning the Wait

PostgreSQL provides two key parameters in postgresql.conf to control this behavior:

  • commit_delay: This defines how many microseconds a transaction will sleep after preparing its commit but before officially requesting a WAL flush.
  • commit_siblings: This acts as a safety switch. If there are at least this many other active transactions currently running, the system will apply the commit_delay. If there are fewer, it assumes the system isn't under enough load to justify the delay, so it skips the wait.

Putting it into practice

Imagine your system handles a massive influx of small transactions. If you notice high CPU usage on the WAL writer, you might apply these settings:

# Wait 500 microseconds if there are at least 5 other transactions
commit_delay = 500
commit_siblings = 5

By setting commit_delay to 500, you are essentially telling PostgreSQL: "Wait a split second to see if your friends arrive." If 10 transactions arrive within that window, they "group" together. Instead of 10 separate, expensive disk syncs, you perform one large, efficient write.

However, be careful! Setting commit_delay too high will artificially inflate transaction latency for every single user, making your application feel sluggish. It is a classic trade-off: you sacrifice individual response time to increase the total number of transactions the database can handle per second.

Key Takeaway: Use commit_delay and commit_siblings to batch WAL flushes during high load, trading off slight latency per transaction to drastically improve overall throughput.