Cloud Event Driven Architecture

Production engineering guide for cloud event driven architecture covering patterns, implementation strategies, and operational best practices.

Cloud Event Driven Architecture (EDA) is a design pattern where components communicate through events—discrete, meaningful facts about state changes in a system. It matters when systems must react to real-time data, scale independently, and tolerate failures gracefully: in microservices, real-time analytics, order processing, or IoT pipelines. Events decouple producers and consumers, enabling systems to evolve without coordination.

Core Components and Their Roles

An event is a self-contained message containing metadata and a payload. It is emitted when a significant change occurs—such as OrderCreated, PaymentProcessed, or UserSignedUp. The architecture relies on a message broker to store and deliver events reliably. The broker must persist events across restarts, support multiple consumers, and handle backpressure.

The primary operations are:

The message broker typically supports:

Publishing Events

A producer emits an event by sending a structured message to a broker endpoint. The message must include:

Example of a published event:

{
  "event_id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
  "event_type": "OrderCreated",
  "timestamp": "2024-09-18T14:32:15.123Z",
  "data": {
    "order_id": "ORD-2024-09-18-001",
    "customer_id": "CUST-1001",
    "items": [
      { "product_id": "P-101", "quantity": 2 },
      { "product_id": "P-102", "quantity": 1 }
    ],
    "total_amount": 159.99
  },
  "schema_id": "order.v1"
}

Publishing is done over HTTP POST to a topic endpoint:

curl -X POST https://events.example.com/topics/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "event_id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
    "event_type": "OrderCreated",
    "timestamp": "2024-09-18T14:32:15.123Z",
    "data": {
      "order_id": "ORD-2024-09-18-001",
      "customer_id": "CUST-1001",
      "items": [
        { "product_id": "P-101", "quantity": 2 },
        { "product_id": "P-102", "quantity": 1 }
      ],
      "total_amount": 159.99
    },
    "schema_id": "order.v1"
  }'

The broker returns a 202 Accepted with the assigned event_id and offset in the response:

{
  "event_id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
  "offset": 12345,
  "status": "accepted",
  "message": "Event successfully queued for delivery"
}

Consuming Events

Consumers poll or stream events from a topic. The most common approach is pull-based consumption using a start_offset and batch_size parameter.

A consumer reads events from a topic with:

curl -X GET "https://events.example.com/topics/orders?group_id=order-processing&start_offset=12345&batch_size=10" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

The response is a list of events:

{
  "events": [
    {
      "event_id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
      "event_type": "OrderCreated",
      "timestamp": "2024-09-18T14:32:15.123Z",
      "data": {
        "order_id": "ORD-2024-09-18-001",
        "customer_id": "CUST-1001",
        "items": [
          { "product_id": "P-101", "quantity": 2 },
          { "product_id": "P-102", "quantity": 1 }
        ],
        "total_amount": 159.99
      },
      "schema_id": "order.v1"
    },
    {
      "event_id": "b2c3d4e5-f6g7-8901-h2i3-j4k5l6m7n8o9",
      "event_type": "OrderUpdated",
      "timestamp": "2024-09-18T14:32:16.456Z",
      "data": {
        "order_id": "ORD-2024-09-18-001",
        "status": "shipped",
        "tracking_number": "TRK-2024-09-18-001"
      },
      "schema_id": "order.v1"
    }
  ],
  "next_offset": 12357,
  "last_offset": 12357
}

The consumer updates its offset to next_offset and uses it in the next request.

Event Processing with Backpressure and Failure Handling

When a consumer processes events, it must acknowledge them upon successful handling. Acknowledgment prevents reprocessing and enables exactly-once semantics.

A consumer sends an acknowledgment:

curl -X PUT "https://events.example.com/consumers/order-processing/offsets" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "group_id": "order-processing",
    "topic": "orders",
    "offset": 12357,
    "processed_at": "2024-09-18T14:33:00.000Z"
  }'

The broker records the offset per group and topic. If the consumer crashes after processing 10 events but before sending the ACK, the broker retries delivery from the last saved offset.

Failure modes:

To mitigate this, use idempotent event handlers:

CREATE TABLE processed_events (
  event_id UUID PRIMARY KEY,
  processed_at TIMESTAMP WITH TIME ZONE,
  processed_by TEXT,
  metadata JSONB
);

When processing an event, the handler first checks:

SELECT event_id FROM processed_events WHERE event_id = 'a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8';

If present, it skips processing. If not, it processes the event and inserts the record.

Schema Evolution and Event Versioning

Events may evolve over time. A consumer must handle multiple versions of the same event type.

The schema_id field in the event payload allows versioning. The broker can store the schema for each schema_id and validate incoming events.

A schema might be:

{
  "title": "OrderCreated",
  "type": "object",
  "properties": {
    "order_id": { "type": "string" },
    "customer_id": { "type": "string" },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "product_id": { "type": "string" },
          "quantity": { "type": "integer" }
        }
      }
    },
    "total_amount": { "type": "number" }
  },
  "required": ["order_id", "customer_id", "items", "total_amount"]
}

The broker validates incoming events against the schema. If validation fails, it returns:

{
  "error": "schema_validation_failed",
  "message": "Invalid schema for OrderCreated",
  "details": [
    "Missing required property: total_amount",
    "Invalid type for items: expected array, got object"
  ],
  "event_id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
  "schema_id": "order.v1"
}

Consumers can handle schema evolution by:

Event-Driven Workflows and Chaining

Events can trigger cascading actions. A OrderCreated event may lead to:

Each service emits its own event, which may be consumed by other services.

A workflow might be:

OrderCreated → InvoiceGenerated → PaymentScheduled → ShipmentScheduled

This is achieved by:

A service consuming OrderCreated may emit OrderProcessed:

{
  "event_id": "c3d4e5f6-g7h8-9012-i3j4-k5l6m7n8o9p1",
  "event_type": "OrderProcessed",
  "timestamp": "2024-09-18T14:33:15.000Z",
  "data": {
    "order_id": "ORD-2024-09-18-001",
    "invoice_id": "INV-2024-09-18-001",
    "payment_status": "scheduled",
    "shipment_status": "pending"
  },
  "schema_id": "order.processed.v1"
}

This event is published to the orders topic. Another service, shipment-service, subscribes to OrderProcessed and triggers a shipment.

Common Pitfalls and Sharp Edges

Best Practices

Cloud Event Driven Architecture is not a technology stack—it is a discipline of designing systems around events. When done well, it delivers resilience, scalability, and responsiveness.

This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.