บทที่ 28 · Part 5 — From Model to Running System

Event Sourcing Selectively

ประเมิน history, temporal query และ audit value เทียบกับ schema evolution, projection และ operational cost

Event Sourcing Selectively

เพราะ domain มี events ไม่ได้แปลว่าต้องใช้ Event Sourcing Pattern นี้เก็บ event sequence เป็น source of record และ derive current state จึงให้ temporal/history power แต่เพิ่ม schema evolution, projection, replay, privacy และ operational complexity เลือกเฉพาะ context/aggregate ที่ value ชนะ cost

จบบทนี้คุณจะ

แยก Event Sourcing จาก Domain/Integration Events ประเมิน temporal/audit/reconstruction value ออกแบบ event stream, optimistic concurrency, projections, upcasting/migration และ correction พร้อมอธิบายเมื่อ CRUD state + audit log ง่ายกว่า

Pattern คืออะไร

Azure Event Sourcing Pattern อธิบายการ append events ที่อธิบาย state changes และ rebuild state โดย replay Current state ไม่ใช่ source หลัก

TransferIntentOpened
BeneficiarySelected
TransferIntentConfirmed
CancellationRequested
TransferIntentCancelled

events ต้องเป็น durable facts สำหรับ stream ไม่ใช่ทุก technical notification

ภาพนี้แยก 2 path: command replay stream เพื่อใช้ authoritative model ตัดสิน ส่วน query อ่าน projection ที่ rebuild ได้ การมี event bus หรือ integration events ยังเป็นอีก concern ไม่ได้เกิดฟรี

Value Hypotheses

Event Sourcing อาจคุ้มเมื่อ:

  • ต้องตอบ state ณ เวลา/decision ย้อนหลัง
  • business ให้ value กับ complete change history
  • rules เปลี่ยนและต้อง recompute projections
  • event stream เป็น natural model ของ domain
  • audit/explainability requirement ได้รับการยืนยัน

ไม่ควรเลือกเพียงเพราะ “ Fintech ต้อง audit” Audit record ที่ immutable แยกอาจพอ และ compliance owner ต้องกำหนด evidence/retention/access จริง

Costs

  • event schema immutable-like และ evolution ยาก
  • replay code ทุก version ต้องถูก
  • projections lag/rebuild/monitoring
  • event store operations/backup
  • deletion/privacy conflicts
  • debugging temporal behavior
  • team skill/tooling/on-call
  • integration events ยังแยกจาก internal stream

Stream Boundary และ Concurrency

มัก stream ต่อ Aggregate ID ใช้ expected version เพื่อ optimistic concurrency:

append events to stream transfer-intent/T-104 expectedVersion=7

conflict ต้องกลับ domain semantics ไม่ blind merge

Event Design

Events past tense, capture fact/context พอ replay และไม่ผูก UI/vendor DTO:

{
  "type": "transfer-intent-confirmed.v2",
  "intentId": "T-104",
  "amountMinor": 150000,
  "currency": "THB",
  "termsVersion": "terms-2026-08",
  "occurredAt": "2026-08-11T10:04:00Z"
}

ค่าคือ scenario illustrative ไม่ใช่ policy

Evolution

ทางเลือก:

  • upcast old event on read
  • transform/migrate stream อย่างควบคุม
  • support multiple handlers
  • add corrective event แทน rewrite history
  • snapshot เพื่อ performance แต่ stream ยัง authority

ต้องมี test fixtures historical และ rebuild rehearsal

Immutable ไม่ได้แปลว่าเก็บได้ตลอด

Personal/sensitive data retention, deletion, encryption/key destruction และ access ต้องมาจาก accountable privacy/compliance/security owners พร้อม jurisdiction/version/date Event Sourcing ไม่ทำให้ compliant อัตโนมัติ

Projection และ Decision

Projection สำหรับ query/display อาจ eventual อย่าใช้ stale projection ตัดสิน invariant หาก Aggregate replay authoritative stream เพื่อ command หรือมี consistency strategy ชัด

Event Sourcing vs Audit Log

NeedSimpler optionEvent Sourcing
ใครแก้ recordaudit logอาจเกินจำเป็น
current CRUD statetableไม่คุ้มโดย default
rebuild state at any timehardstrong fit
temporal business modelawkwardpotential fit
external event integrationoutboxseparate concern

แบบฝึกปฏิบัติ: Decision Record

ประเมิน Transfer Intent, Payment Execution, Ledger, Customer Profile, Notification:

Temporal/history need:
Alternative (state + audit):
Stream boundary:
Event examples:
Schema/privacy evolution:
Projection/rebuild operations:
Team capability:
Decision / rejected alternative / review trigger:

เลือกอย่างมาก 1 candidate และอธิบายว่าทำไมส่วนอื่นไม่ใช้

รายการตรวจสอบ

  • ES แยกจาก Domain/Integration Event
  • Value hypothesis มี owner/requirement
  • Stream boundary/concurrency ชัด
  • Events เป็น durable domain facts
  • Schema evolution/replay tested
  • Privacy/retention มี authority
  • Projection ไม่ใช้ authoritative decision โดยเงียบ
  • Simpler alternative ถูกเปรียบเทียบ

สรุปบทนี้

Event Sourcing เป็น persistence/model pattern ที่ทรงพลังเมื่อ temporal history/reconstruction เป็น core need แต่มี lifetime operational cost สูง DDD ไม่ได้บังคับใช้ เลือกแคบ ทดลอง replay/evolution และยอมใช้ state+audit เมื่อพอ

อ่านเพิ่มเติม