This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: postgresql-17-concurrent-merge-partition-deadlock-guardrail

PostgreSQL 17 Concurrent MERGE Isolation and Partition Lock Contention Standard

Prevents partition-level lock contention, write serialization anomalies (SQLSTATE 40001), and cross-transaction deadlocks (SQLSTATE 40P01) during concurrent upsert workloads on PostgreSQL 17 partitioned tables. Enforces deterministic tuple ordering, targeted leaf partition routing, and bounded exponential backoff policies.

Prohibited Anti-Pattern: Unordered Ingestion into Root Partition Tables via Concurrent MERGE Triggering Deadlocks

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: PostgreSQL 17 Concurrent MERGE Isolation and Partition Lock Contention Standard - Prevents partition-level lock contention, write serialization anomalies (SQLSTATE 40001), and cross-transaction deadlocks (SQLSTATE 40P01) during concurrent upsert workloads on PostgreSQL 17 partitioned tables. Enforces deterministic tuple ordering, targeted leaf partition routing, and bounded exponential backoff policies.
globs: src/**/*.repository.ts, src/**/*.dao.ts, src/**/*.service.ts, src/database/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/postgresql-17-concurrent-merge-partition-deadlock-guardrail"
---

# PostgreSQL 17 Concurrent MERGE Isolation and Partition Lock Contention Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unordered Ingestion into Root Partition Tables via Concurrent MERGE Triggering Deadlocks

## System Constraints
You are a Principal Database Architect enforcing concurrency invariants for high-throughput PostgreSQL 17 ingestion pipelines. You mandate that concurrent MERGE statements targeting partitioned tables MUST employ deterministic record sorting (by partition key and primary/unique key) to prevent inverted lock acquisitions, isolate leaf partition writes when partition boundaries are uniform, forbid partition key mutation during MATCHED updates, and wrap write operations in explicit SQLSTATE 40P01/40001 retry harnesses.

## Strict Guidelines
- Engineers MUST ALWAYS sort source datasets deterministically by partition key followed by unique/primary key prior to constructing and binding MERGE parameter batches.
- Engineers MUST NOT execute MERGE statements against parent/root partitioned tables when a batch belongs entirely to a single known partition; target leaf partitions directly to bypass parent routing locks.
- Code SHOULD wrap batch MERGE operations in explicit retry loops intercepting PostgreSQL error codes 40001 (serialization_failure) and 40P01 (deadlock_detected) with randomized exponential jitter.
- Services MUST NEVER mutate the partition key column inside the 'WHEN MATCHED THEN UPDATE' clause of a MERGE statement to eliminate row migration cross-partition deadlock graphs.
- Components MUST chunk concurrent write batches into bounded cohorts (1,000 - 5,000 records) to mitigate lock escalation and transaction starvation under high concurrency.

## Bad vs Good Implementations
### Concurrent Ingestion Pipeline Upsert into Partitioned Analytical Store

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Unsorted multi-row MERGE calls executed concurrently against the parent table acquire row and partition locks in non-deterministic sequences across workers, causing cyclic deadlock wait graphs (SQLSTATE 40P01) and serialization aborts (SQLSTATE 40001). Updating without deterministic ordering violates isolation guarantees under load.
```typescript
import { PoolClient } from 'pg';

interface MetricRecord {
  metricDate: string; // Partition key (e.g., '2026-03-30')
  deviceId: string;   // Unique key component
  reading: number;
}

export async function ingestMetricsBad(
  client: PoolClient,
  records: MetricRecord[]
): Promise<void> {
  // ANTI-PATTERN: Records arrive in arbitrary order, executed against the root partitioned table
  // without explicit transaction ordering or transient deadlock/serialization handling.
  const query = `
    MERGE INTO device_metrics AS target
    USING (
      SELECT unnest($1::date[]) AS metric_date,
             unnest($2::text[]) AS device_id,
             unnest($3::numeric[]) AS reading
    ) AS source
    ON target.metric_date = source.metric_date AND target.device_id = source.device_id
    WHEN MATCHED THEN
      UPDATE SET reading = source.reading
    WHEN NOT MATCHED THEN
      INSERT (metric_date, device_id, reading)
      VALUES (source.metric_date, source.device_id, source.reading);
  `;

  const dates = records.map(r => r.metricDate);
  const devices = records.map(r => r.deviceId);
  const readings = records.map(r => r.reading);

  await client.query(query, [dates, devices, readings]);
}
```

