This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
devopscritical PriorityID: postgres-17-pg-stat-io-budget-throttling-standard

Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling

Enforces real-time per-backend I/O budget monitoring and Linux cgroup v2 block I/O throttling derived from Postgres 17 pg_stat_io metrics. Prevents NVMe/EBS disk controller saturation and backend starvation by programmatically calculating differential read, write, and extend operations and applying kernel-level IOPS caps to runaway backend worker PIDs.

Prohibited Anti-Pattern: Unregulated Storage Controller Saturation via Unthrottled Backend I/O Spikes

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling - Enforces real-time per-backend I/O budget monitoring and Linux cgroup v2 block I/O throttling derived from Postgres 17 pg_stat_io metrics. Prevents NVMe/EBS disk controller saturation and backend starvation by programmatically calculating differential read, write, and extend operations and applying kernel-level IOPS caps to runaway backend worker PIDs.
globs: infra/**/*.{ts,js}, src/daemon/**/*.{ts,js}, src/telemetry/**/*.{ts,js}, scripts/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/postgres-17-pg-stat-io-budget-throttling-standard"
---

# Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling

> **Severity**: CRITICAL | **Category**: devops
> **Anti-Pattern Warning**: Unregulated Storage Controller Saturation via Unthrottled Backend I/O Spikes

## System Constraints
You are a Principal Software Architect and DevOps Rules Author. You must enforce the Postgres 17 pg_stat_io Budget Throttling Standard. Uncontrolled disk read/write/extend storms lead to storage queue starvation, multi-second query latencies, and EBS burst depletion. You must enforce automated sampling of Postgres 17 pg_stat_io deltas, PID-to-cgroup correlation, and proactive kernel-level enforcement via Linux cgroups v2 io.max controls.

## Strict Guidelines
- Engineers MUST ALWAYS sample pg_stat_io metrics via differential snapshots over bounded intervals (e.g., 1000ms) rather than accumulating raw counters.
- Engineers MUST correlate pg_stat_io backend context and target metrics (reads, writes, extends, fsyncs) with pg_stat_activity to pinpoint the exact OS process IDs (PIDs).
- Services MUST apply Linux cgroups v2 `io.max` controls (IOPS or byte throughput limits) dynamically to the target backend's cgroup slice when observed I/O exceeds provisioned budget thresholds.
- Engineers MUST NOT depend solely on application-level timeouts or PostgreSQL's internal `vacuum_cost_limit`, which fail to throttle sequential table scans or unbounded temp relation spills.
- Components MUST restore baseline cgroups v2 `io.max` allocations ('max max') once differential I/O metrics drop below the target low watermark for two consecutive sampling windows.

## Bad vs Good Implementations
### Postgres 17 pg_stat_io Delta Monitor and Dynamic cgroup v2 Throttler

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: This implementation queries absolute, cumulative pg_stat_io numbers without calculating rates over time, fails to identify individual operating system backend PIDs, and only emits a log statement without enforcing kernel-level block I/O limits, allowing rogue backends to saturate the disk controller.
```typescript
// Naive, passive monitoring that detects I/O spikes after disk exhaustion without kernel intervention
import { Client } from 'pg';

interface RawIoRow {
  backend_type: string;
  reads: string;
}

export async function monitorPostgresIo(client: Client): Promise<void> {
  // Anti-pattern: Queries cumulative counters without temporal deltas
  const res = await client.query<RawIoRow>('SELECT backend_type, reads FROM pg_stat_io;');
  for (const row of res.rows) {
    if (parseInt(row.reads, 10) > 1_000_000) {
      // Anti-pattern: Merely logging an alert while controller queue saturates
      console.warn(`High cumulative reads detected on ${row.backend_type}: ${row.reads}`);
    }
  }
}
```

