# From Request-Response to Events — Event-Driven Architecture & CQRS

Source: https://www.skillbyai.com/en/event-driven-architecture/f-why

> Explain the coupling problems of synchronous call chains and how events reduce them.

## Telling others what happened

In a **request-response** design, the Orders service calls Payments, then Inventory, then Email, and waits for each. Every service must be **up at the same moment** (temporal coupling), Orders must **know every downstream service** and its API, and one slow dependency slows the whole chain. In an **event-driven architecture (EDA)**, Orders records the order and **publishes an event**, `OrderPlaced`, to a broker. Payments, Inventory, Email and Analytics **subscribe** and react in their own time. Orders no longer knows who is listening, so adding a new consumer (say, a loyalty-points service) needs no change to Orders. The price is new complexity: work becomes **asynchronous**, data becomes **eventually consistent**, and the flow of a business process is spread across services, so it is harder to see and debug.

## Call chain versus published event

On the left, one service calls each dependency in turn; on the right, it publishes once and many consumers react.

![Left side: a box with a chain of arrows to three boxes in sequence. Right side: a box sending one arrow into a broker bar, which fans out arrows to four boxes.](assets/figures/event-driven-architecture/section-1-map.svg) — Figure 1.1 — Synchronous call chain compared with publish-subscribe.

## Two ways to place an order

The synchronous version fails if any dependency is down; the event version only needs the broker.

```python
# synchronous orchestration: Orders knows and waits for everyone
def place_order_sync(order):
    save(order)
    payments.charge(order)          # down? the order fails
    inventory.reserve(order)        # slow? the user waits
    email.send_confirmation(order)  # new requirement? edit this function

# event-driven: Orders records a fact and publishes it
def place_order_evented(order):
    save(order)
    broker.publish("orders.placed", {
        "type": "OrderPlaced",
        "orderId": order.id,
        "customerId": order.customer_id,
        "total": str(order.total),
    })
    # Payments, Inventory, Email and Analytics each subscribe independently
```

## A wedding announcement

Phoning each relative one by one is request-response: if someone does not pick up, you are stuck. Posting the news in the family group is an event: everyone reads it when they can, and a cousin who joins the group later can still react.

**Quiz:** What kind of coupling does publishing events mainly remove?

- [x] Temporal coupling, where the caller and every dependency must be available at the same time
- [ ] Coupling to the programming language
- [ ] Coupling to the database engine
- [ ] All coupling of any kind

*Answer:* Temporal coupling, where the caller and every dependency must be available at the same time. Consumers process events when they are available; the publisher does not wait for them.
