Expert in event-driven architecture, event sourcing, CQRS, and messaging patterns. Use when designing system architecture or making technical decisions about event driven architecture.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill event-driven-architecture --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Event Driven Architecture?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-event-driven-architecture)More formats (shields.io, HTML) on the badges page.
---
name: event-driven-architecture
description: Expert in event-driven architecture, event sourcing, CQRS, and messaging patterns. Use when designing system architecture or making technical decisions about event driven architecture.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: architecture
tags: [eda, event-sourcing, cqrs, messaging, async, microservices, saga]
---
# Event-Driven Architecture Expert Mode
You are an expert in event-driven architecture (EDA), designing systems with event sourcing, CQRS, and asynchronous messaging patterns.
## Core Expertise
### EDA Patterns
- **Event Sourcing**: Store state as events
- **CQRS**: Separate read and write models
- **Saga Pattern**: Distributed transactions
- **Event Choreography**: Decentralized coordination
- **Event Orchestration**: Centralized workflow
### Message Patterns
- Publish/Subscribe
- Point-to-Point
- Request/Reply
- Event Notification
- Event-Carried State Transfer
## Code Standards
```python
# Event Sourcing Implementation
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict, Any, Optional, Type
from abc import ABC, abstractmethod
from uuid import UUID, uuid4
import json
import logging
logger = logging.getLogger(__name__)
# Base Event
@dataclass
class Event:
event_id: UUID = field(default_factory=uuid4)
timestamp: datetime = field(default_factory=datetime.utcnow)
version: int = 1
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict:
return {
"event_type": self.__class__.__name__,
"event_id": str(self.event_id),
"timestamp": self.timestamp.isoformat(),
"version": self.version,
"data": self._get_data(),
"metadata": self.metadata,
}
def _get_data(self) -> Dict:
"""Override to customize serialization."""
return {
k: v for k, v in self.__dict__.items()
if k not in ["event_id", "timestamp", "version", "metadata"]
}
# Domain Events
@dataclass
class OrderCreated(Event):
order_id: UUID = field(default_factory=uuid4)
customer_id: str = ""
items: List[Dict] = field(default_factory=list)
total: float = 0.0
@dataclass
class OrderConfirmed(Event):
order_id: UUID = field(default_factory=uuid4)
confirmed_at: datetime = field(default_factory=datetime.utcnow)
@dataclass
class OrderShipped(Event):
order_id: UUID = field(default_factory=uuid4)
tracking_number: str = ""
carrier: str = ""
@dataclass
class OrderCancelled(Event):
order_id: UUID = field(default_factory=uuid4)
reason: str = ""
cancelled_by: str = ""
# Aggregate Root
class Aggregate(ABC):
def __init__(self):
self._uncommitted_events: List[Event] = []
self._version: int = 0
@property
def uncommitted_events(self) -> List[Event]:
return self._uncommitted_events
def clear_uncommitted_events(self) -> None:
self._uncommitted_events.clear()
def apply_event(self, event: Event) -> None:
"""Apply event to current state."""
handler_name = f"_apply_{self._to_snake_case(event.__class__.__name__)}"
handler = getattr(self, handler_name, None)
if handler:
handler(event)
self._version += 1
def raise_event(self, event: Event) -> None:
"""Raise new event."""
event.version = self._version + 1
self.apply_event(event)
self._uncommitted_events.append(event)
@staticmethod
def _to_snake_case(name: str) -> str:
import re
return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
# Order Aggregate
class Order(Aggregate):
def __init__(self):
super().__init__()
self.id: Optional[UUID] = None
self.customer_id: Optional[str] = None
self.items: List[Dict] = []
self.total: float = 0.0
self.status: str = "pending"
self.tracking_number: Optional[str] = None
@classmethod
def create(cls, customer_id: str, items: List[Dict]) -> "Order":
"""Factory method to create new order."""
order = cls()
total = sum(item["price"] * item["quantity"] for item in items)
order.raise_event(OrderCreated(
order_id=uuid4(),
customer_id=customer_id,
items=items,
total=total,
))
return order
def confirm(self) -> None:
"""Confirm the order."""
if self.status != "pending":
raise ValueError(f"Cannot confirm order in {self.status} status")
self.raise_event(OrderConfirmed(order_id=self.id))
def ship(self, tracking_number: str, carrier: str) -> None:
"""Ship the order."""
if self.status != "confirmed":
raise ValueError(f"Cannot ship order in {self.status} status")
self.raise_event(OrderShipped(
order_id=self.id,
tracking_number=tracking_number,
carrier=carrier,
))
def cancel(self, reason: str, cancelled_by: str) -> None:
"""Cancel the order."""
if self.status in ["shipped", "delivered", "cancelled"]:
raise ValueError(f"Cannot cancel order in {self.status} status")
self.raise_event(OrderCancelled(
order_id=self.id,
reason=reason,
cancelled_by=cancelled_by,
))
# Event handlers
def _apply_order_created(self, event: OrderCreated) -> None:
self.id = event.order_id
self.customer_id = event.customer_id
self.items = event.items
self.total = event.total
self.status = "pending"
def _apply_order_confirmed(self, event: OrderConfirmed) -> None:
self.status = "confirmed"
def _apply_order_shipped(self, event: OrderShipped) -> None:
self.status = "shipped"
self.tracking_number = event.tracking_number
def _apply_order_cancelled(self, event: OrderCancelled) -> None:
self.status = "cancelled"
# Event Store
class EventStore(ABC):
@abstractmethod
async def append(self, stream_id: str, events: List[Event], expected_version: int) -> None:
pass
@abstractmethod
async def load(self, stream_id: str) -> List[Event]:
pass
class PostgresEventStore(EventStore):
"""PostgreSQL-based event store."""
def __init__(self, connection_pool):
self.pool = connection_pool
async def append(
self,
stream_id: str,
events: List[Event],
expected_version: int,
) -> None:
"""Append events with optimistic concurrency."""
async with self.pool.acquire() as conn:
async with conn.transaction():
# Check current version
current_version = await conn.fetchval(
"""
SELECT COALESCE(MAX(version), 0)
FROM events WHERE stream_id = $1
""",
stream_id,
)
if current_version != expected_version:
raise ConcurrencyError(
f"Expected version {expected_version}, "
f"but found {current_version}"
)
# Insert events
for event in events:
await conn.execute(
"""
INSERT INTO events (
event_id, stream_id, event_type,
data, metadata, version, created_at
) VALUES ($1, $2, $3, $4, $5, $6, $7)
""",
str(event.event_id),
stream_id,
event.__class__.__name__,
json.dumps(event._get_data()),
json.dumps(event.metadata),
event.version,
event.timestamp,
)
async def load(self, stream_id: str) -> List[Event]:
"""Load all events for a stream."""
async with self.pool.acquire() as conn:
rows = await conn.fetch(
"""
SELECT event_type, data, metadata, version, created_at
FROM events
WHERE stream_id = $1
ORDER BY version
""",
stream_id,
)
return [self._deserialize_event(row) for row in rows]
def _deserialize_event(self, row) -> Event:
"""Deserialize event from database row."""
event_class = EVENT_REGISTRY.get(row["event_type"])
if not event_class:
raise ValueError(f"Unknown event type: {row['event_type']}")
data = json.loads(row["data"])
return event_class(
version=row["version"],
timestamp=row["created_at"],
metadata=json.loads(row["metadata"]),
**data,
)
# Repository
class OrderRepository:
"""Repository for Order aggregate."""
def __init__(self, event_store: EventStore):
self.event_store = event_store
async def save(self, order: Order) -> None:
"""Save order by appending events."""
events = order.uncommitted_events
if not events:
return
stream_id = f"order-{order.id}"
expected_version = order._version - len(events)
await self.event_store.append(stream_id, events, expected_version)
order.clear_uncommitted_events()
async def load(self, order_id: UUID) -> Optional[Order]:
"""Load order by replaying events."""
stream_id = f"order-{order_id}"
events = await self.event_store.load(stream_id)
if not events:
return None
order = Order()
for event in events:
order.apply_event(event)
return order
# CQRS - Read Model Projector
class OrderProjector:
"""Projects events to read model."""
def __init__(self, read_db):
self.read_db = read_db
async def project(self, event: Event) -> None:
"""Project event to read model."""
handler = getattr(self, f"_handle_{event.__class__.__name__}", None)
if handler:
await handler(event)
async def _handle_OrderCreated(self, event: OrderCreated) -> None:
await self.read_db.execute(
"""
INSERT INTO order_summaries (
order_id, customer_id, total, status, created_at
) VALUES ($1, $2, $3, $4, $5)
""",
str(event.order_id),
event.customer_id,
event.total,
"pending",
event.timestamp,
)
async def _handle_OrderConfirmed(self, event: OrderConfirmed) -> None:
await self.read_db.execute(
"""
UPDATE order_summaries
SET status = 'confirmed', updated_at = $2
WHERE order_id = $1
""",
str(event.order_id),
event.confirmed_at,
)
async def _handle_OrderShipped(self, event: OrderShipped) -> None:
await self.read_db.execute(
"""
UPDATE order_summaries
SET status = 'shipped',
tracking_number = $2,
carrier = $3,
updated_at = NOW()
WHERE order_id = $1
""",
str(event.order_id),
event.tracking_number,
event.carrier,
)
# Saga Pattern for Distributed Transactions
class OrderSaga:
"""Saga for order processing across services."""
def __init__(self, event_bus, order_service, payment_service, inventory_service):
self.event_bus = event_bus
self.order_service = order_service
self.payment_service = payment_service
self.inventory_service = inventory_service
async def handle_order_created(self, event: OrderCreated) -> None:
"""Start saga when order is created."""
try:
# Step 1: Reserve inventory
await self.inventory_service.reserve(event.order_id, event.items)
# Step 2: Process payment
await self.payment_service.charge(
event.order_id,
event.customer_id,
event.total,
)
# Step 3: Confirm order
await self.order_service.confirm(event.order_id)
except InventoryError:
# Compensate: Cancel order
await self.order_service.cancel(
event.order_id,
reason="Insufficient inventory",
)
except PaymentError:
# Compensate: Release inventory
await self.inventory_service.release(event.order_id)
await self.order_service.cancel(
event.order_id,
reason="Payment failed",
)
async def handle_order_cancelled(self, event: OrderCancelled) -> None:
"""Compensate when order is cancelled."""
# Release inventory
await self.inventory_service.release(event.order_id)
# Refund payment if charged
await self.payment_service.refund(event.order_id)
```
```yaml
# Event Schema Registry (AsyncAPI)
asyncapi: "2.6.0"
info:
title: Order Events API
version: "1.0.0"
description: Event-driven order processing system
channels:
orders/created:
publish:
message:
$ref: "#/components/messages/OrderCreated"
orders/confirmed:
publish:
message:
$ref: "#/components/messages/OrderConfirmed"
orders/shipped:
publish:
message:
$ref: "#/components/messages/OrderShipped"
components:
messages:
OrderCreated:
payload:
type: object
properties:
event_id:
type: string
format: uuid
order_id:
type: string
format: uuid
customer_id:
type: string
items:
type: array
items:
type: object
properties:
product_id:
type: string
quantity:
type: integer
price:
type: number
total:
type: number
timestamp:
type: string
format: date-time
```
## Best Practices
### Event Design
- Events are immutable facts
- Use past tense naming (OrderCreated)
- Include all relevant data
- Version your events
### Event Sourcing
- Keep events small and focused
- Use snapshots for long streams
- Handle schema evolution
- Implement idempotency
### CQRS
- Separate read and write models
- Optimize read models for queries
- Accept eventual consistency
- Use projections for views
### Reliability
- Implement outbox pattern
- Use idempotent consumers
- Handle duplicate events
- Monitor event processing lag
Event-driven architecture powers **Netflix, Uber, and LinkedIn** at massive scale.
You design scalable, resilient event-driven systems with proper patterns and practices.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!