Skill — Event-Driven Architecture
When this skill activates
Any task involving event bus design, pub/sub patterns, message ordering,
delivery guarantees, dead letter handling, or event schema evolution.
Mandatory actions when this skill is active
Before writing any code
- Classify event types (domain, integration, or command events).
- Define delivery guarantees required for each event stream.
- Design the event schema with forward/backward compatibility in mind.
During implementation
- Make all consumers idempotent (safe to process same event multiple times).
- Implement dead letter topic handling with alerting.
- Use partition keys to maintain ordering where required.
After implementation
- Register events in the event catalog with schema and owner.
- Add consumer lag monitoring.
- Document retry and failure handling in ARCHITECTURE.md.
Event Types
Domain Events
- Facts about what happened in a bounded context.
- Named in past tense:
OrderPlaced, PaymentProcessed, UserRegistered.
- Owned by the producing domain — consumers must adapt.
- Immutable once published.
Integration Events
- Cross-boundary communication between services.
- May be transformed from domain events (different schema, less detail).
- Published on shared event bus (Kafka, SNS, EventBridge).
Command Events
- Request for action (not a fact).
- Named as imperative:
ProcessPayment, SendNotification.
- Exactly one consumer expected to handle.
- Requires acknowledgment/response.
Delivery Guarantees
At-Most-Once
- Fire and forget. No retries.
- Use for: metrics, analytics, non-critical notifications.
- Risk: message loss on failure.
At-Least-Once (Recommended Default)
- Retry until acknowledged.
- Consumers MUST be idempotent.
- Use for: most business events.
- Risk: duplicate processing (mitigated by idempotency).
Exactly-Once (Expensive)
- Requires transactional outbox + deduplication.
- Use for: financial transactions, inventory changes.
- Implementation: idempotency key + processed event log.
Ordering Guarantees
Per-Partition Ordering
- Events with the same partition key are ordered.
- Partition key = entity ID (e.g., order_id, user_id).
- Different entities may be processed out of order (acceptable).
Global Ordering
- Extremely expensive — single partition = no parallelism.
- Almost never needed — design around per-entity ordering instead.
Kafka Partition Key Design
topic: order-events
partition_key: order_id
result: all events for order-123 arrive in sequence
Schema Evolution
Compatibility Modes (Avro/Protobuf)
- Backward compatible: new schema can read old data (add optional fields).
- Forward compatible: old schema can read new data (ignore unknown fields).
- Full compatible: both directions (safest, most restrictive).
Rules for Safe Evolution
- Adding optional fields: always safe.
- Removing fields: only if no consumers depend on them.
- Renaming fields: treat as remove + add (breaking).
- Changing field types: always breaking.
Schema Registry
- Central registry of all event schemas with version history.
- Validates compatibility before allowing schema updates.
- Consumers reference schema by ID (embedded in message header).
Consumer Groups
Competing Consumers (Scaling Pattern)
- Multiple instances in same group share the load.
- Each message processed by exactly one instance.
- Use for: order processing, notification sending.
- Scale by adding more consumers (up to partition count).
Broadcasting (Fan-Out Pattern)
- Each consumer group gets every message.
- Use for: audit logging, cache invalidation, analytics.
- Different groups process independently at their own pace.
Dead Letter Topics (DLT)
Flow
message → consumer → FAIL → retry (3x with backoff) → FAIL → DLT → alert
Requirements
- Every consumer MUST have a DLT configured.
- DLT messages retain full context (original message + error + attempt count).
- Alert on first DLT message (don't silently accumulate).
- Manual resolution workflow: inspect → fix → replay or discard.
Retry Strategy
- Attempt 1: immediate.
- Attempt 2: 1 second delay.
- Attempt 3: 10 second delay.
- After 3 failures: route to DLT.
Event Catalog
Every event in the system must be registered:
| Field |
Description |
| Event name |
OrderPlaced |
| Schema version |
v3 |
| Owner (team) |
Order Service team |
| Producers |
order-service |
| Consumers |
notification-svc, analytics-svc, fulfillment-svc |
| Partition key |
order_id |
| Delivery guarantee |
at-least-once |
| Retention |
7 days |
Self-check before task completion
Before marking a task done when this skill was active:
1---2name: event-driven-architecture3description: Skill — Event-Driven Architecture4---56# Skill — Event-Driven Architecture78## When this skill activates9Any task involving event bus design, pub/sub patterns, message ordering,10delivery guarantees, dead letter handling, or event schema evolution.1112## Mandatory actions when this skill is active1314### Before writing any code151. Classify event types (domain, integration, or command events).162. Define delivery guarantees required for each event stream.173. Design the event schema with forward/backward compatibility in mind.1819### During implementation20- Make all consumers idempotent (safe to process same event multiple times).21- Implement dead letter topic handling with alerting.22- Use partition keys to maintain ordering where required.2324### After implementation25- Register events in the event catalog with schema and owner.26- Add consumer lag monitoring.27- Document retry and failure handling in ARCHITECTURE.md.2829## Event Types3031### Domain Events32- Facts about what happened in a bounded context.33- Named in past tense: `OrderPlaced`, `PaymentProcessed`, `UserRegistered`.34- Owned by the producing domain — consumers must adapt.35- Immutable once published.3637### Integration Events38- Cross-boundary communication between services.39- May be transformed from domain events (different schema, less detail).40- Published on shared event bus (Kafka, SNS, EventBridge).4142### Command Events43- Request for action (not a fact).44- Named as imperative: `ProcessPayment`, `SendNotification`.45- Exactly one consumer expected to handle.46- Requires acknowledgment/response.4748## Delivery Guarantees4950### At-Most-Once51- Fire and forget. No retries.52- Use for: metrics, analytics, non-critical notifications.53- Risk: message loss on failure.5455### At-Least-Once (Recommended Default)56- Retry until acknowledged.57- Consumers MUST be idempotent.58- Use for: most business events.59- Risk: duplicate processing (mitigated by idempotency).6061### Exactly-Once (Expensive)62- Requires transactional outbox + deduplication.63- Use for: financial transactions, inventory changes.64- Implementation: idempotency key + processed event log.6566## Ordering Guarantees6768### Per-Partition Ordering69- Events with the same partition key are ordered.70- Partition key = entity ID (e.g., order_id, user_id).71- Different entities may be processed out of order (acceptable).7273### Global Ordering74- Extremely expensive — single partition = no parallelism.75- Almost never needed — design around per-entity ordering instead.7677### Kafka Partition Key Design78```79topic: order-events80partition_key: order_id81result: all events for order-123 arrive in sequence82```8384## Schema Evolution8586### Compatibility Modes (Avro/Protobuf)87- **Backward compatible**: new schema can read old data (add optional fields).88- **Forward compatible**: old schema can read new data (ignore unknown fields).89- **Full compatible**: both directions (safest, most restrictive).9091### Rules for Safe Evolution92- Adding optional fields: always safe.93- Removing fields: only if no consumers depend on them.94- Renaming fields: treat as remove + add (breaking).95- Changing field types: always breaking.9697### Schema Registry98- Central registry of all event schemas with version history.99- Validates compatibility before allowing schema updates.100- Consumers reference schema by ID (embedded in message header).101102## Consumer Groups103104### Competing Consumers (Scaling Pattern)105- Multiple instances in same group share the load.106- Each message processed by exactly one instance.107- Use for: order processing, notification sending.108- Scale by adding more consumers (up to partition count).109110### Broadcasting (Fan-Out Pattern)111- Each consumer group gets every message.112- Use for: audit logging, cache invalidation, analytics.113- Different groups process independently at their own pace.114115## Dead Letter Topics (DLT)116117### Flow118```119message → consumer → FAIL → retry (3x with backoff) → FAIL → DLT → alert120```121122### Requirements123- Every consumer MUST have a DLT configured.124- DLT messages retain full context (original message + error + attempt count).125- Alert on first DLT message (don't silently accumulate).126- Manual resolution workflow: inspect → fix → replay or discard.127128### Retry Strategy129- Attempt 1: immediate.130- Attempt 2: 1 second delay.131- Attempt 3: 10 second delay.132- After 3 failures: route to DLT.133134## Event Catalog135136Every event in the system must be registered:137138| Field | Description |139|-------|-------------|140| Event name | `OrderPlaced` |141| Schema version | `v3` |142| Owner (team) | Order Service team |143| Producers | order-service |144| Consumers | notification-svc, analytics-svc, fulfillment-svc |145| Partition key | order_id |146| Delivery guarantee | at-least-once |147| Retention | 7 days |148149## Self-check before task completion150151Before marking a task done when this skill was active:152153- [ ] Did I read the full SKILL.md before starting? (Not just the triggers)154- [ ] Are all consumers idempotent?155- [ ] Is ordering guaranteed per entity via partition keys?156- [ ] Is dead letter topic configured with alerting?157- [ ] Are event schemas registered in the catalog?158- [ ] Is schema evolution backward-compatible?159- [ ] Are consumer groups configured correctly (competing vs broadcasting)?