1. What is Event-Driven Architecture?

In event-driven architecture (EDA), components produce and consume events. Services are decoupled: producers don’t know about consumers, and vice versa. Events flow through a broker (EventBridge, SNS, SQS, Kinesis) to interested subscribers.

Core Concept Traditional: Service A calls Service B directly (tight coupling). Event-Driven: Service A emits an event ("order created"). EventBridge routes it. Services B, C, and D each react independently. If Service B fails, A and C are unaffected. EDA enables: loose coupling, scalability, and extensibility (add consumers without changing producers).

2. Event-Driven Services on AWS

3. Common EDA Patterns


Pattern 1: Fan-Out

Fan-Out (SNS → Multiple SQS):

  Order Service emits: "OrderCreated."
       |
  SNS Topic: order-events
    |─── SQS: inventory-queue  → Lambda (update inventory)
    |─── SQS: payment-queue   → Lambda (process payment)
    |─── SQS: analytics-queue → Lambda (update dashboards)
    └─── SQS: email-queue     → Lambda (send confirmation)

Each consumer is independent. Adding a new consumer = adding a new SQS subscriber.

Pattern 2: Event Bus Routing

EventBridge Routing:

  Multiple Producers:
    Order Service → event: {source: 'orders', detail-type: 'OrderCreated'}
    User Service  → event: {source: 'users',  detail-type: 'UserRegistered'}
    Payment Svc   → event: {source: 'payments', detail-type: 'PaymentFailed'}
       |
  EventBridge (default bus or custom bus)
       |
  Rules route by content:
    Rule 1: IF source='orders' AND detail-type='OrderCreated'
            → Target: Lambda (fulfill order)
    Rule 2: IF source='payments' AND detail-type='PaymentFailed'
            → Target: SNS (alert team) + SQS (retry queue)

Pattern 3: Saga (Distributed Transactions)

Saga Pattern with Step Functions:

  Problem: Order requires inventory + payment + shipping.
           If payment fails, you must compensate (rollback inventory).

  Step Functions Workflow:
    Step 1: Reserve Inventory (Lambda)
      → Success: Step 2
      → Failure: END (nothing to compensate)
    Step 2: Process Payment (Lambda)
      → Success: Step 3
      → Failure: COMPENSATE → Release Inventory (Lambda)
    Step 3: Arrange Shipping (Lambda)
      → Success: END (order complete)
      → Failure: COMPENSATE → Refund Payment + Release Inventory

  Saga = each step has a compensating action for rollback.
Saga Pattern Distributed transactions across microservices are hard (no global ACID). The Saga pattern solves this: each step either succeeds and moves forward, or fails and triggers compensating actions to undo previous steps. Step Functions is the ideal AWS service for Saga orchestration.

Pattern 4: CQRS (Command Query Responsibility Segregation)

  1. Separate WRITE model (commands) from READ model (queries)
  2. Write: DynamoDB (optimized for writes)
  3. Read: DynamoDB Streams → Lambda → OpenSearch or ElastiCache (optimized for reads)
  4. Benefits: scale reads and writes independently, optimize each for its workload
  5. Use for: high-read applications, complex search requirements, different read/write patterns


Pattern 5: Event Sourcing

  1. Store all state changes as an immutable sequence of events (not current state)
  2. Kinesis or DynamoDB as an event store. Rebuild the current state by replaying events.
  3. Benefits: complete audit trail, replay for debugging, temporal queries
  4. Use for: financial systems, audit-heavy domains, event replay requirements


4. EventBridge vs SNS vs SQS

Exam Tip EDA: "Event routing with rules" = EventBridge. "Fan-out one-to-many" = SNS → SQS. "Decouple + buffer" = SQS. "Streaming + replay" = Kinesis. "Saga / distributed transactions" = Step Functions. "CQRS" = separate read/write stores. "Event on S3 upload" = S3 Event Notification. "DynamoDB change events" = DynamoDB Streams. EventBridge = default choice for event-driven patterns.