Event-Driven vs Message-Based: The Misunderstanding That Breaks Systems

Event-Driven vs Message-Based: The Misunderstanding That Breaks Systems

Many systems today use asynchronous communication, but not every async system is event-driven. This misunderstanding leads to tightly coupled architectures, duplicate processing bugs, and systems that are harder to evolve than the monoliths they replaced.

Let’s break this down properly.


The Root of the Confusion

At a glance, both approaches look similar:

  • Messages are sent
  • Consumers receive them
  • Work happens asynchronously

So teams assume:

“Event-driven = messaging system”

But that’s where things go wrong.


Event-Driven Architecture (EDA)

An event is a fact:

“Something already happened.”

Examples:

  • UserRegistered
  • OrderPlaced
  • PaymentCompleted

Key characteristics:

  • Events represent state changes
  • Producers don’t care who consumes them
  • Messages are immutable
  • Multiple consumers can react independently
  • Events can be replayed

👉 Think of it as broadcasting history


Message-Based Communication

A message is usually a command:

“Please do this.”

Examples:

  • SendEmail
  • GenerateInvoice
  • ProcessPayment

Key characteristics:

  • Often point-to-point
  • Consumer is expected to handle the task
  • Message is removed after consumption
  • Typically used with queues

👉 Think of it as delegating work


The Core Difference

Article content

Real-World Example (From My Experience)

I built a Notification Service using:

  • Kafka (event streaming)
  • Redis (idempotency)
  • PostgreSQL (storage)
  • Firebase / Azure Communication Services

Event-Driven Flow

User Service → publishes → UserRegistered event
                    ↓
            Kafka Topic (user-events)
                    ↓
        Notification Service consumes
                    ↓
      Sends Email / Push Notification        

Here:

  • The producer doesn’t know about notifications
  • Multiple services can consume the same event
  • We can replay events if needed

👉 This is true event-driven architecture


Message-Based Flow (Common Mistake)

User Service → sends → SendWelcomeEmail message
                    ↓
               Queue
                    ↓
        Notification Service consumes
                    ↓
              Sends Email        

Here:

  • The producer knows exactly what should happen
  • This is not event-driven
  • This is task delegation

👉 This is messaging — not EDA


The Dangerous Misuse

“Using Kafka like a Queue”

This happens when teams:

  • Publish commands instead of events
  • Have only one consumer group
  • Delete or ignore history
  • Treat topics like work queues

Example:

Kafka Topic: send-email
Message: SendEmail(userId)        

This is just a queue with extra complexity.

👉 You lose:

  • Replay capability
  • Decoupling
  • Flexibility


When to Use Each

Use Event-Driven When:

  • You want multiple systems to react independently
  • You need audit logs or history
  • You want loose coupling
  • You expect future consumers

Use cases:

  • Auditing
  • Data synchronization
  • Analytics pipelines
  • Notifications (triggered by events)


Use Message-Based When:

  • You need guaranteed processing of a task
  • There is one clear consumer
  • You want simple task execution

Use cases:

  • Sending emails (as a direct task)
  • Image processing
  • Payment execution
  • Background jobs


Idempotency: The Hidden Requirement

In event-driven systems, duplicate processing WILL happen.

Why?

  • At-least-once delivery
  • Retries
  • Consumer failures

Solution:

👉 Use idempotency

Example approach:

  • Store processed event IDs in Redis
  • Ignore duplicates

if (redis.exists(eventId)) return;
process();
redis.set(eventId);        

Without this:

  • Duplicate emails
  • Double charges
  • Inconsistent data


Key Insight

Event-driven is about facts. Messaging is about actions.

If your system is saying:

  • “Do this” → Messaging
  • “This happened” → Event-driven


✍️ Written by Janith Ranasinghe—a software engineer passionate about learning, documenting, and sharing knowledge about backend design and system architecture.


To view or add a comment, sign in

More articles by Janith Ranasinghe

Others also viewed

Explore content categories