What’s in an (event) name?

J.D. Carlston  |  07 January 2022

When Juliet asked Romeo “What’s in a Name?” she was trying to wish away family history—the inheritance, customs, and all the feuding baggage that came with being a Capulet. A name is an arbitrary, agreed-upon label, but it often points to a lineage of events.

To Juliet's credit, being able to let go of systemic baggage allows us to build a new future (and new software without the cruft of the old). But, just as she and Romeo learned, the conventions underpinning two different domains may mean they can't function together without additional work being done. Context is still king.

So, if cooler heads reign when talking about the state of events, what's to be done to help systems evolve and adapt to change? How do we build scalable, interoperable event-driven systems? How do we keep inertia and the cost of change down?

A common syntax between systems and events and behaviors becomes necessary. In this, the Semantic Web can help. And thus the CNCF CloudEvent spec was born. This relatively simple standard goes a long way toward facilitating event conversations between systems. Using open standards can help you scale.

------------------ Message -------------------
Concept Name: identity.user.domain-events
------------------- key ----------------------
Key: 17cce427-2027-4b54-9149-626df8109d00
------------------ headers -------------------
content-type: application/cloudevents+json; charset=UTF-8
------------------- value --------------------
 "specversion" : "1.0",
 "type" : "usersignedin",
 "source" : "identity.user",
 "id" : "b65d1b31-1f46-4fbe-a7b4-e93f8c96a449", //event uuid
 "time" : "2018-04-05T03:56:24Z",
 "datacontenttype" : "application/json",
 “subject” : “17cce427-2027-4b54-9149-626df8109d00”, //source key
 “traceparent”: “60080489-f508-4dfd-a96a-62cb8a382689”, //correlation key
 "data" : {
  ... serialized JSON text ...

CNCF Structured Content Mode Example

For systems to interact they must have a shared language, roles, and conventions that allow them to work together (sidenote: this is the basis of “culture” in any system). Some conventions make eventing easier and less costly.

Eventing conventions

  • Events reflect foundational facts about a system or its parts
  • Events are units of notable change within the lifecycle of their parent
  • Events are bounded in time—are past-tense and include an element or period of time (e.g. Time or StartedAt and EndedAt)
  • Events are atomic, immutable, and orderly
  • Events have publishers and consumers as well as some kind of routing mechanism

When building new systems, we often act as well-meaning Juliets trying to share information across systems and break down old and unknown conventions to do so. Sometimes we get things mixed up. We’re human. It happens. We can iterate into being better.

Are you trying to wish away conventions or mutate definitions? Immutability is important—if you’re tempted to edit a past event, you’re likely doing it wrong, and now may be a good time to rethink your system design.

What should be included in an event? Atomicity helps us understand what does and doesn’t belong. Don’t include events inside events—define a new aggregate or entity instead. This can be helpful when modeling or modifying your system.

Events must be accurately ordered in time by the publishing system—make sure the clocks are synchronized and logging correctly. Make sure you can sort, partition, index, and filter. In the systems I work on we’ve standardized around ids, keys, time and date names, and formats.

Events are different from commands. In computing, if they haven't happened yet they aren't an event. People often confuse commands with events or event messages. Models can become conflated. Event-driven isn’t the same thing as event-sourced. Conflation contributes to unclear responsibilities, looping, or even deadlocked systems over time.

As you build, it’s important to document the conventions and constraints. Logic can be automated with certain assumptions taken as truth over time.

Points of interest

These could potentially help you build out your logical base:

  • Track and correlate information both inside and across domains
    • You can use CNCF extensions like traceparent for distributed tracing
    • You can use IDs or keys to build relational sets
  • Use events to understand behavior, telemetry, or state
  • Events can store state, but they don’t have to—they can be stateless or stateful. Knowing when and why (e.g. read or write models; compaction or notification sets) can help you design better systems
  • Events can be logged or ephemeral. Having conventions that determine when and where can help you adapt to changing requirements
  • Events are units of flow. Little’s Law applies to them. You can build metrics and measure aspects of fitness through their aggregation

Since events express key pieces of a lifecycle this is something that can help you understand and code your domain.

Here’s an example of events and commands for a Meeting entity in the Meetings domain. Notice how some events are aggregated into a single domain event.

DOMAIN	                Meetings
EXTERNAL COMMAND	GetScheduledMeetings()
EXTERNAL COMMAND	ScheduleMeeting(Type, DateTime, Users)
INTERNAL COMMAND 	AddUsersToScheduledMeeting(ID, Users)
DOMAIN EVENT 		MeetingScheduled
EXTERNAL COMMAND 	AddUsersToMeeting(ID, Users)
INTERNAL EVENT 		UsersAddedToMeeting
DOMAIN EVENT 		MeetingAdjusted
INTERNAL EVENT 		DailyMeetingsJobRan
DOMAIN EVENT 		MeetingOccurred
INTERNAL COMMAND	GetTodaysMeetings()
INTERNAL EVENT 		DailyMeetingsReportRan
DOMAIN EVENT		MeetingsCompacted
DOMAIN EVENT		MeetingTombstoned

Your system of record might only capture and publish the DOMAIN EVENTS in the example above. Like zooming in on a map, the frame, or level of abstraction, matters for what messages you choose to publish to your consumers.

As your system becomes more complex, structural evolution (of which versioning is part) of the domain may become important to record in your event store. For that to happen, these changes must be included in the lifecycle record. Like genetic code, adaptation may need to be codified and observed to be propagated in a complex system.

SYSTEM COMMAND		RegisterDomain(Meetings)
SYSTEM EVENT		system.DomainRegistered
SYSTEM COMMAND		AddTopic(Meetings, root, v1.0) 
SYSTEM EVENT		system.TopicAdded
SYSTEM EVENT		system.TopicSchemaRegistered
DOMAIN			Meetings
EXTERNAL COMMAND	GetScheduledMeetings()
EXTERNAL COMMAND	ScheduleMeeting(Type, DateTime, Users)
DOMAIN EVENT 		root.MeetingScheduled
EXTERNAL COMMAND 	AddUsersToMeeting(ID, Users)
INTERNAL EVENT 		UsersAddedToMeeting
DOMAIN EVENT 		root.MeetingAdjusted
INTERNAL EVENT 		DailyMeetingsJobRan
DOMAIN EVENT 		root.MeetingOccurred
INTERNAL COMMAND	GetTodaysMeetings()
INTERNAL EVENT 		DailyMeetingsReportRan
DOMAIN EVENT		root.DailyMeetingsCompacted
DOMAIN EVENT		root.MeetingTombstoned
SYSTEM COMMAND		VersionTopic(Meetings, root, v2.0)
SYSTEM EVENT		system.TopicRegistered
SYSTEM EVENT		system.TopicSchemaRegistered
SYSTEM EVENT		system.TopicVersioned

Make sure your lifecycle works on paper. You can mock up the stories you want to tell. If your mockup covers all of your use cases or BDD scenarios for your MVP you’ve got a hella good start on your system.

Sometimes events carry state and relations. Sometimes they don’t. They can act an awful lot like Montagues and Capulets. Work to understand the roles and teams that own entities. Find overlap and areas where conventions or standards might help the business communicate. Be aware of relational dependencies. Try not to act as a pass-through for data that is owned by other teams' models. It makes change difficult later on.

Naming conventions

  • Event names are human-readable and follow a SubjectObjectPredicate format
    • Events must contain a reference to at least one subject —an aggregate, an entity, or a domain
  • Topics are nominal phrases or concepts that describe and categorize streams of events
  • Events map to system-readable operations (functions or transactions)
  • Events are grouped in a traversable domain or entity based on function or type
  • Strong naming conventions help you automate systems and scale more easily over time
    • Make your Domain Events more descriptive: events with Created, Updated, Deleted are generally lower than the domain level

In order to integrate, to communicate and to interoperate events must convey a shared set of meaning within both human and automated systems. Name your events carefully and well. Build systems that can adapt and evolve with a reasonable amount of shared intention. Communicate regularly with your consumers.

Evolutionary conventions

  • Systems that allow small, incremental changes are easier to evolve
  • Attributes inside events are part of the default config of an entity or domain
    • Attributes can be built, assigned, and retired using evolutionary patterns in a system designed to handle them
    • Changes to the structure of schemas or metadata are part of an evolutionary system
  • Domain, Topic, and schema registries can help your teams discover important events
  • Mutation & Versioning around breaking changes can be automated or semi-automated with evolutionary design patterns
  • Build systems where events and entities can evolve and change depending on business requirements
  • Include FULL lifecycles—make ways to retire and tombstone systems, entities, and events

We build stories with events; we use them to semantically and syntactically plot, build, communicate, and collaborate.

Take some lessons from Shakespeare’s tragedy. You can create common language and conventions that allow you to inform people about systemic or breaking change. This can help keep the cost of change down. Seek awareness, use descriptive naming standards, register schemas, and share practices around persistent events.

Additional Resources

Photo of J.D. Carlston

J.D. Carlston I am passionate about technology and enjoy leading teams across the business and non-profit sectors into unexplored territory. I’m always excited to create and learn from engineering projects. I love trying to build and break systems and currently work on a software architecture team whose mission is to democratize tech skills for humankind. Additionally, I volunteer in a number of charitable organizations that promote learning and scientific innovation. I also love writing, making art, and collaborating with friends and family in the beautiful outdoors around the world. You can reach me at @jdcarlston on Twitter.