This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: postgres-17-json-table-memory-quota-guardrail

Postgres 17 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail

Enforces strict session-level memory quotas (`work_mem`, `statement_timeout`) and deterministic batching constraints when projecting nested JSONB event payloads using PostgreSQL 17's SQL/JSON `JSON_TABLE` function. Prevents unconstrained JSON path navigation and unbounded array flattening from exhausting backend process memory (`OOM Killer`) during high-throughput ingestion pipelines.

Prohibited Anti-Pattern: Unbounded JSON_TABLE execution on multi-megabyte payloads under default global work_mem without transaction-level quotas or chunking

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: "Postgres 17 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail - Enforces strict session-level memory quotas (`work_mem`, `statement_timeout`) and deterministic batching constraints when projecting nested JSONB event payloads using PostgreSQL 17's SQL/JSON `JSON_TABLE` function. Prevents unconstrained JSON path navigation and unbounded array flattening from exhausting backend process memory (`OOM Killer`) during high-throughput ingestion pipelines."
globs: "src/database/**/*.ts, src/repositories/**/*.ts, src/services/ingestion/**/*.ts, src/migrations/**/*.sql"
alwaysApply: true
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/postgres-17-json-table-memory-quota-guardrail"
---

# Postgres 17 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unbounded JSON_TABLE execution on multi-megabyte payloads under default global work_mem without transaction-level quotas or chunking

## System Constraints
You are a Principal Database Architect enforcing strict memory bounds and transactional safety on PostgreSQL 17 JSON_TABLE operations. Mandate localized session quotas, explicit plan node memory caps, mandatory batch-chunking, and strict path-expression evaluation rules to prevent process OOM crashes and server degradation during semi-structured ingestion.

## Strict Guidelines
- Engineers MUST ALWAYS set explicit transaction-local `work_mem` and `statement_timeout` parameters via `SET LOCAL` prior to executing queries containing `JSON_TABLE` over multi-row or nested JSONB structures.
- Engineers MUST NOT execute `JSON_TABLE` directly over unbounded raw ingest tables; ingestion MUST process payloads in deterministic chunks (maximum 500 records or 5MB aggregated payload per batch).
- Queries MUST explicitly specify data types and column lengths inside the `COLUMNS (...)` clause of `JSON_TABLE`, avoiding unconstrained `TEXT` conversions and omitting unsupported wildcards in JSON path expressions.
- Engineers MUST utilize the `PASSING` clause with explicit typed parameters instead of string concatenation or dynamic interpolation inside JSON path expressions to allow the query planner to cache extraction paths.
- Services MUST implement circuit breakers that trap `insufficient_memory` (SQLSTATE 53200) and `query_canceled` (SQLSTATE 57014) to dynamically reduce batch size before retrying ingestion.

## Bad vs Good Implementations
### Unbounded JSON_TABLE vs. Transaction-Bounded Chunked Ingestion

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The bad example sends unbounded JSON arrays into JSON_TABLE without transaction-local memory controls (SET LOCAL work_mem), without timeouts, and using unbounded TEXT types with Cartesian nested path expansions. This quickly exhausts PostgreSQL backend memory on large payloads.
```typescript
import { Pool } from 'pg';

export async function ingestEventBatch(pool: Pool, rawPayloads: Array<{ id: string; data: unknown }>): Promise<void> {
  // ANTI-PATTERN: Direct unbounded JSON_TABLE query using default pool settings
  // Risk: Nested JSON path evaluations explode backend RSS memory; uncontained allocation causes OOM kill
  await pool.query(`
    INSERT INTO normalized_events (event_id, metric_name, metric_value, timestamp)
    SELECT jt.event_id, jt.metric_name, jt.metric_value, jt.recorded_at
    FROM UNNEST($1::jsonb[]) AS batch(val),
    JSON_TABLE(
      batch.val,
      '$.events[*]' COLUMNS (
        event_id TEXT PATH '$.id',
        metric_name TEXT PATH '$.metrics[*].name',
        metric_value NUMERIC PATH '$.metrics[*].val',
        recorded_at TIMESTAMPTZ PATH '$.timestamp'
      )
    ) AS jt;
  `, [JSON.stringify(rawPayloads.map(p => p.data))]);
}
```

