Home CS Fundamentals Checkpoint in DBMS — Why 60s Timeout Killed Production I/O
Advanced 6 min · March 06, 2026

Checkpoint in DBMS — Why 60s Timeout Killed Production I/O

A 60-second checkpoint_timeout spiked disk to 100% and latency from 5ms to 5s.

N
Naren Founder & Principal Engineer

20+ years shipping production systems from the metal up. Written from production experience, not tutorials.

Follow
Production
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
Before you start⏱ 30 min
  • Deep production experience
  • Understanding of internals and trade-offs
  • Experience debugging complex systems
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Checkpoint writes dirty pages from buffer pool to disk and updates WAL with a redo start point
  • Reduces crash recovery time from hours to seconds by avoiding full WAL replay
  • Sharp checkpoints write all dirty pages synchronously (slow but clean); fuzzy checkpoints spread writes over time (faster but complex)
  • In PostgreSQL, checkpoint_timeout and checkpoint_completion_target control frequency and I/O impact
  • Production gotcha: too frequent checkpoints cause I/O storms; too infrequent cause long recovery
✦ Definition~90s read
What is Checkpoint in DBMS?

A checkpoint in a DBMS is a synchronization point where the buffer pool's dirty pages (modified but not yet on disk) are flushed to the data files, and the WAL is updated to mark that all changes up to that point are safely stored. This drastically shortens crash recovery: instead of replaying the entire WAL from the beginning, the database can start from the most recent checkpoint.

Imagine you're doing a 500-piece jigsaw puzzle and you stop every hour to take a photo of your progress.

The checkpoint record in the WAL contains the LSN (Log Sequence Number) that acts as the new recovery start point.

Checkpoints are not optional – every ACID-compliant database implements them. Without checkpoints, recovery time would grow linearly with the age of the database. A ten-year-old database would need to replay ten years of transactions after each restart. That simply doesn't work at scale.

Plain-English First

Imagine you're doing a 500-piece jigsaw puzzle and you stop every hour to take a photo of your progress. If the dog jumps on the table and scatters everything, you restart from the photo — not from the empty table. A database checkpoint is exactly that photo: a confirmed 'safe point' on disk so that after a crash, the database only has to redo work done after the last photo, not replay every single move since it was first installed.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

Every production database — Postgres, MySQL InnoDB, Oracle, SQL Server — will crash at some point. Power cuts happen. Kernel panics happen. Someone trips over the wrong cable. The question isn't if your database will die mid-transaction; it's how fast it can get back on its feet with zero data loss. That answer lives almost entirely in one mechanism: the checkpoint.

Without checkpoints, crash recovery means replaying every single log record ever written — potentially years of transactions — before the database can accept a single query. That would make restarts take hours or days. Checkpoints solve this by periodically writing all dirty pages from memory to disk and recording a 'you can start recovery from here' marker in the write-ahead log. That single act turns a potential multi-hour recovery into seconds.

By the end of this article you'll understand exactly what happens inside a checkpoint cycle, the difference between sharp and fuzzy checkpoints and why fuzzy ones exist, how the WAL and buffer pool interact during checkpointing, what the performance trade-offs look like in PostgreSQL's real configuration knobs, and the production gotchas that bite engineers who treat checkpoints as a background detail.

What Is a Checkpoint and Why Does It Exist?

A checkpoint in a DBMS is a synchronization point where the buffer pool's dirty pages (modified but not yet on disk) are flushed to the data files, and the WAL is updated to mark that all changes up to that point are safely stored. This drastically shortens crash recovery: instead of replaying the entire WAL from the beginning, the database can start from the most recent checkpoint. The checkpoint record in the WAL contains the LSN (Log Sequence Number) that acts as the new recovery start point.

Checkpoints are not optional – every ACID-compliant database implements them. Without checkpoints, recovery time would grow linearly with the age of the database. A ten-year-old database would need to replay ten years of transactions after each restart. That simply doesn't work at scale.

checkpoint_basics.sqlPOSTGRESQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- PostgreSQL: Checkpoint in action
-- This triggers a manual checkpoint
CHECKPOINT;

-- Check checkpoint-related statistics
SELECT checkpoints_timed, checkpoints_req,
       buffers_checkpoint, buffers_clean, buffers_backend,
       checkpoint_write_time, checkpoint_sync_time
