Skip to content

NestJS Event Patterns

Event patterns publish notifications without waiting for a response—ideal for "order created" style domain events. This lesson covers @EventPattern and emit().

Fire-and-Forget Events

Producers call client.emit('user.created', payload). Consumers decorate handlers with @EventPattern('user.created'). Emitters do not receive handler return values; design consumers to be idempotent.

@EventPattern('order.created')
handleOrderCreated(data: { orderId: string }) {
  return this.notificationsService.sendOrderEmail(data.orderId);
}

Even though the method can return a Promise, the producer that emitted the event will not await that work as an RPC response.

Emitting Events

this.client.emit('order.created', { orderId: order.id });
  • Use events for side effects: emails, analytics, cache invalidation, projections.
  • Do not use events when the caller must get a calculated result—use message patterns instead.
  • Include enough data in the payload for consumers to act without synchronous callbacks.
  • Name events in past tense (order.created) to signal facts that already happened.

Event Pattern Cheatsheet

Emit vs send at a glance.

Need Use
Need a response send + @MessagePattern
Notify others emit + @EventPattern
Fan-out to many consumers Pub/sub capable transporter + events
Idempotent handling Dedupe by event id / aggregate version

At-Least-Once Delivery

Most brokers deliver at least once. Consumers must tolerate duplicates (check processed event ids) or make operations safely re-runnable.

Event Payload Design

Prefer carrying the data consumers need, or a stable id plus a way to fetch details. Avoid huge payloads that blow broker message limits.

Common Mistakes

  • Expecting emit() to return handler results.
  • Building workflows that break if an event is processed twice.
  • Using vague event names like update without a clear subject.
  • Doing critical transactional work only in an async event after committing inconsistently.

Key Takeaways

  • @EventPattern handles fire-and-forget events.
  • emit() publishes without waiting for a reply.
  • Design idempotent consumers for duplicate delivery.
  • Name events as past-tense domain facts.

Pro Tip

Include a unique eventId and occurredAt in every event payload from day one—observability and dedupe both get easier later.