#### Production Standard (Correct)
> **Standard**: This standard uses Postgres 17 pg_stat_io metrics paired with active backend PIDs from pg_stat_activity to compute true per-second differential IOPS (reads, writes, extends). When an individual backend breaches the configured budget, it intervenes directly at the OS layer via Linux cgroups v2 (`io.max`), restricting the backend process's storage access until throughput normalizes.
```typescript
// Production-grade: Differential pg_stat_io sampling and Linux cgroup v2 io.max actuation
import { promises as fs } from 'node:fs';
import { Client } from 'pg';

interface BackendIoSnapshot {
  pid: number;
  backendType: string;
  ioTarget: string;
  totalOps: number;
  timestamp: number;
}

interface MetricRow {
  pid: number;
  backend_type: string;
  target: string;
  total_ops: string;
}

const CGROUP_ROOT = '/sys/fs/cgroup/system.slice';
const IOPS_BUDGET_LIMIT = 4000; // Max allowed IOPS per backend before throttling
const THROTTLED_IOPS_CAP = 1200;
const MAJOR_MINOR_DEV = '259:0'; // Target block device (e.g., nvme0n1)

export class PostgresIoThrottler {
  private snapshots = new Map<number, BackendIoSnapshot>();

  constructor(private readonly client: Client) {}

  public async evaluateAndThrottle(): Promise<void> {
    const now = Date.now();
    // Postgres 17 pg_stat_io correlated with pg_stat_activity to bind PID to I/O target
    const query = `
      SELECT 
        a.pid,
        s.backend_type,
        s.target,
        (s.reads + s.writes + s.extends) AS total_ops
      FROM pg_stat_io s
      JOIN pg_stat_activity a ON a.backend_type = s.backend_type
      WHERE a.state = 'active' AND a.pid <> pg_backend_pid();
    `;

    const { rows } = await this.client.query<MetricRow>(query);

    for (const row of rows) {
      const pid = Number(row.pid);
      const totalOps = Number(row.total_ops);
      const prev = this.snapshots.get(pid);

      if (prev) {
        const elapsedSec = (now - prev.timestamp) / 1000;
        if (elapsedSec >= 1.0) {
          const currentIops = (totalOps - prev.totalOps) / elapsedSec;
          if (currentIops > IOPS_BUDGET_LIMIT) {
            await this.enforceKernelCgroupThrottle(pid, THROTTLED_IOPS_CAP);
          } else if (currentIops < (IOPS_BUDGET_LIMIT * 0.5)) {
            await this.resetKernelCgroupThrottle(pid);
          }
        }
      }

      this.snapshots.set(pid, {
        pid,
        backendType: row.backend_type,
        ioTarget: row.target,
        totalOps,
        timestamp: now,
      });
    }
  }

  private async enforceKernelCgroupThrottle(pid: number, iopsCap: number): Promise<void> {
    const cgroupPath = `${CGROUP_ROOT}/postgresql-backend-${pid}.scope/io.max`;
    try {
      // Writes cgroup v2 format: '<major>:<minor> riops=<n> wiops=<n>'
      const rule = `${MAJOR_MINOR_DEV} riops=${iopsCap} wiops=${iopsCap}`;
      await fs.writeFile(cgroupPath, rule, { flag: 'w' });
    } catch (err) {
      // Gracefully handle backends terminating during control loop
      if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
        throw err;
      }
    }
  }

  private async resetKernelCgroupThrottle(pid: number): Promise<void> {
    const cgroupPath = `${CGROUP_ROOT}/postgresql-backend-${pid}.scope/io.max`;
    try {
      const rule = `${MAJOR_MINOR_DEV} riops=max wiops=max`;
      await fs.writeFile(cgroupPath, rule, { flag: 'w' });
    } catch (err) {
      if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
        throw err;
      }
    }
  }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling

Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling defines an industrial-grade behavioral standard for devops engineering. Enforces real-time per-backend I/O budget monitoring and Linux cgroup v2 block I/O throttling derived from Postgres 17 pg_stat_io metrics. Prevents NVMe/EBS disk controller saturation and backend starvation by programmatically calculating differential read, write, and extend operations and applying kernel-level IOPS caps to runaway backend worker PIDs. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unregulated Storage Controller Saturation via Unthrottled Backend I/O Spikes Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnregulated Storage Controller Saturation via Unthrottled Backend I/O SpikesCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS sample pg_stat_io metrics via differential snapshots over bounded intervals (e.g., 1000ms) rather than accumulating raw counters.

Engineers MUST ALWAYS sample pg_stat_io metrics via differential snapshots over bounded intervals (e.g., 1000ms) rather than accumulating raw counters.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST correlate pg_stat_io backend context and target metrics (reads, writes, extends, fsyncs) with pg_stat_activity to pinpoint the exact OS process IDs (PIDs).

Engineers MUST correlate pg_stat_io backend context and target metrics (reads, writes, extends, fsyncs) with pg_stat_activity to pinpoint the exact OS process IDs (PIDs).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST apply Linux cgroups v2 `io.max` controls (IOPS or byte throughput limits) dynamically to the target backend's cgroup slice when observed I/O exceeds provisioned budget thresholds.

Services MUST apply Linux cgroups v2 `io.max` controls (IOPS or byte throughput limits) dynamically to the target backend's cgroup slice when observed I/O exceeds provisioned budget thresholds.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST NOT depend solely on application-level timeouts or PostgreSQL's internal `vacuum_cost_limit`, which fail to throttle sequential table scans or unbounded temp relation spills.

Engineers MUST NOT depend solely on application-level timeouts or PostgreSQL's internal `vacuum_cost_limit`, which fail to throttle sequential table scans or unbounded temp relation spills.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components MUST restore baseline cgroups v2 `io.max` allocations ('max max') once differential I/O metrics drop below the target low watermark for two consecutive sampling windows.

Components MUST restore baseline cgroups v2 `io.max` allocations ('max max') once differential I/O metrics drop below the target low watermark for two consecutive sampling windows.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Postgres 17 pg_stat_io Real-Time Backend I/O Budget Throttling critical for AI coding assistants?

Enforces real-time per-backend I/O budget monitoring and Linux cgroup v2 block I/O throttling derived from Postgres 17 pg_stat_io metrics. Prevents NVMe/EBS disk controller saturation and backend starvation by programmatically calculating differential read, write, and extend operations and applying kernel-level IOPS caps to runaway backend worker PIDs. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unregulated Storage Controller Saturation via Unthrottled Backend I/O Spikes) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Postgres