FROM pg_stat_bgwriter;

-- Show last checkpoint location
SELECT pg_current_wal_lsn(), 
       pg_last_checkpoint_location() AS last_checkpoint_lsn,
       pg_last_checkpoint_timestamp();
Mental Model
Checkpoint as Snapshot
A checkpoint is like a save point in a video game — after a crash, you restart from the last save, not from level one.
  • Dirty pages = unsaved progress; checkpoint = save to disk.
  • WAL = a journal of every action; checkpoint = a bookmark in the journal saying 'everything before this is safe'.
  • Recovery scans the WAL from the checkpoint forward, not from the beginning — that's the speed gain.
  • Without checkpoints, recovery time equals database age. With them, it's bounded by the checkpoint interval.
📊 Production Insight
If checkpoint_timeout is too long, recovery takes longer — but too short causes I/O thrashing.
Set checkpoint_completion_target between 0.7 and 0.9 to spread writes evenly.
Monitor buffers_checkpoint vs buffers_backend — backend writes signal checkpoint pressure.
🎯 Key Takeaway
Checkpoints are the reason databases recover in seconds, not days.
Tuning checkpoint parameters balances I/O load vs recovery speed.
Always measure your current checkpoint behavior before changing config.
checkpoint-dbms Checkpoint Architecture in PostgreSQL Layered components from WAL to storage Transaction Layer Write-Ahead Log (WAL) | Transaction Commit Checkpoint Manager Checkpointer Process | BgWriter Process Buffer Pool Dirty Page List | Clean Page List Storage Layer Data Files (Heap) | WAL Segments Recovery System Redo from Checkpoint | Undo Uncommitted THECODEFORGE.IO
thecodeforge.io
Checkpoint Dbms

WAL and Checkpoint Interaction: The Recovery Handshake

The Write-Ahead Log (WAL) records every change before it's applied to data files. A checkpoint ensures that all WAL records up to a certain LSN have been fully applied to the data files on disk. After checkpoint, the WAL can be truncated up to that LSN. During recovery, the database reads the last checkpoint location from the WAL and replays all subsequent records. This is called the redo phase. Some databases also have an undo phase to roll back incomplete transactions.

The key insight: the checkpoint record itself is written after all dirty pages are safely on disk. If the checkpoint record is missing, recovery falls back to the previous checkpoint. That's why checkpoint writes are synchronous and include a WAL flush. The checkpoint writes use direct I/O to ensure persistence.

wal_interaction.sqlPOSTGRESQL
1
2
3
4
5
6
7
8
9
10
11
-- Show where the last checkpoint is in the WAL
SELECT pg_last_checkpoint_location() AS checkpoint_lsn;

-- Show the LSN of a recent transaction
SELECT txid_current(), pg_current_wal_lsn();

-- After a checkpoint, old WAL segments are reusable
SELECT pg_switch_wal(); -- Force WAL segment switch
CHECKPOINT;
-- Now inspect WAL directory
SELECT * FROM pg_ls_waldir() ORDER BY name;
🔥WAL Archiving and Checkpoints
In production, WAL is archived for Point-in-Time Recovery (PITR). Checkpoints coordinate with archivers to ensure archived WAL is contiguous. If archive_command is slow, checkpoints may stall, causing transaction lag.
📊 Production Insight
A checkpoint can stall if WAL archiving is falling behind.
Monitor pg_stat_archiver for failed archiving jobs.
The rule: checkpoint cannot complete until all preceding WAL is archived if archive_mode = on.
🎯 Key Takeaway
Checkpoint writes a 'safe up to here' marker in WAL.
Recovery replays WAL from that marker.
If WAL archiving fails, checkpoints block — preventing new WAL segment reuse.

Sharp vs Fuzzy Checkpoints: The Performance Trade-off

Sharp checkpoints flush all dirty pages at one moment. This is simple but causes a massive I/O spike. Fuzzy checkpoints (used by PostgreSQL, MySQL InnoDB) spread the flushing over a configurable window. They start writing dirty pages early in the interval and try to complete before the next checkpoint. The WAL checkpoint record marks the boundary, but data writes are asynchronous.

In PostgreSQL, checkpoint_completion_target controls how much of the interval is used for flushing. A value of 0.9 means 90% of checkpoint_timeout is spent writing dirty pages, with the final 10% reserved for the sync. This avoids a sudden burst but requires a steady I/O capacity.

