This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: pg17-subxact-overflow-logical-decoding-guardrail

PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection

Enforces strict limits on nested subtransactions and savepoints to prevent PGPROC cache overflow (>64 subxacts) and SubtransSLRU lock contention. Eliminates catastrophic replication worker stalling, ReorderBuffer disk spillages, and replication lag during high-throughput Change Data Capture (CDC).

Prohibited Anti-Pattern: Unbounded Iterative Savepoints Inside Long-Lived Transactions Triggering SLRU Thrashing

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection - Enforces strict limits on nested subtransactions and savepoints to prevent PGPROC cache overflow (>64 subxacts) and SubtransSLRU lock contention. Eliminates catastrophic replication worker stalling, ReorderBuffer disk spillages, and replication lag during high-throughput Change Data Capture (CDC).
globs: src/**/*.{ts,tsx,sql}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/pg17-subxact-overflow-logical-decoding-guardrail"
---

# PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unbounded Iterative Savepoints Inside Long-Lived Transactions Triggering SLRU Thrashing

## System Constraints
You are a Principal Database Architect enforcing strict PostgreSQL concurrency patterns for Postgres 17. Subtransactions allocate SubXIDs; exceeding the 64-entry in-memory cache (PGPROC_MAX_CACHED_SUBXIDS) forces PostgreSQL to write to disk-backed SLRU structures (pg_subtrans) and acquire SubtransControlLock on every subsequent snapshot lookup across all backends. Under high-throughput logical replication (CDC via wal2json, pgoutput, or Debezium), subxact overflow causes massive ReorderBuffer memory exhaustion, serializes replication workers, and triggers unrecoverable replication lag. You must reject any ORM or raw SQL code nesting savepoints or transaction-level exception handling loops within bulk transactional workloads.

## Strict Guidelines
- Engineers MUST ALWAYS decompose bulk operations into discrete, top-level transactional batches rather than nesting savepoints inside a loop.
- Engineers MUST NOT exceed a subtransaction depth of 1, and NEVER accumulate more than 64 SubXIDs in any single database session.
- Code SHOULD handle record-level errors using set-based SQL constructs (such as ON CONFLICT DO NOTHING/UPDATE) rather than PL/pgSQL EXCEPTION blocks or ORM nested transactions.
- Services MUST isolate high-write CDC target tables from patterns that trigger savepoints to protect Postgres 17 logical decoding worker throughput.
- Components NEVER execute iterative nested transaction blocks (e.g., Prisma tx.$transaction, TypeORM savepoints, or raw SAVEPOINT) inside unbounded iteration.

## Bad vs Good Implementations
### Batch Ingestion with Error Handling: Savepoint Loop vs Set-Based Chunking

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using nested transactions or savepoints inside an iteration causes the transaction to exceed PGPROC_MAX_CACHED_SUBXIDS (64). The subxid array overflows into pg_subtrans, creating heavy SubtransControlLock contention for all concurrent queries checking visibility and forcing logical replication decoders to spill transactions to disk.
```typescript
import { PrismaClient } from '@prisma/client';

export async function ingestRecordsBad(prisma: PrismaClient, items: Array<{ id: string; payload: string }>) {
  // Anti-pattern: Outer transaction with nested savepoints per iteration
  return await prisma.$transaction(async (tx) => {
    for (const item of items) {
      try {
        // In nested transaction/savepoint mode, this creates a SAVEPOINT
        // If items.length > 64, PGPROC subxid cache overflows immediately.
        // Logical decoding workers stall serializing ReorderBuffer snapshots.
        await tx.$transaction(async (nestedTx) => {
          await nestedTx.eventLog.create({ data: item });
        });
      } catch (err) {
        // Rolls back to savepoint, thrashing SubtransSLRU under concurrent read load
        console.warn(`Failed to insert item ${item.id}`, err);
      }
    }
  });
}
```

#### Production Standard (Correct)
> **Standard**: By chunking work into distinct top-level transactions and employing set-based skipDuplicates (ON CONFLICT DO NOTHING), zero savepoints and zero subxids are allocated. The PGPROC cache never overflows, pg_subtrans remains untouched, and Postgres 17 logical decoding streams WAL changes with optimal in-memory throughput.
```typescript
import { PrismaClient, Prisma } from '@prisma/client';

const BATCH_SIZE = 500;

export async function ingestRecordsGood(prisma: PrismaClient, items: Array<{ id: string; payload: string }>) {
  // Invariant Guardrail: Chunk into bounded top-level transactions with set-based resolution
  for (let i = 0; i < items.length; i += BATCH_SIZE) {
    const chunk = items.slice(i, i + BATCH_SIZE);

    // Top-level independent transaction without subtransactions/savepoints
    await prisma.$transaction(async (tx) => {
      // Use native ON CONFLICT rather than savepoint/exception catch
      await tx.eventLog.createMany({
        data: chunk,
        skipDuplicates: true,
      });
    }, {
      isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted,
      timeout: 10000,
    });
  }
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection

PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection defines an industrial-grade behavioral standard for backend engineering. Enforces strict limits on nested subtransactions and savepoints to prevent PGPROC cache overflow (>64 subxacts) and SubtransSLRU lock contention. Eliminates catastrophic replication worker stalling, ReorderBuffer disk spillages, and replication lag during high-throughput Change Data Capture (CDC). 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: Unbounded Iterative Savepoints Inside Long-Lived Transactions Triggering SLRU Thrashing 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 DriftUnbounded Iterative Savepoints Inside Long-Lived Transactions Triggering SLRU ThrashingCritical
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 decompose bulk operations into discrete, top-level transactional batches rather than nesting savepoints inside a loop.

Engineers MUST ALWAYS decompose bulk operations into discrete, top-level transactional batches rather than nesting savepoints inside a loop.

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 NOT exceed a subtransaction depth of 1, and NEVER accumulate more than 64 SubXIDs in any single database session.

Engineers MUST NOT exceed a subtransaction depth of 1, and NEVER accumulate more than 64 SubXIDs in any single database session.

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

Code SHOULD handle record-level errors using set-based SQL constructs (such as ON CONFLICT DO NOTHING/UPDATE) rather than PL/pgSQL EXCEPTION blocks or ORM nested transactions.

Code SHOULD handle record-level errors using set-based SQL constructs (such as ON CONFLICT DO NOTHING/UPDATE) rather than PL/pgSQL EXCEPTION blocks or ORM nested transactions.

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

Services MUST isolate high-write CDC target tables from patterns that trigger savepoints to protect Postgres 17 logical decoding worker throughput.

Services MUST isolate high-write CDC target tables from patterns that trigger savepoints to protect Postgres 17 logical decoding worker throughput.

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 NEVER execute iterative nested transaction blocks (e.g., Prisma tx.$transaction, TypeORM savepoints, or raw SAVEPOINT) inside unbounded iteration.

Components NEVER execute iterative nested transaction blocks (e.g., Prisma tx.$transaction, TypeORM savepoints, or raw SAVEPOINT) inside unbounded iteration.

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 PostgreSQL 17 Subtransaction Snapshot Overflow & Logical Decoding Protection critical for AI coding assistants?

Enforces strict limits on nested subtransactions and savepoints to prevent PGPROC cache overflow (>64 subxacts) and SubtransSLRU lock contention. Eliminates catastrophic replication worker stalling, ReorderBuffer disk spillages, and replication lag during high-throughput Change Data Capture (CDC). 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 (Unbounded Iterative Savepoints Inside Long-Lived Transactions Triggering SLRU Thrashing) 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

PostgreSQL