Skip to main content
Events are immutable facts. Each carries a type, payload, metadata, and monotonic position within the aggregate. Treat them like append-only logs rather than mutable rows.

Designing event types

  • Use verbs in past tense (person_registered, person_updated).
  • Keep payloads focused: one event should represent a single business fact.
  • Version types explicitly (invoice_paid.v2) if the meaning changes drastically; otherwise, evolve schemas through optional fields.

Schema evolution

Add optional fields first, then tighten them once you are confident they always appear. Use schemas to encode those rules:
# declare allowed events and snapshot cadence
dbx schema create person --events person_registered,person_updated --snapshot-threshold 50
# add or constrain columns later
dbx schema field person first_name --type text --required
dbx schema field person status --type text
For breaking changes, mint a new event type and deprecate the old one in code; schemas can lock a list of allowed events to enforce the transition.

Metadata for traceability

Include machine-readable routing hints and human context:
{
  "@actor": "svc-invoice",
  "@correlation": "req-8821",
  "@source": "api",
  "@replay": false,
  "region": "us-east-1"
}
Plugins can filter on metadata without parsing payloads, and auditors can answer “who triggered this event?” instantly.

Replaying events

Use events to rebuild read models or repair downstream systems:
dbx events --aggregate person --aggregate-id p-991 --sort version:asc --take 100 --json
dbx plugin replay search person p-991 --payload-mode event-only
When replaying into plugins, set an @replay extension so receivers can differentiate new writes from backfills.

Idempotency

Events are naturally idempotent because they never overwrite prior entries. However, when events trigger external systems (webhooks, API calls), include deterministic identifiers (event_id, aggregate_id+version) so receivers deduplicate deliveries. Well-structured events keep the write path clean and make downstream integrations predictable.