This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: postgres-17-failover-slot-synchronization-boundary

Postgres 17 Logical Slot Synchronization Pre-Promotion Invariant

Mandates that automated database failover scripts, cluster controllers, and promotion orchestrators enforce logical replication slot synchronization on PostgreSQL 17 physical standbys before issuing promotion commands. Pre-promotion synchronization via sync_replication_slots and pg_sync_replication_slots() eliminates downstream subscriber desynchronization, LSN gaps, and required full table resynchronization.

Prohibited Anti-Pattern: Promoting a physical standby to primary without verifying or forcing logical replication slot synchronization, corrupting downstream logical subscribers.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Postgres 17 Logical Slot Synchronization Pre-Promotion Invariant - Mandates that automated database failover scripts, cluster controllers, and promotion orchestrators enforce logical replication slot synchronization on PostgreSQL 17 physical standbys before issuing promotion commands. Pre-promotion synchronization via sync_replication_slots and pg_sync_replication_slots() eliminates downstream subscriber desynchronization, LSN gaps, and required full table resynchronization.
globs: src/**/*.{ts,js}, scripts/**/*.{ts,js}, infra/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/postgres-17-failover-slot-synchronization-boundary"
---

# Postgres 17 Logical Slot Synchronization Pre-Promotion Invariant

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Promoting a physical standby to primary without verifying or forcing logical replication slot synchronization, corrupting downstream logical subscribers.

## System Constraints
You are a Principal Software Architect enforcing Postgres 17 failover boundaries. You must enforce that physical standby promotion workflows rigorously synchronize all downstream logical replication slots before promoting any standby to primary status. Promoting a standby with desynchronized or missing logical slots causes downstream CDC consumers (e.g., Debezium, microservice read models) to crash or skip WAL changes due to missing confirmed flush LSNs. Standby promotion workflows must explicitly assert sync_replication_slots is active and invoke pg_sync_replication_slots() to achieve zero-loss failover.

## Strict Guidelines
- Engineers MUST ALWAYS verify that logical replication slots on the primary are configured with 'failover = true' before relying on automated slot synchronization.
- Engineers MUST NOT execute 'SELECT pg_promote()' or trigger standby promotion before ensuring 'pg_replication_slots.synced' is true for all required failover slots.
- Promotion scripts and failover orchestrators MUST invoke 'SELECT pg_sync_replication_slots()' explicitly during controlled failovers to guarantee confirmed flush LSN convergence prior to role transition.
- Services orchestrating high-availability MUST verify that the standby configuration includes 'sync_replication_slots = on' and that 'hot_standby_feedback = on' is active to prevent primary WAL removal prior to slot sync.
- Engineers NEVER perform uncontrolled failovers to a standby whose logical slots have a confirmed_flush_lsn strictly older than the primary's last acknowledged replication flush without raising a catastrophic data loss alert.

## Bad vs Good Implementations
### PostgreSQL 17 Controlled Standby Promotion Hook

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Calling pg_promote() directly on a PostgreSQL 17 physical standby without checking or syncing logical replication slots will leave downstream subscribers stranded. Logical slots not synchronized will remain behind or missing on the new primary, breaking WAL streaming continuity.
```typescript
import { Client } from 'pg';

export async function promoteStandbyToPrimary(standbyClient: Client): Promise<void> {
  // Anti-Pattern: Promoting physical standby immediately without verifying
  // or synchronizing Postgres 17 logical replication failover slots.
  // Downstream logical subscribers (Debezium/CDC) will encounter LSN gaps and crash.
  const res = await standbyClient.query('SELECT pg_promote(wait => true, wait_seconds => 60)');
  if (!res.rows[0].pg_promote) {
    throw new Error('Promotion timed out or failed');
  }
}
```

