Claude-skill-registry Event Style Guide
Event-driven design conventions: event envelope, naming, versioning, schema evolution rules, idempotency, ordering/partitioning, retry and dead-letter handling
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/event-style-guide" ~/.claude/skills/majiayu000-claude-skill-registry-event-style-guide && rm -rf "$T"
manifest:
skills/data/event-style-guide/SKILL.mdsource content
Event Style Guide
Overview
มาตรฐานการออกแบบ events สำหรับ event-driven architecture: envelope format, naming, versioning, และ schema evolution ที่ทำให้ระบบ decouple ได้อย่างปลอดภัย
Why This Matters
- Interoperability: ทุก service เข้าใจ event format เดียวกัน
- Evolution: เปลี่ยน schema โดยไม่ break consumers
- Debugging: Trace events ข้าม services ได้
- Contract: Clear agreement between producers/consumers
Core Concepts
1. Event Envelope Structure
- ทุก event ต้องเป็น envelope เดียวกัน เพื่อให้ tooling/observability ทำงานได้
- metadata ต้องมี
,id
,type
,source
,timespecVersion - correlation ต้องมี
(ผูกกับ request/trace) และcorrelationId
(optional)causationId - payload อยู่ใน
เท่านั้น (หลีกเลี่ยง “metadata ปน payload”)data
2. Event Naming Convention
- รูปแบบ:
<domain>.<entity>.<action>.v<major> - ใช้ past-tense สำหรับ domain events (
,created
,updated
)completed - actions ต้องสื่อความหมายและไม่กว้างเกินไป (หลีกเลี่ยง
,changed
ถ้าไม่จำเป็น)processed
3. Event Versioning
- version ใน
เป็น major เพื่อบอก breaking changes:typeuser.created.v1 - changes แบบ non-breaking (เพิ่ม field optional) ไม่ต้อง bump major แต่ควร track schema version ใน registry
- หากต้อง breaking: ออก
และรองรับ consumers เก่าในช่วง deprecationv2
4. Schema Evolution
กฎหลัก: consumers ต้อง “ignore unknown fields” และ producers ต้องไม่ลบ/เปลี่ยนความหมาย field เดิมภายใน major เดียวกัน
- ✅ เพิ่ม field optional (หรือเพิ่ม enum values แบบ backward-compatible ถ้า consumers handle unknown)
- ❌ ลบ field, rename field, เปลี่ยน type, เพิ่ม required field
- ถ้าจำเป็นต้อง rename: ทำแบบ “add new + deprecate old” แล้วค่อยตัดใน major ถัดไป
5. Event Types
- Domain events: facts ที่เกิดขึ้นแล้ว (source-of-truth) เช่น
order.payment.completed.v1 - Integration events: แปล domain event สำหรับระบบอื่น/ภายนอก (อาจ mask/redact fields)
- Commands: “ขอให้ทำ” (ควรเป็น request/response หรือ separate channel) ไม่ควรปนกับ domain events
6. Idempotency
ต้อง unique (UUID v4) และใช้สำหรับ dedupe ที่ consumerid- consumer ต้อง idempotent: บันทึก
ที่ process แล้ว หรือใช้ upsert/deterministic state transitionseventId - ถ้า broker อาจส่งซ้ำ (at-least-once) ให้คาดไว้ตั้งแต่แรก
7. Event Ordering
- ถ้าต้องการ ordering ให้ define partition key (เช่น
,tenantId
) และส่งไป partition เดียวกันorderId - ถ้าต้อง strict ordering ต่อ entity ให้มี
(optional) ในsequence
หรือdatadetails - หลีกเลี่ยงการพึ่ง ordering ข้าม partition (แทบไม่รับประกัน)
8. Dead Letter Handling
- define retry policy: exponential backoff + jitter + max attempts
- classify errors: retryable vs non-retryable (validation/domain errors ไม่ควร retry)
- เมื่อเกิน max retries ให้ส่ง DLQ พร้อม metadata ที่พอสำหรับ replay (แต่ไม่ใส่ secrets/PII เกินจำเป็น)
- ต้องมี playbook: “inspect → fix → replay”
Quick Start
export interface EventEnvelope<T> { id: string; type: string; source: string; specVersion: "1.0"; time: string; correlationId: string; causationId?: string; dataContentType: "application/json"; dataSchema?: string; data: T; } export type UserCreatedV1 = EventEnvelope<{ userId: string; email: string; tenantId: string; }>;
Production Checklist
- All events follow envelope standard
- Event naming consistent
- Version in every event
- Schema registered in registry
- Idempotency keys present
- Dead letter queue configured
Event Envelope Standard
interface EventEnvelope<T> { // Metadata id: string; // UUID v4 type: string; // "user.created.v1" source: string; // "user-service" specVersion: string; // "1.0" time: string; // ISO 8601 // Correlation correlationId: string; // Request correlation causationId?: string; // Causing event ID // Payload data: T; // Event-specific data dataContentType: string; // "application/json" dataSchema?: string; // Schema URL }
Retry & DLQ Policy (ตัวอย่าง)
- retry: 1s, 5s, 15s, 1m, 5m (max 5 ครั้ง) + jitter
- non-retryable:
,VAL_
,BIZ_
,AUTH_
(ส่ง DLQ ทันทีหรือ discard ตาม policy)AUTHZ_ - DLQ message ต้องมี: original
,event.id
, error summary, attempt count, first/last seen timestampevent.type
Event Naming Convention
# Format: <domain>.<entity>.<action>.v<version> # Examples: user.account.created.v1 order.payment.completed.v1 inventory.stock.reserved.v1 notification.email.sent.v1 # Actions (past tense for domain events): - created, updated, deleted - completed, failed, cancelled - started, finished, expired
Schema Evolution Rules
| Change Type | Compatibility | Example |
|---|---|---|
| Add optional field | ✅ Safe | Add |
| Add required field | ❌ Breaking | Add |
| Remove field | ❌ Breaking | Remove |
| Rename field | ❌ Breaking | → |
| Change type | ❌ Breaking | → |
Anti-patterns
- No versioning: Can't evolve schemas
- Massive payloads: Events too large
- Missing correlation: Can't trace flows
- Shared events: Tight coupling between services
- Hidden contracts: schema อยู่ใน code แต่ไม่มี registry/docs
Integration Points
- Message brokers (Kafka, RabbitMQ)
- Schema registries
- Event stores
- Monitoring systems