#### Production Standard (Correct)
> **Standard**: Tuples are deterministically ordered in memory and enforced in the CTE source subquery, eliminating deadlocks caused by opposing lock acquisition orders. The transaction is encapsulated in an exponential-backoff retry harness specifically handling SQLSTATE 40P01 and 40001.
```typescript
import { PoolClient } from 'pg';

interface MetricRecord {
  metricDate: string; // Partition key (YYYY-MM-DD)
  deviceId: string;   // Unique key component
  reading: number;
}

const POSTGRES_DEADLOCK_CODE = '40P01';
const POSTGRES_SERIALIZATION_FAILURE = '40001';
const MAX_RETRIES = 5;

export async function ingestMetricsGood(
  client: PoolClient,
  records: MetricRecord[]
): Promise<void> {
  if (records.length === 0) return;

  // INVARIANT 1: Deterministic sort on partition key, then secondary unique key.
  // Guarantees all concurrent transactions acquire row locks in identical directional order.
  const sorted = [...records].sort((a, b) => {
    const dateCmp = a.metricDate.localeCompare(b.metricDate);
    return dateCmp !== 0 ? dateCmp : a.deviceId.localeCompare(b.deviceId);
  });

  const dates = sorted.map(r => r.metricDate);
  const devices = sorted.map(r => r.deviceId);
  const readings = sorted.map(r => r.reading);

  const query = `
    WITH source_data AS (
      SELECT 
        val.metric_date,
        val.device_id,
        val.reading
      FROM (
        SELECT 
          unnest($1::date[]) AS metric_date,
          unnest($2::text[]) AS device_id,
          unnest($3::numeric[]) AS reading
      ) AS val
      ORDER BY val.metric_date ASC, val.device_id ASC
    )
    MERGE INTO device_metrics AS target
    USING source_data AS source
    ON target.metric_date = source.metric_date AND target.device_id = source.device_id
    WHEN MATCHED THEN
      UPDATE SET reading = source.reading
    WHEN NOT MATCHED THEN
      INSERT (metric_date, device_id, reading)
      VALUES (source.metric_date, source.device_id, source.reading);
  `;

  // INVARIANT 2: Transient deadlock & serialization failure retry harness with jitter.
  let attempt = 0;
  while (true) {
    try {
      await client.query('BEGIN');
      await client.query(query, [dates, devices, readings]);
      await client.query('COMMIT');
      break;
    } catch (err: unknown) {
      await client.query('ROLLBACK');
      const pgError = err as { code?: string };
      const isTransient = pgError.code === POSTGRES_DEADLOCK_CODE || pgError.code === POSTGRES_SERIALIZATION_FAILURE;

      if (isTransient && attempt < MAX_RETRIES) {
        attempt++;
        const jitterMs = Math.floor(Math.random() * 50) + Math.pow(2, attempt) * 20;
        await new Promise(resolve => setTimeout(resolve, jitterMs));
        continue;
      }
      throw err;
    }
  }
}
```

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: PostgreSQL 17 Concurrent MERGE Isolation and Partition Lock Contention Standard

PostgreSQL 17 Concurrent MERGE Isolation and Partition Lock Contention Standard defines an industrial-grade behavioral standard for backend engineering. Prevents partition-level lock contention, write serialization anomalies (SQLSTATE 40001), and cross-transaction deadlocks (SQLSTATE 40P01) during concurrent upsert workloads on PostgreSQL 17 partitioned tables. Enforces deterministic tuple ordering, targeted leaf partition routing, and bounded exponential backoff policies. 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: Unordered Ingestion into Root Partition Tables via Concurrent MERGE Triggering Deadlocks 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 DriftUnordered Ingestion into Root Partition Tables via Concurrent MERGE Triggering DeadlocksCritical
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 sort source datasets deterministically by partition key followed by unique/primary key prior to constructing and binding MERGE parameter batches.

Engineers MUST ALWAYS sort source datasets deterministically by partition key followed by unique/primary key prior to constructing and binding MERGE parameter batches.

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 MERGE statements against parent/root partitioned tables when a batch belongs entirely to a single known partition

Engineers MUST NOT execute MERGE statements against parent/root partitioned tables when a batch belongs entirely to a single known partition; target leaf partitions directly to bypass parent routing locks.

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 wrap batch MERGE operations in explicit retry loops intercepting PostgreSQL error codes 40001 (serialization_failure) and 40P01 (deadlock_detected) with randomized exponential jitter.

Code SHOULD wrap batch MERGE operations in explicit retry loops intercepting PostgreSQL error codes 40001 (serialization_failure) and 40P01 (deadlock_detected) with randomized exponential jitter.

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 NEVER mutate the partition key column inside the 'WHEN MATCHED THEN UPDATE' clause of a MERGE statement to eliminate row migration cross-partition deadlock graphs.

Services MUST NEVER mutate the partition key column inside the 'WHEN MATCHED THEN UPDATE' clause of a MERGE statement to eliminate row migration cross-partition deadlock graphs.

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 chunk concurrent write batches into bounded cohorts (1,000 - 5,000 records) to mitigate lock escalation and transaction starvation under high concurrency.

Components MUST chunk concurrent write batches into bounded cohorts (1,000 - 5,000 records) to mitigate lock escalation and transaction starvation under high concurrency.

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 Concurrent MERGE Isolation and Partition Lock Contention Standard critical for AI coding assistants?

Prevents partition-level lock contention, write serialization anomalies (SQLSTATE 40001), and cross-transaction deadlocks (SQLSTATE 40P01) during concurrent upsert workloads on PostgreSQL 17 partitioned tables. Enforces deterministic tuple ordering, targeted leaf partition routing, and bounded exponential backoff policies. 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 (Unordered Ingestion into Root Partition Tables via Concurrent MERGE Triggering Deadlocks) 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