Skip to content

Widhian Bramantya

coding is an art form

Menu
  • About Me
Menu
debezium

Implementing the Outbox Pattern with Debezium

Posted on September 27, 2025September 27, 2025 by admin

Introduction

Modern applications often need to store data and at the same time publish events.
Example:

  • An e-commerce system creates an order in the database.
  • At the same moment, it needs to notify a shipping service and a billing service.

If the app writes to the database and Kafka separately, things can go wrong:

  • The database write succeeds but the Kafka message fails: event is lost.
  • The Kafka message succeeds but the database write fails: inconsistent state.

This problem is called the dual-write problem.
The Outbox Pattern solves it.

What is the Outbox Pattern?

The idea:

  1. The application writes its business data and an outbox record in the same database transaction.
  2. Debezium monitors the outbox table using Change Data Capture (CDC).
  3. Debezium publishes the outbox record to Kafka as an event.
  4. Consumers (other services) read the event from Kafka.

Because both business data and outbox record are written atomically, there is no inconsistency.

Outbox Table Example

CREATE TABLE order_outbox (
  id UUID PRIMARY KEY,
  order_id UUID NOT NULL,
  event_type VARCHAR(50) NOT NULL,
  payload JSONB NOT NULL,
  created_at TIMESTAMP DEFAULT now()
);
  • order_id: reference to the business entity.
  • event_type: e.g., ORDER_CREATED, ORDER_PAID.
  • payload: JSON with event details.
  • created_at: timestamp for ordering.

Application Flow

sequenceDiagram
  autonumber
  participant App as Order Service
  participant DB as PostgreSQL
  participant DBZ as Debezium Connector
  participant K as Kafka
  participant S as Shipping Service
  participant B as Billing Service

  App->>DB: Insert into orders + order_outbox (same TX)
  DBZ->>DB: Read WAL (change in order_outbox)
  DBZ-->>K: Publish event to Kafka topic
  K-->>S: Deliver event to Shipping Service
  K-->>B: Deliver event to Billing Service

Debezium Connector Config

{
  "name": "ecommerce-order-outbox-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "database.hostname": "ecom-prod-db.example.com",
    "database.port": "5432",
    "database.user": "cdc_user",
    "database.password": "******",
    "database.dbname": "ecommerce",
    "database.server.name": "ecommerce",
    "table.include.list": "public.order_outbox",
    "transforms": "unwrap",
    "transforms.unwrap.type": "io.debezium.transforms.ExtractNewRecordState",
    "key.converter": "org.apache.kafka.connect.json.JsonConverter",
    "key.converter.schemas.enable": false,
    "value.converter": "org.apache.kafka.connect.json.JsonConverter",
    "value.converter.schemas.enable": false
  }
}

See this article for production grade connector.

See also  Connecting Debezium with Kafka for Real-Time Streaming
Pages: 1 2
Category: Debezium, Kafka

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Linkedin

Widhian Bramantya

Recent Posts

  • Log Management at Scale: Integrating Elasticsearch with Beats, Logstash, and Kibana
  • Index Lifecycle Management (ILM) in Elasticsearch: Automatic Data Control Made Simple
  • Blue-Green Deployment in Elasticsearch: Safe Reindexing and Zero-Downtime Upgrades
  • Maintaining Super Large Datasets in Elasticsearch
  • Elasticsearch Best Practices for Beginners
  • Implementing the Outbox Pattern with Debezium
  • Production-Grade Debezium Connector with Kafka (Postgres Outbox Example – E-Commerce Orders)
  • Connecting Debezium with Kafka for Real-Time Streaming
  • Debezium Architecture – How It Works and Core Components
  • What is Debezium? – An Introduction to Change Data Capture
  • Offset Management and Consumer Groups in Kafka
  • Partitions, Replication, and Fault Tolerance in Kafka
  • Delivery Semantics in Kafka: At Most Once, At Least Once, Exactly Once
  • Producers and Consumers: How Data Flows in Kafka
  • Kafka Architecture Explained: Brokers, Topics, Partitions, and Offsets
  • Getting Started with Apache Kafka: Core Concepts and Use Cases
  • Security Best Practices for RabbitMQ in Production
  • Understanding RabbitMQ Virtual Hosts (vhosts) and Their Uses
  • RabbitMQ Performance Tuning: Optimizing Throughput and Latency
  • High Availability in RabbitMQ: Clustering and Mirrored Queues Explained

Recent Comments

  1. Playing with VPC AWS (Part 2) – Widhian's Blog on Playing with VPC AWS (Part 1): VPC, Subnet, Internet Gateway, Route Table, NAT, and Security Group
  2. Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh – Widhian's Blog on Basic Concept of ElasticSearch (Part 1): Introduction
  3. Basic Concept of ElasticSearch (Part 2): Architectural Perspective – Widhian's Blog on Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh
  4. Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh – Widhian's Blog on Basic Concept of ElasticSearch (Part 2): Architectural Perspective
  5. Basic Concept of ElasticSearch (Part 1): Introduction – Widhian's Blog on Basic Concept of ElasticSearch (Part 2): Architectural Perspective

Archives

  • October 2025
  • September 2025
  • August 2025
  • November 2021
  • October 2021
  • August 2021
  • July 2021
  • June 2021
  • March 2021
  • January 2021

Categories

  • Debezium
  • Devops
  • ElasticSearch
  • Golang
  • Kafka
  • Lua
  • NATS
  • Programming
  • RabbitMQ
  • Redis
  • VPC
© 2025 Widhian Bramantya | Powered by Minimalist Blog WordPress Theme