DBRaven
Failure Mode · capacity

Disk I/O Saturation

critical

Summary

The storage device reaches its IOPS or throughput ceiling, causing all disk- dependent database operations to queue behind I/O requests, driving latency from sub-millisecond to hundreds of milliseconds and degrading all database operations simultaneously.

Description

Database performance is ultimately bounded by storage I/O. PostgreSQL requires disk I/O for: WAL writes (every write transaction), dirty buffer flushes (checkpoint), uncached page reads (data not in shared_buffers), autovacuum (reading and writing heap pages), and temporary files (sort and hash operations spilling to disk). When the cumulative I/O demand from all these sources exceeds the storage device's capacity, the I/O subsystem queues requests.

AWS EBS volume characteristics: GP2 provides burst to 3,000 IOPS up to a burst credit bucket, with baseline at 3 IOPS/GB (a 100GB GP2 volume has 300 IOPS baseline). GP3 provides 3,000 IOPS baseline regardless of size, configurable up to 16,000 IOPS. io1/io2 provides up to 64,000 IOPS. A GP3 volume at 3,000 IOPS baseline will saturate with PostgreSQL running a sustained checkpoint + autovacuum + OLTP write workload on a moderately sized table.

I/O saturation is insidious because it affects all operations uniformly. A checkpoint consuming 2,800 of the 3,000 available IOPS leaves only 200 IOPS for WAL writes. WAL writes stall. Transaction commits stall waiting for WAL fsync. All active write transactions queue. The database appears frozen with no queries completing. Read operations that require uncached pages also queue. Even simple queries slow dramatically.

The Linux I/O scheduler queues I/O requests when the device is saturated. Queue depth grows. The kernel reports iowait CPU time: the fraction of CPU time spent waiting for I/O rather than executing instructions. Sustained iowait > 10% on a database host is a warning; iowait > 30% indicates severe saturation.

Temporary file I/O is a particularly dangerous contributor: a query that exceeds work_mem writes a sort or hash file to disk. A poorly indexed query sorting 10GB of data generates 10GB of disk reads (sort input) + 10GB of writes (sort output) : consuming I/O capacity for the duration of the query and degrading all concurrent operations.

