Event Naming
Causet event names are stable, public contracts. Naming them well from the start avoids breaking changes later.
Format: SCREAMING_SNAKE_CASE
All event names use SCREAMING_SNAKE_CASE:
ARTIST_FOLLOWED
TICKET_PURCHASED
SHOW_ANNOUNCED
CONCERT_ATTENDEDLowercase, camelCase, or hyphenated names are not supported and will be rejected by the compiler.
Past Tense
Events describe facts that have already occurred. Use the past tense:
| Good | Bad |
|---|---|
ARTIST_FOLLOWED | FOLLOW_ARTIST |
TICKET_PURCHASED | PURCHASE_TICKET |
SHOW_ANNOUNCED | ANNOUNCE_SHOW |
STOCK_RESERVED | RESERVE_STOCK |
USER_REGISTERED | REGISTER_USER |
ORDER_FULFILLED | FULFILL_ORDER |
Commands belong in action names. Events belong in the past.
Domain Scoping
Prefix events with their domain when the name would otherwise be ambiguous:
# Ambiguous — "attended" what?
events:
ATTENDED:
state: user
...
# Clear — domain-scoped
events:
CONCERT_ATTENDED:
state: user
...For applications with multiple entity types that share similar concepts:
events:
ARTIST_SHOW_ANNOUNCED: # artist's perspective
state: artist
...
VENUE_SHOW_SCHEDULED: # venue's perspective
state: venue
...Examples by Domain
Concert app
events:
ARTIST_FOLLOWED: {}
ARTIST_UNFOLLOWED: {}
SHOW_ANNOUNCED: {}
SHOW_CANCELLED: {}
TICKET_PURCHASED: {}
TICKET_REFUNDED: {}
CONCERT_ATTENDED: {}
SETLIST_PUBLISHED: {}E-commerce
events:
PRODUCT_LISTED: {}
PRODUCT_DELISTED: {}
CART_ITEM_ADDED: {}
CART_ITEM_REMOVED: {}
ORDER_PLACED: {}
ORDER_FULFILLED: {}
ORDER_CANCELLED: {}
PAYMENT_CAPTURED: {}
REFUND_ISSUED: {}Fintech
events:
ACCOUNT_OPENED: {}
DEPOSIT_RECEIVED: {}
WITHDRAWAL_INITIATED: {}
TRANSFER_COMPLETED: {}
ACCOUNT_FROZEN: {}
KYC_VERIFIED: {}Stability: Event Names Are Contracts
Once an event is deployed and used in production, its name is a stable contract:
- Ledger entries reference the event type by name.
- Projections subscribe to events by name (
source_events: [ARTIST_FOLLOWED]). - Listeners and sagas trigger on events by name.
- SDK clients may reference event types by name.
Renaming an event is a breaking change. Existing ledger entries still reference the old name. Projections subscribed to the old name will stop firing.
If you need to rename an event, use the versioning pattern instead:
# Keep old event for backward compatibility
events:
TICKET_PURCHASED: { ... } # deprecated — emit TICKET_PURCHASED_V2 instead
TICKET_PURCHASED_V2: { ... } # new name with updated payloadWhen to Version vs Rename
| Change | Strategy |
|---|---|
| Adding an optional payload field | Safe — add it, no version bump needed |
| Removing a payload field | Breaking — add _V2 event without the field |
| Renaming a payload field | Breaking — add _V2 event with the new name |
| Changing a field type | Breaking — add _V2 event with the new type |
| Renaming the event itself | Breaking — add new event name, deprecate old |
See Event Versioning for the full strategy.
System Events Naming
Internal operational events use a consistent prefix:
PROJECTION_FAILED
REPLAY_STARTED
REPLAY_COMPLETED
HANDLER_RETRIEDThese use the same SCREAMING_SNAKE_CASE convention, past tense, and are typically kind: system in the DSL.
Related Pages
- Defining Events — full event DSL syntax
- Event Versioning — how to evolve events safely
- Event Metadata — reserved fields