#### Production Standard (Correct)
> **Standard**: The good example chunks the ingestion into deterministically sized sets (250 records), wraps execution in a transaction, applies `SET LOCAL work_mem = '32MB'` and a `statement_timeout`, uses precise column data types (`VARCHAR(64)`, `NUMERIC(18,4)`), and leverages SQL/JSON standard `NESTED PATH` projection with error handling.
```typescript
import { Pool, PoolClient } from 'pg';

interface RawEventBatch {
  id: string;
  data: Record<string, unknown>;
}

const BATCH_CHUNK_SIZE = 250;

export async function ingestEventBatch(pool: Pool, rawPayloads: RawEventBatch[]): Promise<void> {
  for (let i = 0; i < rawPayloads.length; i += BATCH_CHUNK_SIZE) {
    const chunk = rawPayloads.slice(i, i + BATCH_CHUNK_SIZE);
    const client: PoolClient = await pool.connect();

    try {
      await client.query('BEGIN;');

      // Enforce localized memory quotas and circuit-breaker timeout
      await client.query("SET LOCAL work_mem = '32MB';");
      await client.query("SET LOCAL statement_timeout = '15s';");

      const jsonPayload = JSON.stringify(chunk.map((c) => c.data));

      await client.query(`
        INSERT INTO normalized_events (event_id, metric_name, metric_value, timestamp)
        SELECT 
          jt.event_id,
          jt.metric_name,
          jt.metric_value,
          jt.recorded_at
        FROM JSON_TABLE(
          $1::jsonb,
          '$[*]' COLUMNS (
            event_id VARCHAR(64) PATH '$.id' ERROR ON ERROR,
            NESTED PATH '$.metrics[*]' COLUMNS (
              metric_name VARCHAR(128) PATH '$.name',
              metric_value NUMERIC(18, 4) PATH '$.val'
            ),
            recorded_at TIMESTAMPTZ PATH '$.timestamp'
          )
        ) AS jt;
      `, [jsonPayload]);

      await client.query('COMMIT;');
    } catch (error: unknown) {
      await client.query('ROLLBACK;');
      throw error;
    } finally {
      client.release();
    }
  }
}
```

Recommended MCP Servers (mcp-serverlist.com)

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

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Postgres 17 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail

Postgres 17 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail defines an industrial-grade behavioral standard for backend engineering. Enforces strict session-level memory quotas (`work_mem`, `statement_timeout`) and deterministic batching constraints when projecting nested JSONB event payloads using PostgreSQL 17's SQL/JSON `JSON_TABLE` function. Prevents unconstrained JSON path navigation and unbounded array flattening from exhausting backend process memory (`OOM Killer`) during high-throughput ingestion pipelines. 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 JSON_TABLE execution on multi-megabyte payloads under default global work_mem without transaction-level quotas or chunking 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 JSON_TABLE execution on multi-megabyte payloads under default global work_mem without transaction-level quotas or chunkingCritical
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 set explicit transaction-local `work_mem` and `statement_timeout` parameters via `SET LOCAL` prior to executing queries containing `JSON_TABLE` over multi-row or nested JSONB structures.

Engineers MUST ALWAYS set explicit transaction-local `work_mem` and `statement_timeout` parameters via `SET LOCAL` prior to executing queries containing `JSON_TABLE` over multi-row or nested JSONB structures.

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 execute `JSON_TABLE` directly over unbounded raw ingest tables

Engineers MUST NOT execute `JSON_TABLE` directly over unbounded raw ingest tables; ingestion MUST process payloads in deterministic chunks (maximum 500 records or 5MB aggregated payload per batch).

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

Queries MUST explicitly specify data types and column lengths inside the `COLUMNS (...)` clause of `JSON_TABLE`, avoiding unconstrained `TEXT` conversions and omitting unsupported wildcards in JSON path expressions.

Queries MUST explicitly specify data types and column lengths inside the `COLUMNS (...)` clause of `JSON_TABLE`, avoiding unconstrained `TEXT` conversions and omitting unsupported wildcards in JSON path expressions.

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 utilize the `PASSING` clause with explicit typed parameters instead of string concatenation or dynamic interpolation inside JSON path expressions to allow the query planner to cache extraction paths.

Engineers MUST utilize the `PASSING` clause with explicit typed parameters instead of string concatenation or dynamic interpolation inside JSON path expressions to allow the query planner to cache extraction paths.

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

Services MUST implement circuit breakers that trap `insufficient_memory` (SQLSTATE 53200) and `query_canceled` (SQLSTATE 57014) to dynamically reduce batch size before retrying ingestion.

Services MUST implement circuit breakers that trap `insufficient_memory` (SQLSTATE 53200) and `query_canceled` (SQLSTATE 57014) to dynamically reduce batch size before retrying ingestion.

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 JSON_TABLE Memory Quota and Streaming Ingestion Guardrail critical for AI coding assistants?

Enforces strict session-level memory quotas (`work_mem`, `statement_timeout`) and deterministic batching constraints when projecting nested JSONB event payloads using PostgreSQL 17's SQL/JSON `JSON_TABLE` function. Prevents unconstrained JSON path navigation and unbounded array flattening from exhausting backend process memory (`OOM Killer`) during high-throughput ingestion pipelines. 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 JSON_TABLE execution on multi-megabyte payloads under default global work_mem without transaction-level quotas or chunking) 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