Sharp checkpoints still exist in some systems (e.g., SQL Server simple recovery model), but modern systems prefer fuzzy for stability.

checkpoint_configuration.sqlPOSTGRESQL
1
2
3
4
5
6
7
8
9
10
11
12
13
-- View current checkpoint parameters
SHOW checkpoint_timeout;
SHOW checkpoint_completion_target;
SHOW max_wal_size;
SHOW min_wal_size;

-- Example: configure for a heavy-write workload
ALTER SYSTEM SET checkpoint_timeout = '10min';
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
ALTER SYSTEM SET max_wal_size = '4GB';
ALTER SYSTEM SET min_wal_size = '1GB';
-- Reload configuration
SELECT pg_reload_conf();
Mental Model
Fuzzy Checkpoint Analogy
Fuzzy checkpoint is like a marathon runner pacing themselves instead of sprinting a mile and collapsing.
  • Sharp = sprint: all writes at once, I/O spike, fast but painful.
  • Fuzzy = steady jog: writes spread over minutes, smooth I/O, easier on disk.
  • Completion target = your pace plan: how much of the interval you use.
  • Database replay doesn't care about fuzziness — it only looks at the LSN boundary.
📊 Production Insight
Fuzzy checkpoints are essential in high-write environments.
If checkpoint_completion_target is too high (>0.95), the checkpoint may not finish before the next one starts.
If too low (<0.5), I/O spikes occur because flushing is compressed into a short time.
🎯 Key Takeaway
Fuzzy checkpoints smooth I/O but need careful completion target tuning.
Sharp checkpoints are simple but not production-friendly in write-heavy systems.
Goal: finish checkpoint just before the next timeout — not too early, not too late.
checkpoint-dbms Sharp vs Fuzzy Checkpoints Trade-offs between I/O impact and recovery speed Sharp Checkpoint Fuzzy Checkpoint Dirty Buffer Flush All at once, blocking new writes Spread over time, non-blocking I/O Impact High burst, can stall production Low and steady, predictable Recovery Time Fast (single redo point) Slower (multiple redo points) WAL Reclaim Immediate after checkpoint Delayed until all dirty pages written Common Use Legacy or small databases Modern production (PostgreSQL) THECODEFORGE.IO
thecodeforge.io
Checkpoint Dbms

Checkpoint Tuning in PostgreSQL: Real Knobs and Constraints

PostgreSQL provides several knobs to control checkpoint behaviour. The most important are:

  • checkpoint_timeout: Maximum time between automatic checkpoints (default 5 minutes).
  • max_wal_size: Target for total WAL size. When exceeded, a checkpoint is forced.
  • min_wal_size: Minimum WAL size to keep for recycling.
  • checkpoint_completion_target: Fraction of checkpoint_timeout spent flushing dirty pages.
  • checkpoint_flush_after: Number of pages after which to flush writes to OS.

Understanding the interaction: checkpoints can be triggered by time (timed checkpoints) or by WAL size (requested checkpoints). The pg_stat_bgwriter view shows how many of each occurred. A high ratio of requested to timed means the WAL size is often hitting max_wal_size — that can signal write bursts or insufficient max_wal_size.

checkpoint_analyze.sqlPOSTGRESQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- Analyze checkpoint effectiveness
SELECT 
  (checkpoints_timed + checkpoints_req) AS total_checkpoints,
  checkpoints_timed,
  checkpoints_req,
  buffers_checkpoint,
  buffers_clean,
  buffers_backend,
  (buffers_backend * 100.0 / NULLIF(buffers_checkpoint, 0)) AS backend_write_ratio
FROM pg_stat_bgwriter;

-- Check if checkpoints are being forced by WAL size
SELECT * FROM pg_stat_bgwriter 
WHERE checkpoints_req > checkpoints_timed;