#### Production Standard (Correct)
> **Standard**: The orchestrator invokes pg_sync_replication_slots() to catch up logical slot positions before promotion and verifies that all failover slots have synced = true in pg_replication_slots. Only then is pg_promote() executed, ensuring zero data loss for downstream logical replication consumers.
```typescript
import { Client } from 'pg';

interface ReplicationSlotStatus {
  slot_name: string;
  synced: boolean;
  confirmed_flush_lsn: string | null;
}

export async function promoteStandbyToPrimary(standbyClient: Client): Promise<void> {
  // 1. Explicitly force synchronization of all enabled failover logical slots
  try {
    await standbyClient.query('SELECT pg_sync_replication_slots()');
  } catch (err) {
    throw new Error(`Failed to synchronize logical replication slots: ${String(err)}`);
  }

  // 2. Validate that all critical failover slots are fully synced
  const { rows } = await standbyClient.query<ReplicationSlotStatus>(
    `SELECT slot_name, synced, confirmed_flush_lsn
     FROM pg_replication_slots
     WHERE failover = true AND temporary = false`
  );

  const unSyncedSlots = rows.filter((slot) => !slot.synced);
  if (unSyncedSlots.length > 0) {
    const unSyncedNames = unSyncedSlots.map((s) => s.slot_name).join(', ');
    throw new Error(`Standby promotion aborted: Slots [${unSyncedNames}] are not synchronized.`);
  }

  // 3. Promote standby only after slot synchronization boundary invariant is verified
  const promoteResult = await standbyClient.query<{ pg_promote: boolean }>(
    'SELECT pg_promote(wait => true, wait_seconds => 60)'
  );

  if (!promoteResult.rows[0]?.pg_promote) {
    throw new Error('Promotion failed or timed out on standby');
  }
}
```

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 Logical Slot Synchronization Pre-Promotion Invariant

Postgres 17 Logical Slot Synchronization Pre-Promotion Invariant defines an industrial-grade behavioral standard for backend engineering. Mandates that automated database failover scripts, cluster controllers, and promotion orchestrators enforce logical replication slot synchronization on PostgreSQL 17 physical standbys before issuing promotion commands. Pre-promotion synchronization via sync_replication_slots and pg_sync_replication_slots() eliminates downstream subscriber desynchronization, LSN gaps, and required full table resynchronization. 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: Promoting a physical standby to primary without verifying or forcing logical replication slot synchronization, corrupting downstream logical subscribers. 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 DriftPromoting a physical standby to primary without verifying or forcing logical replication slot synchronization, corrupting downstream logical subscribers.Critical
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 verify that logical replication slots on the primary are configured with 'failover = true' before relying on automated slot synchronization.

Engineers MUST ALWAYS verify that logical replication slots on the primary are configured with 'failover = true' before relying on automated slot synchronization.

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 'SELECT pg_promote()' or trigger standby promotion before ensuring 'pg_replication_slots.synced' is true for all required failover slots.

Engineers MUST NOT execute 'SELECT pg_promote()' or trigger standby promotion before ensuring 'pg_replication_slots.synced' is true for all required failover slots.

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

Promotion scripts and failover orchestrators MUST invoke 'SELECT pg_sync_replication_slots()' explicitly during controlled failovers to guarantee confirmed flush LSN convergence prior to role transition.

Promotion scripts and failover orchestrators MUST invoke 'SELECT pg_sync_replication_slots()' explicitly during controlled failovers to guarantee confirmed flush LSN convergence prior to role transition.

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 orchestrating high-availability MUST verify that the standby configuration includes 'sync_replication_slots = on' and that 'hot_standby_feedback = on' is active to prevent primary WAL removal prior to slot sync.

Services orchestrating high-availability MUST verify that the standby configuration includes 'sync_replication_slots = on' and that 'hot_standby_feedback = on' is active to prevent primary WAL removal prior to slot sync.

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

Engineers NEVER perform uncontrolled failovers to a standby whose logical slots have a confirmed_flush_lsn strictly older than the primary's last acknowledged replication flush without raising a catastrophic data loss alert.

Engineers NEVER perform uncontrolled failovers to a standby whose logical slots have a confirmed_flush_lsn strictly older than the primary's last acknowledged replication flush without raising a catastrophic data loss alert.

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 Logical Slot Synchronization Pre-Promotion Invariant critical for AI coding assistants?

Mandates that automated database failover scripts, cluster controllers, and promotion orchestrators enforce logical replication slot synchronization on PostgreSQL 17 physical standbys before issuing promotion commands. Pre-promotion synchronization via sync_replication_slots and pg_sync_replication_slots() eliminates downstream subscriber desynchronization, LSN gaps, and required full table resynchronization. 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 (Promoting a physical standby to primary without verifying or forcing logical replication slot synchronization, corrupting downstream logical subscribers.) 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