Skip to main content

Event Listeners

Key Insight

Event Listeners are all about trade-offs. They're not inherently good or bad—it depends on the context and requirements of your system.

1. Introduction and Key Question​

When should we use Event Listeners, and when should we avoid them? Is there a clear right or wrong, or is it always a trade-off?

2. Event Management in System Architecture​

In modern architectures, especially Microservices and Event-Driven Architecture, several patterns exist for managing events:

Store all changes to application state as a sequence of events.

Impact on Code Quality Metrics​

Why Event Management Matters

As event volume grows, it impacts various aspects of your codebase differently:

🔻 Declining Metrics

  • Code Readability
  • Module Cohesion

🔺 Improving Metrics

  • Decoupling Dependencies
  • System Flexibility
note

In modular or microservice systems where decoupling is crucial, Event Listeners can be particularly valuable.

3. Team Contract for Event Listeners​

Core Principle

Using Event Listeners within a single module is prohibited. They should only be used for communication between separate modules.

Event Listeners as Orchestrators​

Event listeners should focus solely on orchestration responsibilities, not core business logic execution. They should remain as lightweight as possible by:

  • Delegating business logic to dedicated service layers
  • Avoiding complex conditionals or business rules
  • Minimizing synchronous operations and blocking calls
  • Keeping the listener focused on routing and coordination

This approach maintains clear separation of concerns and improves maintainability.

Example Scenario​

Allowed

✅ Allowed: Module A fires an event that Module B listens to

Not Allowed

❌ Not Allowed: Module A directly calls Module B's methods

Why This Matters

Direct module coupling reduces independence and makes the system more rigid. Events create a looser, more maintainable architecture.

4. Implementation Guidelines​

Common Scenarios​

Decision Matrix​

ScenarioStatusImpact
Direct connection between entities of two modules❌ ProhibitedViolates modularity
Directly calling a service from another module⚠️ DiscouragedCauses tight coupling
Firing an event from Module A and listening in Module B✅ AllowedPromotes loose coupling
Best Practice

When in doubt, prefer the event-based approach for inter-module communication.

5. Business Events Standard​

Definition

A Business Event represents a meaningful business occurrence that other parts of the system might be interested in.

Key Characteristics​

  • Future-proofs your architecture
  • Enables loose coupling between modules
  • Makes the system more observable
// Example: Firing a business event
class OrderService {
async completeOrder(orderId) {
// Business logic...
eventBus.publish('order.completed', { orderId, timestamp: Date.now() });
}
}

6. Decision Framework​

When to Use Event Listeners​

✅ Use When:
  • Communicating between independent modules
  • Decoupling is more important than direct coupling
  • Multiple components need to react to an event

When to Avoid Event Listeners​

❌ Avoid When:
  • Communication stays within a single module
  • Direct coupling is simpler and more maintainable
  • You need synchronous communication

7. Final Guidelines​

Key Points
  • Refactor any intra-module event listeners when found
  • Keep inter-module event-based communication
  • Document all business events and their purposes
Remember

Even if there are no current listeners, firing business events for important occurrences helps maintain flexibility for future requirements.