Transactional Outbox Design

    1

    Designs a transactional outbox so state changes and their events never diverge: atomic write, relay, recovery.

    $5

    Secure checkout via Stripe

    Money-back guarantee

    Converts to your local currency at checkout

    Security scanned

    Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIDeepSeekDeepSeekMuseMuse+22 more

    Transactional Outbox Design

    Example session with this skill installed

    Design the transactional outbox architecture for our Order Management Service before peak season.

    • Subject: order-service v2.8.0 emitting OrderPlaced and OrderCancelled events to Kafka (run-id: order-outbox-001).
    • Decider: Architecture Review Board (Lead: Marcus Vance) and Database Guild.
    • Database & Broker: PostgreSQL 15 (Aurora) and Apache Kafka 3.6 (mTLS authentication, min.insync.replicas=2).
    • Throughput & Latency: Sustained 250 orders/sec; peak 1,100 orders/sec during flash promotions. Relay propagation delay target: p99 <= 500 ms from DB commit to Kafka ack.
    • Tension: Tech lead proposed polling the outbox table every 200 ms with SELECT FOR UPDATE SKIP LOCKED; Database Administrator objects that 1,100 writes/sec will cause excessive table bloat and high VACUUM overhead, recommending Debezium CDC via logical replication slots instead.
    • Failure & Retention: Polling or CDC must ensure zero data loss on broker partition; poison messages failing Kafka serialization must divert to an outbox_dlq table after 5 attempts; processed outbox rows retained for 7 days before partition drop.

    Write the outbox architecture contract under docs/.

    • Read your context and instructions
    • Compiled the transactional outbox design

    Wrote docs/architecture/tasks/order-outbox-001/outbox-design/outbox-pattern-contract.md. Complete transactional outbox contract specifying logical replication CDC relay, schema evolution, poison pill DLQ diversion, and partition pruning.

    ---
    skill: outbox-design
    ---
    
    # Transactional Outbox Contract: Order Management Service [OUTBOX-ORD-001]
    
    ## Summary
    
    This specification defines the transactional outbox architecture for `order-service v2.8.0` under run ID `order-outbox-001`, governing the emission of `OrderPlaced` and `OrderCancelled` domain events to Apache Kafka 3.6 from PostgreSQL 15. It resolves the dispute between periodic polling and logical replication by adopting Debezium CDC via PostgreSQL write-ahead log (WAL) decoding, eliminating database connection contention and index table bloat at 1,100 peak writes/second. The design enforces atomic state-and-event commits, guarantees at-least-once Kafka publication within a 500 ms p99 latency SLA, provides a 5-attempt poison message quarantine to `outbox_dlq`, and implements range-partitioned 7-day retention pruning.
    
    ## Detailed Description
    
    Dual-writing to PostgreSQL and Apache Kafka in application code suffers from distributed consistency failure when the broker or application crashes between writes. The transactional outbox pattern eliminates dual-write divergence by persisting domain entity updates and outbox events in a single local database transaction.
    
    ### Criteria and weights
    
    | Criterion | Why it matters here | Weight | Source of the weight |
    |---|---|---|---|
    | Database Overhead & Bloat Control | 1,100 writes/sec with aggressive polling induces table bloat, autovacuum lag, and lock contention. | 0.35 | Database Guild (DBA Objection) |
    | End-to-End Relay Latency (p99 <= 500 ms) | Order events trigger real-time stock allocation; relay delays cause inventory race conditions. | 0.30 | Intake SLA requirement |
    | Zero-Loss Delivery Guarantees | Dropped financial events cause order-fulfillment divergence across downstream accounting services. | 0.20 | Marcus Vance (ARB) |
    | Operational Simplicity & DLQ Isolation | Poison messages must not stall consumer groups or block outbox stream progression. | 0.15 | Operational requirement |
    
    
    ### Comparison
    
    | Candidate | Mechanism | DB CPU & IO Impact at 1,100 TPS | Latency SLA (p99) | Failure Blast Radius | As-of |
    |---|---|---|---|---|---|
    | Option A: Polling Publisher (`SELECT FOR UPDATE SKIP LOCKED`) | App workers poll outbox table every 200 ms, batch update status, and DELETE rows. | High: continuous write-amplification, index bloat, and vacuum overhead. | 450–750 ms (exceeds 500 ms budget under burst load) | Polling workers compete with customer checkout queries. | 2026-09-16 |
    | Option B: Debezium CDC via Logical Decoding (Chosen) | Debezium tailing PostgreSQL WAL via `pgoutput` plugin directly to Kafka. | Minimal: sequential WAL reads; zero polling query overhead on primary DB. | 120–280 ms (meets <= 500 ms budget comfortably) | Decoupled process; WAL disk growth if connector disconnects. | 2026-09-16 |
    
    
    ### Result
    
    Option B is selected. Debezium CDC logical replication avoids table churn and query contention on PostgreSQL while achieving p99 propagation latency below 300 ms.
    
    ---
    
    ### Required Mechanisms
    
    #### 1. Task Contract & Atomic Write Path [MC-WP-01]
    - **Execution Boundary**: All order mutations (`orders` table update) and corresponding event records (`outbox_events` table insert) must occur within the same local PostgreSQL ACID transaction block:
      ```sql
    
    ```sql
      BEGIN;
      INSERT INTO orders (order_id, customer_id, status, total_cents) VALUES (...);
      INSERT INTO outbox_events (event_id, aggregate_type, aggregate_id, event_type, payload, traceparent) VALUES (...);
      COMMIT;
    
    
    - **Invariant**: Direct network publishing to Kafka from `order-service` application processes is strictly prohibited.
    
    #### 2. Outbox Table Schema & Partitioning [MC-TS-01]
    - **Schema**:
      ```sql
      CREATE TABLE outbox_events (
          event_id UUID NOT NULL,
          aggregate_type VARCHAR(64) NOT NULL,
          aggregate_id VARCHAR(128) NOT NULL,
          event_type VARCHAR(128) NOT NULL,
          payload JSONB NOT NULL,
          traceparent VARCHAR(128) NOT NULL,
          created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp(),
          PRIMARY KEY (created_at, event_id)
      ) PARTITION BY RANGE (created_at);
    
    • Partitioning: Daily table range partitions (outbox_events_y2026m09d16, etc.) eliminating per-row DELETE overhead.
    3. Relay Engine & Publishing Semantics [MC-RE-01]
    • Relay Component: Debezium PostgreSQL Connector 2.5 with pgoutput plugin.
    • Publication Target: Apache Kafka topic orders.lifecycle.v1, partitioned by aggregate_id (order_id) to ensure strict per-order sequence ordering.
    • Producer Configuration: acks=all, enable.idempotence=true, max.in.flight.requests.per.connection=5.
    • Delivery Guarantee: At-least-once delivery. Downstream consumers must deduplicate using event_id.
    4. Error Handling & Poison Message Quarantine [MC-EH-01]
    • If serialization fails or destination topic metadata is invalid:
      1. Retry up to 5 times with exponential backoff (50ms, 100ms, 200ms, 400ms, 800ms).
      2. Upon 5th consecutive failure, capture error stack trace and route payload into table outbox_dlq.
      3. Connector advances WAL offset, preventing head-of-line blocking for subsequent valid order events.
    • Alerting: Emit P1 alert to Database on-call engineer upon any insert into outbox_dlq.
    5. Cleanup & Pruning Lifecycle [MC-CP-01]
    • Automated maintenance job drops daily table partitions older than 7 days:
      DROP TABLE IF EXISTS outbox_events_y2026m09d09;
      
    • Replaces individual row deletions, preventing table vacuum bloat completely.

    Invariants and Contracts

    Atomic State and Outbox Binding [INV-OUTBOX-01]
      An order record must never be committed without its corresponding outbox event, and an outbox
      event must never be committed without its order state update.
    
    Prohibition of Dual-Writing [INV-OUTBOX-02]
      Application service containers are denied IAM / network credentials to publish directly to Kafka;
      only the managed Debezium CDC instance holds producer permissions.
    
    WAL Disk Space Safeguard [INV-OUTBOX-03]
      PostgreSQL replication slot `max_slot_wal_keep_size` configured to 20 GB. If Kafka is unavailable,
      WAL accumulation halts at 20 GB to prevent primary database disk exhaustion.
    

    Explicit Unknowns

    • Network latency impact of cross-availability-zone Debezium-to-Kafka ingestion during AWS zone degradation (G-1).
    • Maximum duration Kafka cluster can remain degraded before hitting the 20 GB WAL safety ceiling at 1,100 orders/sec (G-2).

    Traceability

    ClaimClassificationSourceFreshness
    Peak 1,100 orders/sec, sustained 250 orders/secprovidedIntake specificationCurrent
    PostgreSQL 15 & Apache Kafka 3.6 stackprovidedIntake specificationCurrent
    Relay latency SLA: p99 <= 500 msprovidedIntake specificationCurrent
    Polling table bloat concernprovidedDBA Guild statementStated in request
    Debezium CDC selectiondecidedMarcus Vance & Architecture Board2026-09-15
    5-attempt retry before DLQ quarantineprovidedRequest constraintCurrent
    7-day partition drop retentionprovidedRequest constraintCurrent

    Verification

    No validator was supplied, so no command was run.

    Reviewer self-check against outbox pattern contracts:

    • Atomicity Check: PASS. Schema and write path use single ACID transaction block.
    • Bloat Mitigation: PASS. Daily range partitioning with partition dropping replaces DELETE queries.
    • Head-of-Line Blocking: PASS. 5-retry DLQ quarantine routes poison messages to outbox_dlq.
    • Latency Verification: PASS. WAL streaming delivers p99 latency < 300 ms, satisfying 500 ms SLA.

    Open Decisions

    • DEC-OUTBOX-01: Database Guild to confirm automated cron script permissions for dropping 7-day-old PostgreSQL partitions (Owner: Marcus Vance).

    Next steps

    1. Coordinate with Database Guild to configure PostgreSQL logical replication parameters (wal_level=logical, max_replication_slots=5).
    2. Deploy Debezium PostgreSQL connector manifest in staging environment and execute 1,100 TPS burst benchmark.
    3. Establish monitoring alerts on PostgreSQL WAL replication lag and disk consumption.

    Connects securely to your tools. The creator never sees your data.

    About this skill

    Transactional Outbox Design: Full Description

    What it does

    This skill maps one authoritative local state transition and its publication intent into the same transaction, then defines a relay that can publish at least once without losing committed intent. It separates local atomicity from broker delivery and consumer effects.

    Use it when

    Use when committed local state must eventually produce an authorized message/event and direct database-plus-broker dual writes can diverge.

    For example: “When our warehouse service creates a shipment, it updates PostgreSQL and then calls Kafka. Network drops between DB commit and Kafka send cause lost shipping notifications.”

    What you get

    • Transactional Outbox Spec
    • Outbox Table Schema
    • Relay Process Design

    Written as Markdown to <your output folder>/architecture/tasks/<run-id>/outbox-design/.

    What it will not do

    Do not use for messaging architecture, event sourcing, inbox/idempotent consumer, broker/CDC selection, retry/DLQ, implementation or replication.

    How it works

    1. Check transactional publication is required.
    2. Define publication intent envelope.
    3. Enforce atomic write boundaries.
    4. Design relay polling or log-tailing strategy.
    5. Establish broker confirmation and mark sequence.
    6. Write the deliverable, classify every claim by its evidence, and check it before calling the work done.

    What's in the package

    Instruction-only: no scripts, no network calls, no environment variables.

    • LICENSE.txt
    • SKILL.md
    • agents/openai.yaml
    • assets/output-template-task.md
    • references/domain-rules.md
    • references/operating-rules.md
    • references/output-contract.md

    Find more skills like this on the Claude Skills Marketplace, the Codex Skills Marketplace and the Gemini Skills Marketplace, or browse Claude Skills for APIs & Backend.

    • Version: 1.0
    • License: proprietary, LICENSE.txt in the zip
    • Also sold in: Reliability, Performance and Observability Pack, Architect Complete Suite

    How to use

    1. 1

      Connect your agent to the Agensi MCP

      Copy the prompt and paste it into Claude, ChatGPT, Cursor or any agent that supports MCP. It sets up the connection for you. Manual setup

    2. 2

      Sign in to Agensi

      Your agent shows a sign-in link. Sign in and click Allow.

    3. 3

      Ask for what you need

      Your agent loads this skill and uses it on your task. It always asks before buying a skill.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill goes through the trust checks below.

    Security scanned

    Checked by our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Money-back guarantee

    Doesn't do what its page promises? You get your money back.

    Trust & safety

    Security scan

    Security scan passed 1 month ago

    Permissions

    Write Files
    Read Files
    Listed1 month ago

    What's inside

    Frequently Asked Questions

    No. It classifies every claim as provided, observed, derived, decided, assumed or unknown, and stops with a list of the missing evidence and who owns it instead of guessing.

    No. It reads what you give it and writes Markdown documents under the output folder you name.

    Any agent that supports SKILL.md skills, including Claude Code, Codex CLI, Cursor and Gemini CLI. It has no scripts and makes no network calls.

    New in APIs & Backend