CDC vs Outbox Pattern: Choosing the Right Event-Driven Architecture

By Šarūnas Navickas — 2025-11-30

Data Ingestion CDC Change Data Capture Outbox Pattern
When building event-driven systems, two patterns consistently emerge in architectural discussions: Change Data Capture (CDC) and the Outbox pattern. Both enable systems to react to data changes, but they approach the problem from fundamentally different angles. Understanding when to use each can mean the difference between a resilient, maintainable system and one that couples teams in unexpected ways.

Understanding the Patterns

Change Data Capture (CDC) works by tailing database transaction logs or change streams to capture every modification to your data. Tools like Debezium read these low-level changes and stream them to consumers. You're essentially getting a live feed of every insert, update, and delete as it happens in the database.
The Outbox pattern takes a different approach. Application code explicitly writes business events to an outbox table within the same database transaction that modifies domain data. A separate process then reliably publishes these events to your message broker. The key difference: these are intentional, business-meaningful events rather than raw database changes.

The Case Against CDC as a Default

There's a growing sentiment in the engineering community that CDC shouldn't be your first choice for inter-service communication. The concern is straightforward: when you consume CDC events, you're consuming implementation details rather than business events.
Consider what CDC gives you: column-level changes, database-specific data types, schema migrations reflected in real-time, and every internal refactoring exposed to downstream consumers. This creates tight coupling at the data layer. When an upstream team refactors their database schema or changes how they model data internally, every CDC consumer potentially breaks.
More critically, you inherit their data quality problems. If the upstream service writes malformed data, performs partial updates, or has consistency issues, those problems flow directly into your system. You're building on an unstable foundation, and debugging becomes a nightmare of tracing issues across service boundaries.

The Outbox Advantage

The Outbox pattern inverts this relationship. Instead of exposing raw data changes, services publish explicit business events: "OrderPlaced", "PaymentProcessed", "InventoryReserved". These events represent the contract between services.
This approach offers several benefits. First, you get semantic clarity - consumers understand business operations, not database mechanics. Second, the upstream team controls what gets exposed. They can refactor their internal data model freely as long as they maintain the event contract. Third, data validation happens at the source. If an event is published, it should represent a valid business state.
The Outbox pattern also enables versioning. You can publish events in a well-defined schema (using Protocol Buffers, Avro, or JSON Schema), version those schemas explicitly, and evolve them in backward-compatible ways. With CDC, schema evolution means coordinating database migrations with consumer code changes.

When CDC Makes Sense

Despite these criticisms, CDC has legitimate use cases. It excels when you're building read models or analytical systems that truly need to mirror source data. If you're maintaining a search index, building a data warehouse, or creating materialized views, CDC's ability to capture every change matters.
CDC is also valuable when you don't control the source system. If you're integrating with a legacy application or third-party database where code changes aren't feasible, CDC might be your only option. The pattern shines for building system-of-record replicas where fidelity to the source database is the explicit goal.
For debugging and auditing, CDC can be invaluable. Having a complete log of every data change helps reconstruct what happened during incidents. Some teams maintain both patterns: Outbox for inter-service communication and CDC for operational observability.

Making the Choice

The decision often comes down to coupling versus convenience. CDC is operationally simpler to set up - no application code changes required. But that convenience comes with hidden coupling costs that accumulate over time.
The Outbox pattern requires more upfront investment. You need to modify application code, design event schemas, and implement the publishing mechanism. But this investment pays dividends in maintainability. Your services communicate through stable, versioned contracts rather than database implementation details.
For inter-service communication in a microservices architecture, the Outbox pattern typically represents better engineering. It aligns with domain-driven design principles, maintains clear bounded contexts, and gives teams autonomy over their internal implementations.

Disclaimer: Dunwich Supports Both Patterns

It's worth noting that Dunwich actually supports both CDC and the Outbox pattern, recognizing that there are appropriate use cases for each approach. The choice between them isn't about tool limitations - it's about architectural fit for your specific needs. Some scenarios genuinely call for CDC's comprehensive change capture, while others benefit from the Outbox pattern's explicit event contracts. Understanding the trade-offs helps you make the right choice for each integration point in your system.

Practical Recommendations

Start with the Outbox pattern for new service-to-service integrations. Define your events as first-class domain concepts. Use schema registries to version and validate event formats. Make event publication part of your service's API contract.
Reserve CDC for scenarios where you truly need database-level fidelity: analytics pipelines, search indexes, cross-region replication, or when integrating with systems you can't modify. Even in these cases, consider whether you can insert an abstraction layer that transforms CDC events into more stable contracts.
If you find yourself consuming CDC from another team's database, have a conversation about publishing proper business events instead. The short-term convenience of CDC rarely justifies the long-term maintenance burden.

Conclusion

The debate between CDC and Outbox isn't about which pattern is universally better - it's about intentionality. CDC makes every data change an implicit API. The Outbox pattern makes events an explicit design choice. For most service communication, explicit wins. Your future self, debugging a production incident at 2 AM, will thank you for choosing clarity over convenience.