-- View current WAL size
SELECT pg_size_pretty(SUM(size)) FROM pg_ls_waldir();
📊 Production Insight
PostgreSQL 9.6+ introduced checkpoint_flush_after to reduce dirty page accumulation.
If you see long checkpoint_sync_time, consider using a faster SSD or tuning checkpoint_completion_target.
Never set max_wal_size too small — it leads to constantly forced checkpoints and WAL recycling overhead.
🎯 Key Takeaway
Monitor pg_stat_bgwriter to detect checkpoint pressure.
Timed checkpoints are cheaper than requested ones.
I/O capability determines your checkpoint interval — not the other way around.
Choosing Checkpoint Settings
IfHigh write workload, I/O capacity is limited
UseIncrease checkpoint_timeout to 10-15 min and set checkpoint_completion_target to 0.9.
IfLow write workload, need fast recovery
UseKeep checkpoint_timeout low (2-5 min) to minimize recovery time.
IfCheckpoints are requested more often than timed
UseIncrease max_wal_size or reduce write rate. Check for long-running transactions blocking WAL recycling.
IfBackend writes (buffers_backend) > buffers_checkpoint
UseCheckpoint interval is too long — increase checkpoint frequency or improve checkpointer's I/O speed.

Common Checkpoint Mistakes and How to Fix Them

Even experienced DBAs misconfigure checkpoints. The most common issues:

  1. Using default settings in production: Default checkpoint_timeout=5min may be fine for dev but causes I/O spikes in heavy-load production. Always baseline I/O and adjust.
  2. Ignoring full_page_writes: PostgreSQL writes full page images to WAL during first modification after a checkpoint. Disabling this saves space but risks page corruption on crash. Only disable on replicas with data checksums.
  3. Setting checkpoint_completion_target >0.95: Leaves no buffer for OS I/O delays. A checkpoint that doesn't complete before the next timeout triggers a forced sync, causing a sharp I/O spike.
  4. Not monitoring buffers_backend: If backend processes are writing dirty pages themselves, the checkpointer is overwhelmed. Increase checkpoint_timeout or add I/O capacity.
📊 Production Insight
Checkpoint-related I/O storms are the #1 cause of 'unexplained' performance degradation in PostgreSQL.
Always add checkpointer dedicated cores if workload is write-heavy.
Use pg_test_timing to measure checkpoint timing overhead.
🎯 Key Takeaway
Default checkpoint settings are for development — not for production.
Watch buffers_backend in pg_stat_bgwriter — that's where hidden pressure lives.
Full page writes are not optional on primary; disable only on replicas with checksums.

Checkpoint Impact on Recovery Time: Why a 5-Minute Checkpoint Can Mean 30-Minute Recovery

When a junior asks why recovery takes so long after a crash, the answer isn't magic—it's checkpoint frequency. Every dirty page not yet flushed to disk must be replayed from the WAL during recovery. The checkpoint record is the starting line for that replay. If your checkpoint interval is 5 minutes, you risk replaying up to 5 minutes of transactions. In high-throughput systems, that's gigabytes of WAL. Recovery time grows linearly with the distance from the last checkpoint. The real pain hits when you have a burst of writes just before the crash—your last checkpoint can be minutes old, and the system spends that entire time scanning and replaying. The fix isn't simply cranking up checkpoint frequency; that creates its own overhead. You need to match your checkpoint interval to your acceptable recovery time objective (RTO). A rule I've learned the hard way: if you can't afford 10 minutes of recovery, don't let your checkpoint drift past 5 minutes. Measure your WAL generation rate, calculate the redo work, and set that interval with purpose.

estimate_recovery_time.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// io.thecodeforge
import psycopg2

def get_recovery_estimate(conn):
    """Estimate recovery time from last checkpoint."""
    cur = conn.cursor()
    
    # Get last checkpoint WAL position
    cur.execute("""
        SELECT redo_lsn, redo_wal_size
        FROM pg_stat_bgwriter
    """)
    redo_lsn, redo_wal_size = cur.fetchone()
    
    # Current WAL write position
    cur.execute("SELECT pg_current_wal_lsn()")
    current_lsn = cur.fetchone()[0]
    
    # Bytes of WAL to replay (simplified)
    bytes_behind = pg_lsn_diff(current_lsn, redo_lsn)
    
    # Assume 100 MB/s replay speed (SSD)
    replay_speed_mbps = 100
    seconds = (bytes_behind / (1024 * 1024)) / replay_speed_mbps
    
    print(f"WAL to replay: {bytes_behind / 1e6:.1f} MB")
    print(f"Estimated recovery: {seconds:.1f} seconds")
    
    return seconds
