This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: pgvector-hnsw-memory-ceiling-guardrail

Postgres 17 pgvector HNSW Graph Memory-Ceiling Invariants

Enforces deterministic bounded memory allocations during HNSW index construction and query-time iterative graph traversals on PostgreSQL 17. Guarantees that concurrent streaming ingestion pipelines configure maintenance_work_mem and hnsw.ef_search within explicit session-isolated bounds to prevent uncoordinated kernel OOM killer events on database primaries.

Prohibited Anti-Pattern: Global Unbounded HNSW Index Creation and Iterative Traversals During Streaming Ingestion

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Postgres 17 pgvector HNSW Graph Memory-Ceiling Invariants - Enforces deterministic bounded memory allocations during HNSW index construction and query-time iterative graph traversals on PostgreSQL 17. Guarantees that concurrent streaming ingestion pipelines configure maintenance_work_mem and hnsw.ef_search within explicit session-isolated bounds to prevent uncoordinated kernel OOM killer events on database primaries.
globs: src/database/**/*.ts, src/migrations/**/*.ts, src/repositories/**/*.ts, src/services/indexing/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/pgvector-hnsw-memory-ceiling-guardrail"
---

# Postgres 17 pgvector HNSW Graph Memory-Ceiling Invariants

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Global Unbounded HNSW Index Creation and Iterative Traversals During Streaming Ingestion

## System Constraints
You are a Principal Database Architect enforcing strict memory-ceiling invariants for Postgres 17 and pgvector (v0.7.0+) HNSW index operations. You must prevent Out-Of-Memory (OOM) events and connection exhaustion caused by unbounded HNSW index builds and iterative graph traversals. Ensure that dynamic DDL statements execute concurrently with safe, localized maintenance_work_mem ceilings, that vector indexing is scheduled asynchronously or isolated from the primary OLTP ingestion path, and that runtime session parameters such as hnsw.ef_search are strictly clamped.

## Strict Guidelines
- Engineers MUST ALWAYS isolate HNSW index creation inside a dedicated maintenance connection using SET LOCAL maintenance_work_mem to an explicit bounded threshold (e.g., 2GB-4GB based on available node RAM) rather than relying on system-wide defaults.
- Engineers MUST ALWAYS execute CREATE INDEX CONCURRENTLY when generating HNSW indexes on active tables to prevent catastrophic catalog locks and streaming ingestion stalls.
- Engineers MUST NOT execute HNSW index builds within application transaction blocks carrying ongoing bulk INSERT/UPDATE workloads.
- Code SHOULD dynamically size max_parallel_maintenance_workers in the builder session such that parallel worker count multiplied by maintenance_work_mem never exceeds 40% of total host unreserved RAM.
- Services MUST enforce strict validation on runtime search parameters, clamping hnsw.ef_search between 16 and 400 within localized transaction scopes to prevent query-time memory explosions during iterative graph scans.
- Components NEVER execute raw DDL string interpolations for HNSW indexing parameters (m, ef_construction) without validating against an allowed numeric whitelist.

## Bad vs Good Implementations
### Unbounded HNSW Index Creation vs. Session-Bounded Concurrent Build

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Executing HNSW index creation inside a global transaction locks the table against writes, while omitting a local maintenance_work_mem cap and running without CONCURRENTLY risks kernel OOM panics when default worker memory is multiplied across maintenance workers.
```typescript
import { Pool } from 'pg';

export async function createVectorIndex(pool: Pool, tableName: string) {
  // Anti-pattern: Global memory context, blocking lock on primary, unconstrained ef_construction
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query(`
      CREATE INDEX idx_items_embedding 
      ON ${tableName} 
      USING hnsw (embedding vector_cosine_ops) 
      WITH (m = 64, ef_construction = 512);
    `);
    await client.query('COMMIT');
  } finally {
    client.release();
  }
}
```

#### Production Standard (Correct)
> **Standard**: Uses CREATE INDEX CONCURRENTLY without an enclosing transaction, rigorously scopes maintenance_work_mem and worker concurrency to protect total host RAM, resets session state before returning the client to the pool, and whitelists table identifiers.
```typescript
import { Pool } from 'pg';

interface HnswIndexConfig {
  m: 16 | 24 | 32 | 48 | 64;
  efConstruction: 64 | 128 | 256;
  maintenanceWorkMemMb: number;
}

export async function createBoundedHnswIndex(
  pool: Pool,
  safeTableName: 'documents' | 'embeddings',
  config: HnswIndexConfig = { m: 16, efConstruction: 128, maintenanceWorkMemMb: 2048 }
): Promise<void> {
  // Invariant: Concurrent DDL cannot run in a multi-statement transaction
  const client = await pool.connect();
  try {
    // Cap memory strictly for this dedicated maintenance session
    await client.query(`SET maintenance_work_mem = '${config.maintenanceWorkMemMb}MB'`);
    await client.query('SET max_parallel_maintenance_workers = 2');

    await client.query(`
      CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_${safeTableName}_embedding_hnsw
      ON ${safeTableName}
      USING hnsw (embedding vector_cosine_ops)
      WITH (m = ${config.m}, ef_construction = ${config.efConstruction})
    `);
  } finally {
    // Reset session settings prior to returning client to the pool
    await client.query('RESET maintenance_work_mem');
    await client.query('RESET max_parallel_maintenance_workers');
    client.release();
  }
}
```

