EventsEvent Naming

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_ATTENDED

Lowercase, 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:

GoodBad
ARTIST_FOLLOWEDFOLLOW_ARTIST
TICKET_PURCHASEDPURCHASE_TICKET
SHOW_ANNOUNCEDANNOUNCE_SHOW
STOCK_RESERVEDRESERVE_STOCK
USER_REGISTEREDREGISTER_USER
ORDER_FULFILLEDFULFILL_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 payload

When to Version vs Rename

ChangeStrategy
Adding an optional payload fieldSafe — add it, no version bump needed
Removing a payload fieldBreaking — add _V2 event without the field
Renaming a payload fieldBreaking — add _V2 event with the new name
Changing a field typeBreaking — add _V2 event with the new type
Renaming the event itselfBreaking — 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_RETRIED

These use the same SCREAMING_SNAKE_CASE convention, past tense, and are typically kind: system in the DSL.