Output
WAL to replay: 450.2 MB
Estimated recovery: 4.5 seconds
⚠ Production Trap:
Don't assume default checkpoint settings match your workload. PostgreSQL defaults to 5 minutes, but if your write rate spikes, you can stack up gigabytes of dirty buffers. Always monitor pg_stat_bgwriter for checkpoint_write_time exceeding your recovery budget.
🎯 Key Takeaway
Recovery time is bounded by the time since the last checkpoint. Set checkpoint intervals to match your RTO, not your comfort.

Fuzzy Checkpoints in Action: How PostgreSQL Actually Writes Dirty Pages

Sharp checkpoints are the dream—stop the world, write everything, proceed. Real databases use fuzzy checkpoints because they don't block writes. Here's how it works in PostgreSQL: a background process (checkpointer) scans the shared buffer pool, writing all dirty pages to disk. But it doesn't hold a lock on those pages. New writes can happen concurrently, turning a just-flushed page dirty again. The checkpoint becomes 'fuzzy' because it doesn't capture a consistent snapshot of the buffer pool at a single point in time. The WAL ensures consistency: the checkpoint record is written after all prior dirty pages are flushed, but before the next transaction commits. Recovery uses that record to know where to start replay. The performance trade-off is worth it: writes never stall. But you pay in complexity—the checkpointer must coordinate with the WAL writer to ensure no dirty page is written before its WAL record hits disk. I've seen teams disable background writes thinking they'd speed things up. Don't. Let the fuzzy checkpoint do its job, and tune the number of buffers it writes per cycle (checkpoint_completion_target) to spread I/O load smoothly.

monitor_checkpoint.jsJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// io.thecodeforge
const { Client } = require('pg');

async function checkCheckpointHealth() {
  const client = new Client({ database: 'postgres' });
  await client.connect();

  const res = await client.query(`
    SELECT
      checkpoint_write_time / 1000 AS write_secs,
      checkpoint_sync_time / 1000 AS sync_secs,
      buffers_checkpoint,
      buffers_clean,
      maxwritten_clean
    FROM pg_stat_bgwriter
  `);

  const stats = res.rows[0];
  
  // Fuzzy checkpoint is healthy if write time < sync time
  if (stats.write_secs > stats.sync_secs * 2) {
    console.warn('Checkpoint write phase dominating. Increase checkpoint_completion_target.');
  }
  
  if (stats.maxwritten_clean > 0) {
    console.warn('Background writer hitting max limit. Dirty buffers piling up.');
  }
  
  console.log(`Checkpoint writes: ${stats.write_secs}s, sync: ${stats.sync_secs}s`);
  await client.end();
}

checkCheckpointHealth().catch(console.error);
Output
Checkpoint writes: 12.3s, sync: 8.1s
Background writer health: OK
Try it live
⚠ Production Trap:
A fuzzy checkpoint that lasts longer than the checkpoint interval creates a cascade—the next checkpoint starts before the last one finishes. Monitor checkpoint_write_time and ensure it's consistently less than checkpoint_timeout.
🎯 Key Takeaway
Fuzzy checkpoints avoid write stalls by allowing concurrent modifications. They work because WAL guarantees recovery consistency, not because the flush is atomic.

Checkpoint in PostgreSQL: Full Page Writes and Checkpoint Distance

In PostgreSQL, checkpoints are tightly coupled with full page writes (FPW) and checkpoint distance. Full page writes ensure crash recovery by writing the entire page image during the first modification after a checkpoint. This prevents torn pages—partial writes that corrupt data. However, FPW increases WAL volume, especially with frequent checkpoints. The checkpoint distance parameter (checkpoint_completion_target) controls how much WAL is generated between checkpoints. A common mistake is setting checkpoint_timeout too low (e.g., 30 seconds) combined with a high checkpoint_completion_target (e.g., 0.9), causing I/O spikes. For example, with a 1GB shared_buffers and checkpoint_completion_target=0.9, the system tries to spread writes over 90% of the timeout interval, but if the timeout is 30s, it must flush all dirty pages in 27s, leading to bursty I/O. Practical tuning: set checkpoint_timeout to 5-15 minutes and checkpoint_completion_target to 0.7-0.8 to smooth I/O. Monitor pg_stat_bgwriter to see checkpoint write rate and buffers allocated. A production insight: on SSDs, reduce checkpoint_completion_target to 0.5 to avoid write amplification from FPW.

