Skip to main content

Pitfalls checklist (print this)

This is the “you’ll thank yourself later” list.

Event design

  • Events are facts (past tense), not requests.
  • You can explain each event to a non-technical domain expert.
  • Events do not include infrastructure concerns (broker details, DB ids).
  • You have a clear event versioning strategy (new types vs upcasters).

Aggregate correctness

  • All invariants are enforced inside the aggregate.
  • Apply(...) methods are deterministic and side-effect free.
  • You never mutate aggregate state without raising an event.

Concurrency

  • All appends use expected stream version.
  • You have a clear retry policy for concurrency conflicts.
  • Commands are idempotent (command id / dedupe) where needed.

Projections

  • Projections are idempotent (checkpointing per stream or global position).
  • You can rebuild projections from scratch.
  • You measure projection lag.
  • You have a poison-event strategy (bad schema, unexpected type).

Integration

  • You don’t publish domain events “as-is” to other services.
  • You use outbox (or equivalent) to avoid write/publish inconsistency.
  • Consumers are idempotent (dedupe keys, exactly-once assumptions avoided).

Operations

  • You can run mixed versions safely (new readers handle old events).
  • You have a documented rebuild/cutover procedure for read models.
  • You log correlation/causation ids.
  • You’ve considered privacy/security implications (PII, encryption, retention).

If you want one guiding principle

Treat events like public APIs you can never revoke.