Naming and identifiers
- Use stable, business-meaningful IDs (
invoice-991,org_42). Avoid database auto-increment integers—they leak implementation details. - Embed shard hints if you plan to distribute aggregates across filesystems:
order:us:10023. - Store identifiers in metadata (
@tenant,@channel) so plugins can route events without parsing payloads.
Lifecycle
Create aggregates explicitly with an initial event:invoice_voided) that mark state without removing history. If you must retire an aggregate, archive it (dbx aggregate archive <type> <id>) or remove only when it has no events (dbx aggregate remove requires version 0).
Metadata conventions
@ prefix for extension metadata. Everything else belongs to your business domain. Consistent metadata enables search, audit, and replication filters. Use namespaced keys (@trace, @tenant) to keep user hints distinct from system metadata.
Anti-patterns to avoid
- God aggregates: packing unrelated concerns (billing + identity + compliance) into one aggregate explodes payload size and causes contention.
- Cross-aggregate transactions: EventDBX is intentionally single-write-path. Model relationships through events (e.g.,
order_paidreferencingpayment_id) and have read models enforce constraints asynchronously. - Mutable fields: never overwrite data in place. Emit a new event (
invoice_amount_adjusted) so the audit trail stays truthful.