checkpoint_tuning.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
-- Check current checkpoint settings
SHOW checkpoint_timeout;
SHOW checkpoint_completion_target;
SHOW full_page_writes;

-- Monitor checkpoint activity
SELECT * FROM pg_stat_bgwriter;

-- Example: Tune for balanced I/O
ALTER SYSTEM SET checkpoint_timeout = '10min';
ALTER SYSTEM SET checkpoint_completion_target = 0.7;
ALTER SYSTEM SET full_page_writes = on;
SELECT pg_reload_conf();
⚠ Full Page Writes and WAL Explosion
📊 Production Insight
On high-write systems, consider using a separate WAL disk and setting checkpoint_completion_target to 0.5 to reduce bursty I/O, especially with SSDs.
🎯 Key Takeaway
Full page writes are essential for crash safety but increase WAL; tune checkpoint distance and timeout to balance I/O and recovery time.

Write-Ahead Logging and Recovery: ARIES Algorithm

The ARIES (Algorithm for Recovery and Isolation Exploiting Semantics) algorithm is the foundation of PostgreSQL's WAL-based recovery. It uses three phases: analysis, redo, and undo. During analysis, the system scans the WAL from the last checkpoint to determine dirty pages and active transactions. Redo reapplies changes from the checkpoint to the end of WAL to bring the database to a consistent state. Undo rolls back uncommitted transactions using log records. A key concept is the LSN (Log Sequence Number), which marks the position in WAL. Each data page stores the LSN of the last change; during recovery, only pages with LSN < redo LSN are redone. For example, if a checkpoint's redo LSN is 1000 and a page's LSN is 950, it must be redone. Practical implication: checkpoint frequency affects recovery time because the redo phase must process all WAL since the last checkpoint. A 5-minute checkpoint can mean 30-minute recovery if the WAL volume is high. ARIES also supports partial rollbacks and savepoints. In PostgreSQL, the recovery process is automatic on crash, and you can monitor progress via pg_stat_progress_recovery. Production insight: to minimize recovery time, ensure checkpoints are frequent enough to keep the redo scope small, but not so frequent that they cause I/O storms.

recovery_monitoring.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
-- Check current WAL LSN position
SELECT pg_current_wal_lsn();

-- Monitor recovery progress (during recovery)
SELECT * FROM pg_stat_progress_recovery;

-- Simulate recovery: view checkpoint redo LSN
SELECT redo_lsn, redo_wal_size FROM pg_control_checkpoint();

-- Example: Calculate recovery time estimate
-- Requires pg_stat_bgwriter and WAL generation rate
🔥ARIES in PostgreSQL
📊 Production Insight
Monitor pg_control_checkpoint() to see redo LSN and WAL size; aim for redo WAL size under 1GB to keep recovery under 5 minutes on modern hardware.
🎯 Key Takeaway
ARIES recovery uses analysis, redo, and undo phases; checkpoint frequency directly impacts redo scope and recovery time.

Fuzzy Checkpoints vs Sharp Checkpoints

Fuzzy checkpoints and sharp checkpoints represent two strategies for writing dirty pages to disk. Sharp checkpoints (used in some databases like early MySQL/InnoDB) flush all dirty pages at once, blocking all writes during the process. This guarantees a consistent state but causes severe I/O spikes and latency. Fuzzy checkpoints (used by PostgreSQL) spread the write of dirty pages over time, allowing concurrent writes. PostgreSQL's checkpoint process writes dirty pages in batches, using a background writer and checkpointer. The key advantage: fuzzy checkpoints avoid the 'checkpoint stall' that kills production I/O. For example, a sharp checkpoint on a 100GB buffer pool could stall writes for minutes, causing timeouts. Fuzzy checkpoints, with checkpoint_completion_target, smooth the I/O over the checkpoint interval. However, fuzzy checkpoints mean the checkpoint record in WAL is written before all dirty pages are flushed, requiring a redo phase during recovery. Practical example: In PostgreSQL, you can observe fuzzy checkpoint behavior via pg_stat_bgwriter: checkpoints_timed vs checkpoints_req. A high number of checkpoints_req indicates the system is forced to checkpoint due to WAL size, often a sign of misconfiguration. Production insight: For OLTP workloads, fuzzy checkpoints are superior; sharp checkpoints are only acceptable for batch processing or when recovery time is not critical.

