ioStats

Return cumulative I/O statistics under 'io', per backend type, object and context (pg_stat_io, PostgreSQL 16+): reads, writes, extends, hits, evictions, reuses, fsyncs and their timings, with a hit percentage.

read-onlyany connectionsweeps replication groupsweeps group

Synopsis

ioStats([backend_type], [context], [object], [pid])

Description

Return cumulative I/O statistics under 'io', per backend type, object and context (pg_stat_io, PostgreSQL 16+): reads, writes, extends, hits, evictions, reuses, fsyncs and their timings, with a hit percentage. This is where backend-written buffers, vacuum's ring-buffer reuse, and bulk read/write I/O become visible separately from the aggregate counters in checkpointStats. Rows with no activity are omitted unless a filter was given.

Given a pid, reports that one backend instead, via pg_stat_get_backend_io, plus its WAL volume under 'wal' -- a backend can be quiet in I/O and still be generating WAL heavily; that requires PostgreSQL 18, since pg_stat_io itself has no pid column. Returns a clear error on PostgreSQL 15 and older, where the view does not exist.

Parameters

backend_type optionalstring
only this backend type, e.g. "client backend", "autovacuum worker", "checkpointer"
context optionalstring
only this I/O context, e.g. "normal", "vacuum", "bulkread", "bulkwrite"
object optionalstring
only this object class, e.g. "relation" or "temp relation"
pid optionalinteger
report this one backend's I/O and WAL instead of the cluster-wide aggregate. PostgreSQL 18 and newer only

Also accepts connection, replication_group, group, role, described once under arguments every tool takes.

Output

pg_stat_io rows per backend type and context. An absent extension or a missing grant is reported as {error, hint} instead.

FieldType
ioarray | null

Scope

This reading is instance-wide -- every database on the same postmaster returns it identically, so asking each of them in turn repeats one answer. The counters here are each server's own, so members of a replication group legitimately disagree and the answer is their sum, not the primary's copy.

Example mocked data

Request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ioStats",
    "arguments": {
      "backend_type": "client backend",
      "object": "relation",
      "context": "normal"
    }
  }
}

Result

{
  "io": [
    {
      "backend_type": "client backend",
      "object": "relation",
      "context": "normal",
      "reads": 8120331,
      "read_time_ms": null,
      "writes": 12044,
      "extends": 30211,
      "hits": 99012003321,
      "evictions": 40221,
      "fsyncs": 0,
      "hit_percent": 99.99,
      "stats_reset": "2026-08-01T00:00:00Z"
    }
  ]
}

Invented values on a fictional shop database, shaped by and checked against this tool's output schema. Real output is returned as structuredContent to clients that negotiate MCP 2025-06-18 or later.

See also

diskUsage, databaseSize, serverSettings, currentActivity, currentLocks, databaseStats, statementStats, wraparoundStatus, progressStats, checkpointStats, tableIOStats, hostCapacity, bufferCacheSummary, bufferCacheContents