I/O access patterns differ by storage engine shape, not just by workload. B-Tree engines (PostgreSQL heap tables plus B-Tree indexes, InnoDB's clustered B-Tree) generate substantial random I/O: an index lookup walks non-contiguous pages, and a row fetch through a secondary index, or in InnoDB through the clustered index after an indirection lookup, touches pages scattered across the file. This is why B-Tree engines are far more sensitive to a storage device's random-IOPS ceiling than to its raw sequential throughput. LSM engines such as Cassandra shift the write side toward sequential I/O: memtable flushes and compaction both write sorted, immutable runs as sequential append operations, which is cheap on both spinning disks and SSDs. The cost moves to reads instead. A point read may have to probe the active memtable and multiple SSTables across several levels before it finds, or rules out, a key, and each SSTable probe is a separate I/O unless a Bloom filter attached to that SSTable short-circuits the miss without touching disk. This read amplification grows with compaction debt (see lsm_compaction_debt): the more unmerged SSTables accumulate, the more of them a single read may have to check. Columnar/OLAP engines are a third shape again. ClickHouse's MergeTree engine is built around large sequential scans over column files; there is comparatively little random I/O in steady state. I/O saturation there is usually a function of scan volume and codec choice (LZ4 by default, or ZSTD, Delta, and DoubleDelta for better ratios at more CPU cost) rather than seek contention, so the primary levers are pruning, letting the primary key and skip indexes rule out whole granules before they are read, and compression, not raw IOPS provisioning.

Characteristics

Propagationfan out
Time to detectSeconds with I/O utilisation monitoring (iowait alerting, EBS IOPS monitoring). Application latency impact is nearly immediate when saturation begins. EBS burst credit exhaustion (GP2) is detectable 10–60 minutes before the drop to baseline IOPS if BurstBalance is monitored.
Blast radiusAll database operations that require disk I/O are affected simultaneously. This includes every write (WAL stall), every uncached read (page fault stall), and background processes (autovacuum, checkpoint). The blast radius is the entire database: all tables, all queries, all connections. Replication is affected as WAL sends slow. All applications using the database experience simultaneous degradation.

Triggers

  • ·PostgreSQL checkpoint flushing large volumes of dirty shared_buffers to disk
  • ·Autovacuum performing full-table vacuum on a large table with many dead tuples
  • ·Workload shift to larger queries that exceed work_mem and generate temporary disk sort files
  • ·Bulk data import or migration generating WAL + heap writes at sustained high rate
  • ·EBS GP2 burst credit exhaustion: volume falls from 3,000 IOPS burst to IOPS_baseline after credits drain

Detection Signals

disk saturationqueue depthalertlatency spike

Mitigation Strategies

Upgrade to higher-IOPS storage tiercomplexity: low

Move from GP2/GP3 baseline to io2 Block Express (up to 64,000 IOPS, 1,000 MB/s). For AWS: modify the EBS volume type and IOPS parameter. Immediate effect after modification completes. Most effective short-term fix. Ongoing cost increase proportional to provisioned IOPS.

Separate WAL and data to distinct storage volumescomplexity: medium

Configure PostgreSQL with PGDATA on one volume and pg_wal on a separate volume. WAL writes are sequential and high-frequency; separating WAL from data page writes eliminates I/O contention between them. Each volume gets its own IOPS budget.

Tune checkpoint and autovacuum to smooth I/Ocomplexity: low

Set checkpoint_completion_target = 0.9 (spread checkpoint I/O over 90% of the checkpoint interval). Set autovacuum_vacuum_cost_delay = 10ms and autovacuum_vacuum_cost_limit = 200 to throttle autovacuum I/O. These settings reduce I/O peaks at the cost of slightly more sustained background I/O.

Increase work_mem to reduce sort spill to diskcomplexity: medium

Identify queries spilling to disk via pg_stat_statements (temp_blks_read and temp_blks_written > 0). Increase work_mem for sessions executing these queries. A query that sorts in memory generates zero temporary disk I/O. Balance against total memory budget (see memory_pressure_oom).

Recovery Steps

  1. 1.Confirm I/O saturation: iostat -x 1 showing util > 90% or iowait > 30%
  2. 2.Identify top I/O consumers: iotop or pg_stat_bgwriter to find checkpoint/autovacuum vs. query I/O
  3. 3.If checkpoint is the driver: immediately reduce checkpoint_completion_target = 0.9 and set autovacuum_vacuum_cost_delay
  4. 4.If query spill is the driver: set work_mem higher for the offending session temporarily
  5. 5.Short-term relief: upgrade EBS volume IOPS (GP3 IOPS can be increased without downtime)
  6. 6.Post-incident: evaluate storage architecture (separate WAL volume, NVMe) and tune checkpoint settings

Estimated recovery time: Seconds to minutes once the saturating I/O source (checkpoint, autovacuum) is throttled or eliminated. EBS IOPS provisioning change takes effect within minutes. Full architectural fixes (separate WAL volume, NVMe migration) require maintenance windows of 30–60 minutes.

Affected Systems

Patterns

write ahead log cdcevent sourcingshardingmaterialized view

Technologies

postgresqlcassandraelasticsearchmongodbmysqlclickhouse

Basis

Precisely measurable failure mode with exact I/O metrics; EBS characteristics and PostgreSQL I/O patterns are well-documented with specific thresholds. The B-Tree random I/O vs. LSM sequential-write/read-amplification distinction and the ClickHouse scan-and-codec framing are standard, documented storage-engine mechanics (Database Internals; ClickHouse and PostgreSQL/InnoDB documentation).

Sources & Claims

B-Tree engines (PostgreSQL heap plus B-Tree indexes, InnoDB's clustered B-Tree) generate substantial random I/O for index lookups and row fetches, because pages touched by a lookup are scattered non-contiguously across the file

pending

ddia or accepted reference · Alex Petrov, Database Internals, B-Tree Basics and on-disk structures chapters

storage-engine-internals-spine batch 3

LSM engines write memtable flushes and compaction output as sequential append operations, while a point read may need to probe the memtable and multiple SSTables across levels, each an independent I/O, before Bloom filters or the read path can rule a given SSTable out

pending

ddia or accepted reference · Alex Petrov, Database Internals, LSM Trees and Log-Structured Storage chapters

storage-engine-internals-spine batch 3

ClickHouse's MergeTree engine performs large sequential column scans and applies compression codecs (LZ4 by default, or ZSTD/Delta/DoubleDelta) per column, so scan I/O is bounded primarily by post-compression bytes read and by primary-key/skip-index pruning rather than by random seeks

pending

official documentation · ClickHouse documentation, MergeTree table engine and Compression Codecs

storage-engine-internals-spine batch 3

Run This Failure

Blast radius analysis for this failure mode within each scenario that carries it.

Related Architecture Knowledge

Inbound: affects this entity

Vulnerable ToWorkload
time series metrics
Grounded

Time-series metric workloads generate write throughput that can saturate disk I/O: 100,000-1,000,000 data points per second produce continuous sequential write load that exceeds spinning disk capacity and requires NVMe or storage-optimized instances to sustain.

Tradeoffs

  • ·NVMe SSDs are 10-20x more expensive than spinning disks per GB but required for high-throughput time-series
  • ·Write batching (accumulate 1000+ points before writing) amortizes I/O overhead : increases latency from ms to seconds
  • ·Column-oriented storage (ClickHouse, TimescaleDB compression) reduces I/O dramatically but requires columnar query patterns
Full relationship →

Used In Architecture Scenarios

Audit and Compliance Platformhigh

Financial Ledger

An append-only audit log architecture for capturing system actions: user operations, data access events, configuration changes, and financial operations: with cryptographic integrity chaining, immutable storage, and dual-path query serving. PostgreSQL stores the authoritative append-only event log in time-partitioned tables; ClickHouse serves historical aggregate queries and retention analytics; Kafka streams audit events in real time to SIEM integrations and security dashboards; Redis caches hot audit query results for compliance-facing read paths. No record is ever updated or deleted: only inserts are permitted. Each record includes a hash of the previous record, forming a tamper-evident chain verifiable without external tooling.

Geospatial Tracking Platformhigh

Realtime Collaboration

A real-time location tracking platform for moving entities: vehicles, delivery couriers, field workers, and assets: receiving position updates at 1–30 second intervals from thousands of simultaneously tracked objects. Redis geospatial indexes (GEOADD / GEOSEARCH) serve sub-10ms proximity queries against the live position surface; PostgreSQL stores durable entity metadata and historical location records; TimescaleDB stores high-frequency time-series location data with automatic hypertable chunking and retention policies; Kafka streams location events to downstream consumers (dispatch systems, customer tracking apps, analytics pipelines). Geofence evaluation runs at ingestion time: each incoming position update is tested against active geofences for the entity's region, and geofence entry/exit events are emitted as Kafka messages to downstream consumers.

IoT Telemetry Ingestion Platformhigh

Write-Heavy Application

A high-rate device telemetry ingestion architecture designed for millions of devices emitting metrics at 1–60 second intervals. Kafka absorbs device writes as an ingestion buffer, decoupling device-facing ingest endpoints from the storage write path so that downstream storage pressure never propagates back to devices. TimescaleDB provides time-series storage with automatic chunk partitioning by time range, native compression, and continuous aggregate views for rollup queries. ClickHouse serves as the OLAP layer for device fleet analytics queries. Redis caches last-known device state (current readings per device) for real-time alerting queries that must not scan historical storage. Backpressure on the Kafka consumer side prevents storage write throughput from being overwhelmed by burst ingestion events from device reconnect storms.

Observability Platformhigh

Analytics Pipeline

A metrics, logs, and traces ingestion and query platform built to absorb the telemetry output of a production system fleet: including the telemetry volume spikes that accompany the incidents the platform is meant to detect. ClickHouse stores metrics data with automatic time-based rollup via continuous materialized views; TimescaleDB provides complementary time-series storage for high-cardinality alert evaluation; Kafka buffers the ingestion stream against downstream write pressure, decoupling ingest acceptance rate from storage write throughput; Elasticsearch serves log full-text search and structured field filtering; Redis caches dashboard query results and active alert state for sub-100ms alert evaluation latency. The alert engine evaluates threshold and anomaly rules against pre-computed materialized views, not raw data, to bound alert evaluation cost independent of ingestion volume.

Streaming Media Platformhigh

Event-Driven System

A video and audio streaming architecture where content ingestion triggers an async multi-variant transcoding pipeline, CDN delivery handles 95%+ of playback traffic, and Cassandra absorbs the write volume of per-user viewing history. Kafka decouples upload events from transcoding workers; MinIO stores raw and encoded assets; Redis maintains playback session state and view counters. The architecture must handle upload spikes without blocking delivery, and cache cold starts without cascading database load.