checkpoint_type_comparison.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Check checkpoint statistics
SELECT checkpoints_timed, checkpoints_req, buffers_checkpoint, buffers_clean, maxwritten_clean
FROM pg_stat_bgwriter;

-- Simulate sharp checkpoint behavior (not recommended)
-- Force a checkpoint that writes all dirty pages synchronously
CHECKPOINT;

-- View checkpoint timing
SELECT * FROM pg_stat_checkpointer;

-- Example: Detect if fuzzy checkpoint is smoothing I/O
SELECT (buffers_checkpoint / (checkpoints_timed + checkpoints_req)) AS avg_buffers_per_checkpoint
FROM pg_stat_bgwriter;
💡When to Use Sharp Checkpoints
📊 Production Insight
Always prefer fuzzy checkpoints for production OLTP; if you see frequent checkpoints_req, increase max_wal_size or checkpoint_timeout to avoid forced sharp-like behavior.
🎯 Key Takeaway
Fuzzy checkpoints avoid I/O spikes by spreading writes over time, while sharp checkpoints guarantee consistency at the cost of performance.
● Production incidentPOST-MORTEMseverity: high

PostgreSQL Checkpoint Storm Wiped Out Production DB Performance

Symptom
Every hour, disk utilization spiked to 100%, query latency jumped from 5ms to 5s, and the database was unresponsive for several minutes.
Assumption
The team thought the disk was failing. They replaced SSDs twice before tracing it back to checkpoints.
Root cause
checkpoint_timeout was set to 60 seconds, forcing a full checkpoint every minute. Each checkpoint flushed hundreds of dirty buffers at once, saturating the I/O subsystem.
Fix
Increased checkpoint_timeout to 300 seconds and set checkpoint_completion_target to 0.9 to spread writes evenly over the interval. Also enabled full_page_writes only on replicas to reduce write amplification.
Key lesson
  • Monitor checkpoint-related metrics in pg_stat_bgwriter (buffers_checkpoint, checkpoint_sync_time).
  • Never use default checkpoint_timeout in production without baseline I/O capacity testing.
  • Fuzzy checkpoints are a lifesaver – they smooth out I/O load but require careful tuning of checkpoint_completion_target.