### Iterative Vector Search Memory Clamping

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Permits arbitrary user values for hnsw.ef_search without bounds checking, leaks state across shared connection pool sessions via raw multi-command execution, and risks thread exhaustion on deep graph traversals.
```typescript
import { Pool } from 'pg';

export async function searchSimilarVectors(pool: Pool, vector: number[], efSearch: number) {
  // Anti-pattern: Trusting user-provided efSearch globally sets connection parameters,
  // causing unbounded memory allocations during iterative scans.
  return pool.query(
    `SET hnsw.ef_search = ${efSearch}; 
     SELECT id, embedding <=> $1 AS distance 
     FROM documents 
     ORDER BY distance LIMIT 10;`,
    [JSON.stringify(vector)]
  );
}
```

#### Production Standard (Correct)
> **Standard**: Enforces deterministic boundaries on hnsw.ef_search, encapsulates runtime parameters within a READ ONLY transaction via SET LOCAL, passes query values safely through parameterized SQL, and releases pool connections clean of state leakage.
```typescript
import { Pool, PoolClient } from 'pg';

const MIN_EF_SEARCH = 16;
const MAX_EF_SEARCH = 200;

export async function searchSimilarVectorsBounded(
  pool: Pool,
  vector: number[],
  requestedEfSearch: number = 40,
  limit: number = 10
): Promise<{ id: string; distance: number }[]> {
  // Invariant: Strictly clamp iterative graph search memory overhead
  const clampedEfSearch = Math.max(MIN_EF_SEARCH, Math.min(requestedEfSearch, MAX_EF_SEARCH));
  const boundedLimit = Math.max(1, Math.min(limit, 100));
  const vectorString = `[${vector.join(',')}]`;

  const client: PoolClient = await pool.connect();
  try {
    await client.query('BEGIN READ ONLY');
    // SET LOCAL limits scope exclusively to this transaction block
    await client.query('SET LOCAL hnsw.ef_search = $1', [clampedEfSearch]);
    
    const result = await client.query<{ id: string; distance: number }>(
      `SELECT id, (embedding <=> $1::vector) AS distance
       FROM documents
       ORDER BY embedding <=> $1::vector
       LIMIT $2`,
      [vectorString, boundedLimit]
    );
    
    await client.query('COMMIT');
    return result.rows;
  } catch (error) {
    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 pgvector HNSW Graph Memory-Ceiling Invariants

Postgres 17 pgvector HNSW Graph Memory-Ceiling Invariants defines an industrial-grade behavioral standard for backend engineering. Enforces deterministic bounded memory allocations during HNSW index construction and query-time iterative graph traversals on PostgreSQL 17. Guarantees that concurrent streaming ingestion pipelines configure maintenance_work_mem and hnsw.ef_search within explicit session-isolated bounds to prevent uncoordinated kernel OOM killer events on database primaries. 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: Global Unbounded HNSW Index Creation and Iterative Traversals During Streaming Ingestion 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 DriftGlobal Unbounded HNSW Index Creation and Iterative Traversals During Streaming IngestionCritical
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 isolate HNSW index creation inside a dedicated maintenance connection using SET LOCAL maintenance_work_mem to an explicit bounded threshold (e.g., 2GB-4GB based on available node RAM) rather than relying on system-wide defaults.

Engineers MUST ALWAYS isolate HNSW index creation inside a dedicated maintenance connection using SET LOCAL maintenance_work_mem to an explicit bounded threshold (e.g., 2GB-4GB based on available node RAM) rather than relying on system-wide defaults.

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 ALWAYS execute CREATE INDEX CONCURRENTLY when generating HNSW indexes on active tables to prevent catastrophic catalog locks and streaming ingestion stalls.

Engineers MUST ALWAYS execute CREATE INDEX CONCURRENTLY when generating HNSW indexes on active tables to prevent catastrophic catalog locks and streaming ingestion stalls.

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

Engineers MUST NOT execute HNSW index builds within application transaction blocks carrying ongoing bulk INSERT/UPDATE workloads.

Engineers MUST NOT execute HNSW index builds within application transaction blocks carrying ongoing bulk INSERT/UPDATE workloads.

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

Code SHOULD dynamically size max_parallel_maintenance_workers in the builder session such that parallel worker count multiplied by maintenance_work_mem never exceeds 40% of total host unreserved RAM.

Code SHOULD dynamically size max_parallel_maintenance_workers in the builder session such that parallel worker count multiplied by maintenance_work_mem never exceeds 40% of total host unreserved RAM.

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 enforce strict validation on runtime search parameters, clamping hnsw.ef_search between 16 and 400 within localized transaction scopes to prevent query-time memory explosions during iterative graph scans.

Services MUST enforce strict validation on runtime search parameters, clamping hnsw.ef_search between 16 and 400 within localized transaction scopes to prevent query-time memory explosions during iterative graph scans.

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.
6

Components NEVER execute raw DDL string interpolations for HNSW indexing parameters (m, ef_construction) without validating against an allowed numeric whitelist.

Components NEVER execute raw DDL string interpolations for HNSW indexing parameters (m, ef_construction) without validating against an allowed numeric whitelist.

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 pgvector HNSW Graph Memory-Ceiling Invariants critical for AI coding assistants?

Enforces deterministic bounded memory allocations during HNSW index construction and query-time iterative graph traversals on PostgreSQL 17. Guarantees that concurrent streaming ingestion pipelines configure maintenance_work_mem and hnsw.ef_search within explicit session-isolated bounds to prevent uncoordinated kernel OOM killer events on database primaries. 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 (Global Unbounded HNSW Index Creation and Iterative Traversals During Streaming Ingestion) 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