# What About Using Structured Naming for Event-Driven Messaging?

By Jag Reehal, 2024-11-20. Canonical: https://arrangeactassert.com/posts/structured-naming-event-driven/

<!-- Excerpt Start -->

It's a well-known adage that naming things is hard.

In event-driven architectures, a consistent naming convention is essential for scalability, communication, collaboration and maintainability.

At the moment, I'm architecting a new event-driven solution, and I planning to adopt a `Structured Naming` approach for event types.

In this post I'll share my thoughts on this approach and its benefits.

<!-- Excerpt End -->

## Recommended Practice: Embedding Metadata in Event Payloads

It's a widely recommended practice to include metadata directly within the event payload.

This metadata provides essential context about the event, such as its type, domain, and service, in addition to the data payload itself.

```json
{
  "detail": {
    "metadata": {
      "id": "01HXHMF28A94NS7NSHC5GM80F4",
      "version": "1",
      "timestamp": "2020-04-28T07:20:20Z",
      "domain": "order",
      "service": "order-service",
      "type": "order-placed"
    },
    "data": {
      "user_id": "123456",
      "order_id": "1234567890123",
      "restaurant_id": "123456789",
      "currency": "USD",
      "total": "42.42"
    }
  }
}
```

In this example, the `type` field within the metadata specifies the event as `order-placed`.

While this method provides the necessary context, it can lead to challenges in event routing and subscription management, especially if you're using NATS, where wildcards offer flexibility and agility.

For instance, if consumers need to subscribe to all events related to orders, they may have to manage subscriptions manually for each type (`order-placed`, `order-updated`, etc.).

## Why Consider a Structured Naming Approach?

The **Structured Naming** approach organises event names in a structured, dot-separated format. This structure mirrors the natural categorisation of events, enabling intuitive grouping, routing, and filtering by using dots (`.`) as separators.

## Example of Structured Event Naming

Using a structured naming approach, events related to orders could be organised like this:

- `order.created`
- `order.updated`
- `order.deleted`

Here, the prefix `order` denotes the domain or entity, while the suffix (`created`, `updated`, `deleted`) specifies the verb. This structure allows consumers to easily subscribe to domain event types, such as all events under `order.*`.

## Consistency is Key

Keeping naming patterns predictable and consistent is critical to reducing cognitive load and avoiding confusion. For instance:
For instance:

- use a single separator style (`order.created`) and avoid mixing styles like `order-created` and `order_created` in the same system.

- Adhering to a clear and consistent format ensures event names remain instantly recognisable.

## Benefits of the Structured Naming Approach

- ### Improved Clarity

The structured naming convention includes both the event's domain and action, making it easier to understand the purpose and intent of an event at a glance.

- ### Efficient Subscription Management

Consumers can use wildcard subscriptions to receive a broader set of events. For example, subscribing to `order.*` captures all events related to orders, such as `order.created` and `order.updated`.

- ### Scalability

As the system grows, adding new event types within a domain becomes seamless. You can introduce new events like `order.canceled` or `user.profile.updated` without overhauling existing subscription logic.

- ### Sharding Capabilities

A structured naming convention can facilitate sharding by grouping related events with common prefixes (e.g. `order.*` or `user.*`).

This simplifies routing related events to the same shard, improving performance and resource allocation.

## Adopting a Structured Naming Pattern

When adopting a structured naming approach, splitting by domain helps communicate intent and related actions.

- ### Domain or Entity

  Represents the primary category, such as `order`, `user`, or `payment`.

- ### Action or Event Type

  Specifies the exact type of event, like `created`, `updated`, or `deleted`.

## Example of Structured Event Names

- ### User Events

  - `user.registered`
  - `user.logged_in`
  - `user.profile.updated`

- ### Payment Events

  - `payment.initiated`
  - `payment.completed`
  - `payment.failed`

This structure provides a consistent and organised approach to naming events, which should prove especially beneficial as systems scale and require more event types across multiple domains.

## Versioning Strategy

When versioning events, a **Version-First** strategy aligns well with wildcard subscriptions and provides immediate visibility of the version. For instance:

- ### Versioned Event Types

  - `v1.order.created`
  - `v2.order.updated`
  - `v1.user.profile.updated`

This approach allows services to listen to specific versions or broader categories, such as `v2.*`, giving flexibility in routing as schemas evolve.

### Benefits of Version-First Naming

1. **Immediate visibility**: Version information is the first thing you see
2. **Easier filtering**: Systems can quickly filter or route by version without parsing the entire event name
3. **Clearer version transitions**: Makes it easier to identify different versions of the same event type
4. **Consistent with API versioning**: Aligns with common API versioning practices

For example, a service could subscribe to all v1 events across domains with `v1.*` or all v2 order events with `v2.order.*`.

## Use Cases

- ### Microservices Architectures

In a microservices environment, services often respond to events from multiple domains. A structured naming convention allows services to subscribe to broader categories efficiently. For example, subscribing to `user.*`simplifies setup by reducing the need to enumerate all event types.

- ### Event Sourcing

In event-sourced systems, where state is reconstructed from historical events, a structured naming scheme enables systematic grouping and processing of events by category.

## AntiPatterns and Potential Drawbacks of Structured Naming

As with all things, there is a danger of overuse and misuse that could lead to complexity and challenges:

- ### Initial Implementation Effort

  Standardising event names across teams requires upfront planning and governance.

- ### Complexity in Deep Naming Structures

  Overly deep structures (e.g., `order.process.payment.canceled`) can reduce clarity. Keeping structures simple and well-documented avoids this pitfall.

## Conclusion

I think a structured naming convention for events can offer a straightforward, organised approach that enhances clarity, scalability, and efficiency in event-driven systems.

Have you tried this approach? I'd love to hear about anything I've missed or overlooked, as well as any challenges, advantages, or pitfalls you've encountered.