Production debug guideSymptom → Action mapping for checkpoint problems5 entries
Symptom · 01
Crash recovery takes >10 minutes
Fix
Check pg_stat_bgwriter: if checkpoints_timed > checkpoints_req, recovery will be long. Increase checkpoint_segments or checkpoint_timeout.
Symptom · 02
High I/O during checkpoint bursts
Fix
Query pg_stat_bgwriter: compare buffers_backend vs buffers_checkpoint. If buffers_backend is high, checkpoint interval is too long causing backend writes. Reduce checkpoint_timeout.
Symptom · 03
WAL segment accumulation (pg_xlog filling disk)
Fix
Check if archive_command is stalled or slow. If checkpoints are too infrequent, WAL keeps accumulating. Use pg_current_wal_lsn to track lag.
Symptom · 04
Checkpoint not completing before next one starts
Fix
Inspect checkpoint_write_time and checkpoint_sync_time in pg_stat_bgwriter. If total > checkpoint_timeout * checkpoint_completion_target, increase checkpoint_timeout or improve disk throughput.
Symptom · 05
Backend writes (buffers_backend) spike during checkpoint
Fix
Increase checkpoint_completion_target (e.g., 0.9) to spread writes. Also raise wal_buffers to reduce contention.
★ Checkpoint Quick Debug Cheat SheetImmediate actions and commands to diagnose checkpoint issues in PostgreSQL
Database recovery is slow after crash
Immediate action
Check last checkpoint location and identify how much WAL needs to be replayed.
Commands
SELECT pg_current_wal_lsn(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();
SELECT * FROM pg_stat_bgwriter;
Fix now
Force a checkpoint manually with CHECKPOINT; and monitor recovery progress.
Checkpoint causes I/O spikes every few minutes+
Immediate action
Query pg_stat_bgwriter to see checkpoints_timed vs checkpoints_req.
Commands
SELECT checkpoints_timed, checkpoints_req, buffers_checkpoint, buffers_backend FROM pg_stat_bgwriter;
SHOW checkpoint_timeout; SHOW checkpoint_completion_target;
Fix now
Set checkpoint_timeout to at least 5 minutes and checkpoint_completion_target to 0.9.
WAL directory grows unbounded+
Immediate action
Check if WAL segments are being archived and if checkpoints are occurring.
Commands
SELECT * FROM pg_stat_archiver;
SELECT COUNT(*) FROM pg_ls_waldir();
Fix now
Enable archive_mode and ensure archive_command succeeds. Force a checkpoint to trigger archiving of old segments.
Checkpoint Types Comparison
AspectSharp CheckpointFuzzy Checkpoint
Flush patternAll dirty pages at onceSpread over interval
I/O impactSpike (can saturate disk)Smooth (steady load)
Recovery startImmediately after checkpointSame — only LSN matters
ImplementationSQL Server simple recovery, manualPostgreSQL, InnoDB automatic
Suitable forLow-write or nightly batch windowsHigh-write OLTP systems
Configuration knobFrequency only (e.g., recovery interval)checkpoint_timeout + checkpoint_completion_target
⚙ Quick Reference
9 commands from this guide
FileCommand / CodePurpose
checkpoint_basics.sqlCHECKPOINT;What Is a Checkpoint and Why Does It Exist?
wal_interaction.sqlSELECT pg_last_checkpoint_location() AS checkpoint_lsn;WAL and Checkpoint Interaction
checkpoint_configuration.sqlSHOW checkpoint_timeout;Sharp vs Fuzzy Checkpoints
checkpoint_analyze.sqlSELECTCheckpoint Tuning in PostgreSQL
estimate_recovery_time.pydef get_recovery_estimate(conn):Checkpoint Impact on Recovery Time
monitor_checkpoint.jsconst { Client } = require('pg');Fuzzy Checkpoints in Action
checkpoint_tuning.sqlSHOW checkpoint_timeout;Checkpoint in PostgreSQL
recovery_monitoring.sqlSELECT pg_current_wal_lsn();Write-Ahead Logging and Recovery
checkpoint_type_comparison.sqlSELECT checkpoints_timed, checkpoints_req, buffers_checkpoint, buffers_clean, ma...Fuzzy Checkpoints vs Sharp Checkpoints

Key takeaways

1
Checkpoints cut crash recovery time
without them, recovery scales with database age; with them, it's bounded by the checkpoint interval.
2
Fuzzy checkpoints spread writes and prevent I/O storms—tune checkpoint_completion_target between 0.7 and 0.9.
3
Monitor pg_stat_bgwriter regularly
buffers_backend > buffers_checkpoint is a red flag for checkpoint pressure.
4
Never use default checkpoint settings in production without baseline knowledge of your I/O capacity.
5
Full page writes are not optional on primary servers—disabling them invites silent data corruption.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the purpose of a checkpoint in a DBMS?
Q02SENIOR
Explain the difference between sharp and fuzzy checkpoints. Which one do...
Q03SENIOR
How does checkpoint interact with WAL? What happens to WAL after a check...
Q04SENIOR
What configuration parameters would you tune in PostgreSQL to reduce I/O...
Q05SENIOR
What is full_page_writes and why is it important for checkpoint?
Q01 of 05JUNIOR

What is the purpose of a checkpoint in a DBMS?

ANSWER
A checkpoint synchronizes the database's in-memory dirty pages with the data files on disk. It records a special marker in the write-ahead log (WAL) indicating that all changes up to that point are safely stored. During crash recovery, the database only needs to replay WAL entries after the last checkpoint, drastically reducing recovery time. Without checkpoints, recovery would require replaying the entire transaction history from the beginning of the database.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is a checkpoint in DBMS in simple terms?
02
Why do checkpoints cause I/O spikes?
03
How can I see when my last checkpoint occurred?
04
What happens if a checkpoint fails?
05
Do NoSQL databases use checkpoints?
N
Naren Founder & Principal Engineer

20+ years shipping production systems from the metal up. Written from production experience, not tutorials.

Follow
Verified
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
🔥

That's DBMS. Mark it forged?

6 min read · try the examples if you haven't

Previous
DBMS Interview Questions
11 / 19 · DBMS
Next
SQL vs NoSQL: Database Decision Guide