DEV Community

丁久
丁久

Posted on • Originally published at dingjiu1989-hue.github.io

Event-Driven Architecture Patterns: Kafka, RabbitMQ, SQS, and EventBridge Compared

This article was originally published on AI Study Room. For the full version with working code examples and related articles, visit the original post.

Event-Driven Architecture Patterns: Kafka, RabbitMQ, SQS, and EventBridge Compared

Event-driven architecture (EDA) is the pattern behind the most scalable systems — from Netflix's microservices to Stripe's payment processing. Instead of services calling each other directly (request-response), they communicate through events (messages about things that happened). This guide covers the patterns, message brokers, and practical implementation of event-driven systems.

Core Event-Driven Patterns

Pattern How It Works Use Case Complexity
Event Notification "Order #123 was placed" — fire and forget, subscribers react Send email on signup, update search index on content change Low
Event-Carried State Transfer Events contain all data subscribers need (no callback to source) Catalog service publishes full product data — search, pricing, and inventory consume it Low-Medium
Event Sourcing State is derived from a sequence of events (not a current snapshot) Banking transactions, audit logs, undo/redo functionality High
CQRS (Command Query Responsibility Segregation) Separate read and write models — writes go through events, reads from materialized views High-read, complex-query applications (e-commerce product search) High
Saga (Distributed Transaction) A sequence of local transactions, each compensated if a later step fails Order fulfillment: reserve inventory → charge payment → schedule shipping High

Message Broker Comparison

Broker Type Throughput Latency Best For
Apache Kafka Distributed event log 1M+ msg/s 2-20ms High-throughput event streaming, event sourcing, data pipelines
RabbitMQ Message queue (AMQP) 50K msg/s <1ms Task distribution, RPC, complex routing patterns
Amazon SQS Managed message queue Unlimited (AWS scaling) 1-50ms AWS-native, zero ops, FIFO when ordering matters
Google Pub/Sub Managed pub/sub Unlimited (GCP scaling) 1-10ms GCP-native, push subscriptions, global by default
Redis Streams In-memory event log 100K msg/s <1ms Lightweight event streaming, already have Redis
NATS Lightweight pub/sub 1M+ msg/s <1ms Low-latency, edge, IoT, microservices

When to Go Event-Driven

Situation Event-Driven? Why
Monolith → microservices migration Yes — use events to decouple Events let services evolve independently
Multiple services need to react to the same event Yes — pub/sub is the pattern One event, many consumers, no coupling
Simple CRUD app, single database No — request-response is fine EDA adds complexity; don't need it yet
Need audit trail of all state changes Yes — event sourcing Events ARE the audit trail
Data analytics / real-time dashboards Yes — event streaming Kafka → stream processing → real-time views
Two services need a synchronous response No — use REST/gRPC Events are async; request-response is simpler for sync needs

Implementing a Saga: Order Fulfillment Example

# Saga pattern: orchestration-based (orchestrator coordinates the steps)
# Each step is a local transaction; each has a compensating action

# Step 1: Create order (reserve inventory)
POST /orders {status: PENDING, items: [...]}
  → Event: "OrderCreated" {order_id: 123}
  → Inventory Service reserves stock

# Step 2: Process payment
  → Event: "InventoryReserved" {order_id: 123}
  → Payment Service charges customer
  → Success: "PaymentProcessed" {order_id: 123}
  → Failure: "PaymentFailed" {order_id: 123}
    → Compensate: Inventory Service releases stock

# Step 3: Schedule shipping
  → Event: "PaymentProcessed" {order_id: 123}
  → Shipping Service creates label
  → Success: "OrderFulfilled" {order_id: 123}
  → Failure: "ShippingFailed" {order_id: 123}
    → Compensate: Payment Service refunds
    → Compensate: Inventory Service releases stock

# Key: each compensating action must be idempotent
# (refunding twice = bad; but idempotent refund = safe to retry)
Enter fullscreen mode Exit fullscreen mode

Bottom line: Start with simple event notification (one service emits, others react) before adopting event sourcing or CQRS. For most projects, RabbitMQ or Redis Streams provide enough throughput with simpler operations. Only reach for Kafka when you need replay, long-term retention, or 1M+ msg/s throughput. The biggest mistake is going fully event-driven when simple request-response would suffice — EDA is a powerful tool, not a default architecture. See also: Microservices vs Monolith and Webhook Implementation Guide.


Read the full article on AI Study Room for complete code examples, comparison tables, and related resources.

Found this useful? Check out more developer guides and tool comparisons on AI Study Room.

Top comments (0)