# Event-Driven Architecture: How I Name Events (A Practical Guide With Examples)

By Jag Reehal, 2025-02-24. Canonical: https://arrangeactassert.com/posts/how-i-name-events/

<!-- Excerpt Start -->

Getting event names right in event-driven architecture and Domain-Driven Design (DDD) is essential for clarity, consistency, and scalability. A key decision is using singular or plural terms in event names.

Here's how I approach it, with examples and reasoning to help you make the best choice.

<!-- Excerpt End -->

## 1. Plural for Collections

Example: `v1.payees.created`

When an event relates to a collection of entities, the domain should be plural. This clarifies that the event belongs to a broader category and aligns with DDD aggregate roots.

**Examples**:

- `v1.payees.created` → A new payee was created within the payees aggregate
- `v1.payments.failed` → A payment failure occurred within the payments domain
- `v1.users.registered` → A user was registered in the users domain

## 2. Singular for Processes

Example: `v1.transaction.authorised`

If the event describes a business process, workflow, or single entity, use singular to avoid confusion with collections.

**Examples**:

- `v1.transaction.authorised` → A single transaction was authorised
- `v1.conversion.trade.settled` → A specific trade within a conversion was settled
- `v1.authentication.failed` → A single authentication attempt failed

## 3. Plural for Sub-Entities

Example: `v1.conversion.trades.settled`

When an event relates to sub-entities within a domain, pluralization helps differentiate them from the main domain.

**Examples**:

- `v1.conversion.trades.settled` → Multiple trades within a single conversion were settled
- `v1.order.items.shipped` → Multiple items in an order were shipped
- `v1.invoice.payments.processed` → Multiple payments related to an invoice were processed

## 4. Versioning at the Beginning

Example: `v1.domain.event`

**Best Practice**: Always place the version number at the beginning to make versioning immediately visible and to facilitate version-based routing and filtering.

🚫 **Bad Example**: `payments.failed.v1`  
✅ **Good Example**: `v1.payments.failed`

### Why Version First?

Placing the version at the beginning offers several advantages:

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

## Additional Guidelines

**Aggregate Naming in DDD**:  
Aggregates in DDD are typically singular (e.g., Order), but event topics use plural names (e.g., `v1.payments.failed`).

**Clarity vs. Rigidity**:  
Conventions should adapt to domain needs. For example: `v1.conversions.trade.settled` might be valid for process collections.

**Event Payload Context**:  
Plurality in event names doesn't dictate entity count. `v1.payments.failed` could reference a single payment failure.

## Recap

- **Plural for collections**: `v1.payees.created`, `v1.payments.failed`
- **Singular for processes**: `v1.transaction.authorised`, `v1.conversion.trade.settled`
- **Plural for sub-entities**: `v1.conversion.trades.settled`, `v1.order.items.shipped`
- **Version at the beginning**: `v1.domain.event`

Following these naming conventions will make your event-driven architecture structured, scalable, and aligned with domain modelling principles.