← Back to Articles         
Event-Driven Architecture

Event-Driven Architecture

Published on 29 Sep 2026     18 min read Microservices
Messaging & Event-Driven

Event-Driven Architecture (EDA) in Microservices

1. What is Event-Driven Architecture?

Event-Driven Architecture (EDA) is an architectural style where different parts of a system communicate and react based on events.

An event represents something that has already happened in the system.

Examples:

OrderCreated
PaymentCompleted
PaymentFailed
InventoryReserved
OrderCancelled
CustomerRegistered
OrderShipped

For example, when an order is created:

Order Service
      │
      │ Publishes
      ▼
  OrderCreated
      │
      ▼
┌─────────────────────┐
│   Message Broker    │
│ Azure Service Bus   │
│ RabbitMQ / Kafka    │
└──────────┬──────────┘
           │
     ┌─────┼─────────────┐
     ▼     ▼             ▼
 Inventory  Notification  Analytics
 Service       Service      Service

The Order Service does not directly call all these services. It announces:

OrderCreated

Other services interested in that event react independently.


2. Simple Definition

Event-Driven Architecture is an architecture where services publish events when something happens, and other services subscribe to those events and perform their own actions.

The basic idea is:

Something happens
       ↓
Event is produced
       ↓
Event is published
       ↓
Interested services receive it
       ↓
Each service reacts independently

3. What is an Event?

An event is a record of a fact that has already occurred.

For example:

OrderCreated

means:

An order has already been created.

Similarly:

PaymentCompleted

means:

The payment has already completed.

An event should normally be expressed in past tense because it describes something that happened.

Good examples:

CustomerRegistered
OrderCreated
PaymentCompleted
InventoryReserved
OrderShipped

Less appropriate event names:

CreateOrder
ProcessPayment
ReserveInventory

Those represent commands, not events.


4. Event vs Command

This is an important interview distinction.

Command

A command says:

Do something.

Examples:

ProcessPayment
ReserveInventory
SendEmail
CreateInvoice

Event

An event says:

Something happened.

Examples:

PaymentCompleted
InventoryReserved
EmailSent
InvoiceCreated
Command Event
Requests an action Announces a fact
ProcessPayment PaymentCompleted
CreateOrder OrderCreated
CancelOrder OrderCancelled
Usually has an intended handler Can have many subscribers
Can potentially be rejected Represents something that occurred

5. Why Do We Need Event-Driven Architecture?

Consider an e-commerce application.

When an order is created, we may need to:

1. Reserve inventory
2. Send confirmation email
3. Update analytics
4. Add loyalty points
5. Create audit record
6. Notify warehouse

Without EDA, the Order Service might directly call every service:

                 ┌──HTTP──> Inventory Service
                 │
                 ├──HTTP──> Email Service
Order Service ───┼──HTTP──> Analytics Service
                 │
                 ├──HTTP──> Loyalty Service
                 │
                 └──HTTP──> Warehouse Service

This creates considerable runtime coupling.

The Order Service needs knowledge of multiple downstream services and must deal with their failures, latency, retry behavior, and API contracts.


6. With Event-Driven Architecture

Instead, the Order Service publishes:

OrderCreated

Architecture:

                       OrderCreated
                            │
                            ▼
                     ┌─────────────┐
                     │   Broker    │
                     └──────┬──────┘
                            │
           ┌────────────────┼─────────────────┐
           │                │                 │
           ▼                ▼                 ▼
      Inventory        Notification       Analytics
       Service            Service          Service
           │
           ├───────────────┐
           │               │
           ▼               ▼
       Loyalty          Warehouse
       Service           Service

The producer only needs to publish the event according to the agreed contract.

This provides loose coupling between services.


7. Purpose of Event-Driven Architecture

EDA is primarily used to build systems that are:

  • Loosely coupled
  • Scalable
  • Responsive
  • Asynchronous
  • Extensible
  • Resilient to temporary consumer failures
  • Suitable for distributed systems
  • Suitable for microservices

It is particularly useful when one business action should trigger multiple independent activities.


8. Main Components of EDA

A typical Event-Driven Architecture contains:

Event Producer
      ↓
    Event
      ↓
Event Broker
      ↓
Event Consumer

Let's examine them individually.


9. Event Producer

The Event Producer is the service where something happens.

Example:

Order Service

An order is successfully created.

The service publishes:

OrderCreated

Example event:

{
    "eventId": "e7c52e7b-6c90-4d7a",
    "eventType": "OrderCreated",
    "occurredAt": "2026-09-29T07:30:00Z",
    "orderId": 1001,
    "customerId": 501,
    "totalAmount": 2500
}

10. Event Broker

The event broker transports/distributes events between producers and consumers.

Common technologies include:

Technology Common use
Azure Service Bus Managed enterprise messaging on Azure
RabbitMQ Message queues and routing
Apache Kafka High-throughput event streaming
AWS SNS/SQS AWS messaging
Google Pub/Sub Google Cloud event messaging

For example:

Order Service
      ↓
OrderCreated
      ↓
Azure Service Bus

11. Event Consumer

A consumer subscribes to an event and reacts when it receives it.

For example:

OrderCreated
     │
     ├──> Inventory Service
     │       ↓
     │    Reserve stock
     │
     ├──> Notification Service
     │       ↓
     │    Send email
     │
     └──> Analytics Service
             ↓
          Record sale

Each consumer owns its business logic.


12. How Does Event-Driven Architecture Work?

Consider a customer placing an order.

Step 1 — Customer creates an order

Customer
   ↓
POST /api/orders
   ↓
Order Service

Step 2 — Order Service stores the order

Order Service
     ↓
Order Database

OrderId = 1001
Status = Created

Step 3 — Publish event

After the order is created:

OrderCreated

is published.

Step 4 — Broker distributes it

Order Service
      ↓
OrderCreated
      ↓
Message Broker

Step 5 — Subscribers receive it

Message Broker
      │
      ├──> Inventory Service
      ├──> Notification Service
      └──> Analytics Service

Step 6 — Consumers react

Inventory Service
      ↓
Reserve inventory

Notification Service
      ↓
Send confirmation

Analytics Service
      ↓
Record order statistics

These operations can happen independently.


13. Complete Example Flow

Imagine this business process:

Customer
   │
   ▼
Order Service
   │
   │ OrderCreated
   ▼
Message Broker
   │
   ▼
Inventory Service
   │
   │ InventoryReserved
   ▼
Message Broker
   │
   ▼
Payment Service
   │
   │ PaymentCompleted
   ▼
Message Broker
   │
   ├───────────────┐
   ▼               ▼
Shipping       Notification
Service           Service
   │
   │ OrderShipped
   ▼
Message Broker

Notice something important:

There is no single long synchronous HTTP chain such as:

Order
 ↓
Inventory
 ↓
Payment
 ↓
Shipping
 ↓
Notification

Instead, business events move the workflow forward.


14. Event-Driven Architecture vs Message-Based Communication

These terms are related but not identical.

Message-Based Communication

This is primarily a communication mechanism.

Producer
   ↓
Message
   ↓
Broker
   ↓
Consumer

Messages can be:

Commands
Events
Work items
Notifications

Event-Driven Architecture

EDA is an architectural style where events represent state changes/business facts and drive reactions throughout the system.

OrderCreated
      ↓
Consumers react
      ↓
New events
      ↓
Other consumers react

Therefore:

EDA commonly uses message-based communication, but not every message-based system is an Event-Driven Architecture.


15. Simple ASP.NET Core Example

Let's implement:

Order API
   ↓
OrderCreated
   ↓
Azure Service Bus
   ↓
Notification Service

Required NuGet Package

Install:

dotnet add package Azure.Messaging.ServiceBus

Package:

Azure.Messaging.ServiceBus

16. Event Model

public class OrderCreatedEvent
{
    public Guid EventId { get; set; }

    public int OrderId { get; set; }

    public int CustomerId { get; set; }

    public decimal TotalAmount { get; set; }

    public DateTime OccurredAt { get; set; }
}

Notice the class name:

OrderCreatedEvent

rather than:

CreateOrderEvent

because the event represents something that already happened.


17. appsettings.json

{
  "AzureServiceBus": {
    "ConnectionString": "<your-service-bus-connection-string>",
    "TopicName": "orders"
  }
}

In production, avoid committing credentials into appsettings.json.

Common alternatives are:

Managed Identity
Azure Key Vault
Environment Variables

18. Event Publisher Interface

public interface IEventPublisher
{
    Task PublishAsync<T>(T eventData);
}

This keeps the business code independent from the specific publisher implementation.


19. Azure Service Bus Publisher

using Azure.Messaging.ServiceBus;
using System.Text.Json;

public class AzureServiceBusEventPublisher : IEventPublisher
{
    private readonly ServiceBusClient _client;
    private readonly IConfiguration _configuration;

    public AzureServiceBusEventPublisher(
        ServiceBusClient client,
        IConfiguration configuration)
    {
        _client = client;
        _configuration = configuration;
    }

    public async Task PublishAsync<T>(T eventData)
    {
        string topicName =
            _configuration["AzureServiceBus:TopicName"]!;

        ServiceBusSender sender =
            _client.CreateSender(topicName);

        string json =
            JsonSerializer.Serialize(eventData);

        var message =
            new ServiceBusMessage(json);

        message.Subject =
            typeof(T).Name;

        await sender.SendMessageAsync(message);
    }
}

20. Program.cs

using Azure.Messaging.ServiceBus;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

string connectionString =
    builder.Configuration[
        "AzureServiceBus:ConnectionString"]!;

builder.Services.AddSingleton(
    new ServiceBusClient(connectionString));

builder.Services.AddScoped<
    IEventPublisher,
    AzureServiceBusEventPublisher>();

var app = builder.Build();

app.MapControllers();

app.Run();

ASP.NET Core DI will automatically inject:

IEventPublisher

where required.


21. OrdersController

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IEventPublisher _publisher;

    public OrdersController(
        IEventPublisher publisher)
    {
        _publisher = publisher;
    }

    [HttpPost]
    public async Task<IActionResult> CreateOrder()
    {
        // Normally save the order into database.

        int orderId = 1001;

        var orderCreatedEvent =
            new OrderCreatedEvent
            {
                EventId = Guid.NewGuid(),
                OrderId = orderId,
                CustomerId = 501,
                TotalAmount = 2500,
                OccurredAt = DateTime.UtcNow
            };

        await _publisher.PublishAsync(
            orderCreatedEvent);

        return Ok(new
        {
            OrderId = orderId,
            Message = "Order created"
        });
    }
}

Flow:

POST /api/orders
      ↓
OrdersController
      ↓
Create Order
      ↓
OrderCreatedEvent
      ↓
IEventPublisher
      ↓
Azure Service Bus

22. Consumer Microservice

Now suppose the Notification Service subscribes to the event.

It can run a BackgroundService.

using Azure.Messaging.ServiceBus;

public class OrderCreatedConsumer
    : BackgroundService
{
    private readonly ServiceBusClient _client;

    public OrderCreatedConsumer(
        ServiceBusClient client)
    {
        _client = client;
    }

    protected override async Task ExecuteAsync(
        CancellationToken stoppingToken)
    {
        ServiceBusProcessor processor =
            _client.CreateProcessor(
                "orders",
                "notification-service");

        processor.ProcessMessageAsync +=
            ProcessMessage;

        processor.ProcessErrorAsync +=
            ProcessError;

        await processor.StartProcessingAsync(
            stoppingToken);

        await Task.Delay(
            Timeout.Infinite,
            stoppingToken);
    }

    private async Task ProcessMessage(
        ProcessMessageEventArgs args)
    {
        string json =
            args.Message.Body.ToString();

        Console.WriteLine(
            $"Order event received: {json}");

        // Send confirmation email here.

        await args.CompleteMessageAsync(
            args.Message);
    }

    private Task ProcessError(
        ProcessErrorEventArgs args)
    {
        Console.WriteLine(
            args.Exception.Message);

        return Task.CompletedTask;
    }
}

Register:

builder.Services.AddHostedService<
    OrderCreatedConsumer>();

23. Why Use a Topic Here?

Suppose three services require OrderCreated:

Order Service
     ↓
OrderCreated
     ↓
orders topic
     │
     ├──> inventory-service subscription
     │
     ├──> notification-service subscription
     │
     └──> analytics-service subscription

Each subscription receives the event independently.

This is different from putting several competing consumers on one queue, where a given message would normally be processed by only one consumer instance from that queue.


24. Event Chaining

EDA becomes especially useful when one event causes another event.

Example:

OrderCreated
      ↓
Inventory Service
      ↓
InventoryReserved
      ↓
Payment Service
      ↓
PaymentCompleted
      ↓
Shipping Service
      ↓
OrderShipped
      ↓
Notification Service

This can implement complex distributed business workflows.

However, it introduces an important design question:

Who controls the overall workflow?

That leads to Saga patterns.


25. Event Choreography

In choreography, there is no central coordinator.

Services react to events.

Order Service
     │
     │ OrderCreated
     ▼
Inventory Service
     │
     │ InventoryReserved
     ▼
Payment Service
     │
     │ PaymentCompleted
     ▼
Shipping Service

Each service knows which events it consumes and what events it publishes.

Advantage

Low central coupling.

Disadvantage

Large workflows can become difficult to understand, debug, and govern.


26. Event Orchestration

With orchestration, a central workflow component coordinates the process.

             ┌─────────────────┐
             │ Saga            │
             │ Orchestrator    │
             └────────┬────────┘
                      │
          ┌───────────┼────────────┐
          ▼           ▼            ▼
      Inventory    Payment      Shipping
       Service     Service       Service

The orchestrator decides:

Reserve Inventory
       ↓
Process Payment
       ↓
Create Shipment

If something fails, it can initiate compensating actions.


27. Choreography vs Orchestration

Choreography Orchestration
Event-driven reactions Central coordinator
No central workflow owner Explicit workflow owner
Lower central coupling More centralized control
Good for simpler event flows Useful for complex workflows
Can become hard to trace Workflow easier to visualize
Services react to events Orchestrator directs steps

Both approaches are used in real systems.


28. Eventual Consistency

EDA often uses eventual consistency.

Suppose:

12:00:00.000
Order created

12:00:00.100
OrderCreated published

12:00:00.300
Inventory updated

12:00:00.600
Analytics updated

For a short period:

Order DB       = Updated
Inventory DB   = Not yet updated
Analytics DB   = Not yet updated

Eventually:

Order DB       = Updated
Inventory DB   = Updated
Analytics DB   = Updated

This is normal in many asynchronous distributed systems.


29. Why Not Use Distributed Database Transactions?

Suppose:

Order Service     → Order DB
Inventory Service → Inventory DB
Payment Service   → Payment DB

Trying to maintain one ACID transaction across independent microservices creates substantial coupling and operational complexity.

Instead, microservice architectures commonly use:

Local transactions
        +
Events
        +
Eventual consistency
        +
Saga/compensation where necessary

30. Transactional Outbox Pattern

This is one of the most important production patterns related to EDA.

Consider:

await SaveOrder();

await PublishEvent();

Problem:

Save Order
   ↓
SUCCESS

Publish OrderCreated
   ↓
FAILURE

Now:

Database says:
Order exists

Broker says:
No OrderCreated event

Consumers never learn about the order.


Solution — Outbox

Store both the business change and the event record in the same local database transaction.

Order Service
      │
      ▼
┌────────────────────────┐
│ Database Transaction   │
│                        │
│ Insert Order           │
│ Insert Outbox Event    │
│                        │
│ COMMIT                 │
└───────────┬────────────┘
            │
            ▼
      Outbox Processor
            │
            ▼
       Message Broker
            │
            ▼
       OrderCreated

If the broker is temporarily unavailable, the event remains in the outbox and can be retried.


31. Idempotent Consumers

Another critical production requirement is idempotency.

A consumer may receive the same event more than once.

Example:

EventId = ABC123
OrderCreated

First delivery:

Consumer processes ABC123

Because of an acknowledgement/network failure, the broker may redeliver:

ABC123

The consumer should avoid unintended duplicate effects.

Conceptually:

if (await AlreadyProcessed(eventId))
{
    return;
}

await ProcessEvent();

await MarkAsProcessed(eventId);

This makes processing safer against duplicate delivery.


32. Retry and Dead-Letter Queue

Suppose Inventory Service receives:

OrderCreated

but its database is temporarily unavailable.

OrderCreated
     ↓
Inventory Consumer
     ↓
Database error
     ↓
Retry
     ↓
Retry
     ↓
Retry

If the message repeatedly fails, it can eventually be moved to:

Dead-Letter Queue

Flow:

Event
 ↓
Consumer
 ↓
Failure
 ↓
Retry policy
 ↓
Still failing
 ↓
DLQ

Operations teams can inspect problematic messages later.


33. Poison Message

A poison message is a message that repeatedly fails processing.

For example:

{
    "orderId": "INVALID",
    "amount": -5000
}

or a message that triggers a consumer bug.

Without appropriate retry limits, it could repeatedly fail forever.

A DLQ provides a place to isolate such messages.


34. Event Ordering

Suppose these events occur:

1. OrderCreated
2. OrderPaid
3. OrderCancelled

A distributed messaging system should not automatically be assumed to provide global ordering across all consumers.

Parallel consumers, retries and partitioning can affect processing order.

If business logic requires ordering, it needs to be designed explicitly using mechanisms supported by the chosen broker, such as partition keys or sessions.


35. Event Schema Versioning

Suppose version 1 is:

{
    "orderId": 1001,
    "amount": 2500
}

Later you change it to:

{
    "orderId": 1001,
    "customerId": 501,
    "currency": "INR",
    "amount": 2500
}

Old consumers may still exist.

Therefore, event contracts need careful evolution.

A useful principle is:

Prefer backward-compatible changes where possible.

For example, adding optional fields is generally safer than removing or renaming fields expected by existing consumers.


36. Correlation ID

Distributed event workflows can become difficult to trace.

Suppose:

OrderCreated
     ↓
InventoryReserved
     ↓
PaymentCompleted
     ↓
OrderShipped

A correlation ID can link the events:

CorrelationId = ORD-1001

Example:

{
    "eventId": "EVENT-003",
    "correlationId": "ORD-1001",
    "eventType": "PaymentCompleted",
    "orderId": 1001
}

Logs can then be searched using:

ORD-1001

to trace the distributed business transaction.


37. Event Metadata

A robust event envelope often contains metadata such as:

{
    "eventId": "2a27f45c",
    "eventType": "OrderCreated",
    "eventVersion": 1,
    "correlationId": "ORD-1001",
    "occurredAt": "2026-09-29T07:30:00Z",
    "source": "OrderService",

    "data": {
        "orderId": 1001,
        "customerId": 501,
        "totalAmount": 2500
    }
}

Important fields include:

EventId
EventType
EventVersion
OccurredAt
CorrelationId
Source
Payload/Data

38. Advantages of Event-Driven Architecture

1. Loose Coupling

Producer does not directly call every consumer.

Producer → Event → Broker → Consumers

2. Scalability

Consumers can scale independently.

Events
  │
  ├──> Consumer Instance 1
  ├──> Consumer Instance 2
  ├──> Consumer Instance 3
  └──> Consumer Instance 4

3. Extensibility

Suppose initially:

OrderCreated
   ├──> Inventory
   └──> Notification

Later the company wants analytics.

Add:

OrderCreated
   ├──> Inventory
   ├──> Notification
   └──> Analytics

The Order Service may require no business-logic change for the new subscriber.


4. Fault Isolation

If Analytics Service is temporarily unavailable:

OrderCreated
     ↓
Broker
     ↓
Analytics unavailable

other subscribers can continue processing independently.


5. Better Traffic Handling

The broker can buffer bursts of events.

Large event burst
      ↓
Broker
      ↓
Consumers process
at sustainable rate

6. Natural Fit for Microservices

Each service can own:

Its database
Its business logic
Its event consumers
Its published events

which supports independent service boundaries.


39. Disadvantages

EDA is powerful, but it adds significant distributed-system complexity.

1. Eventual Consistency

Data may not update everywhere immediately.

2. Difficult Debugging

Instead of:

A → B

you may have:

A
 ↓ Event
B
 ↓ Event
C
 ↓ Event
D

3. Duplicate Events

Consumers often need idempotency.

4. Ordering Complexity

Events may be processed concurrently or retried.

5. Infrastructure

You need messaging infrastructure such as:

Azure Service Bus
RabbitMQ
Kafka

6. Schema Management

Events become contracts between independently deployed services.

7. Operational Complexity

Production systems need:

Monitoring
Tracing
Correlation IDs
Retry policies
DLQ monitoring
Alerting
Broker health monitoring
Consumer lag/backlog monitoring

40. When Should We Use EDA?

EDA is particularly useful for:

E-commerce workflows
Payment processing
Order processing
Notifications
Inventory updates
Audit processing
Analytics pipelines
IoT systems
Background processing
Integration between systems
Long-running business workflows

A strong use case is:

One business event needs several independent reactions.

For example:

CustomerRegistered
      │
      ├──> Send Welcome Email
      ├──> Create Loyalty Account
      ├──> Update Analytics
      └──> Start Onboarding

41. When Should We Avoid EDA?

EDA isn't necessary for every operation.

For a simple immediate query:

GET /api/products/101

the caller wants the result now.

Using:

Client
 ↓
Product API
 ↓
Database
 ↓
Response

is usually much simpler than building an asynchronous event workflow.

Therefore, production microservices commonly use both:

Synchronous
REST / gRPC

        +

Asynchronous
Events / Messaging

42. EDA vs Traditional Request/Response

Request/Response Event-Driven
Caller requests something Producer announces an event
Usually synchronous Commonly asynchronous
Caller knows target Producer need not know all consumers
Immediate response Processing may happen later
More runtime coupling Looser runtime coupling
Easier to trace More distributed tracing complexity
Good for queries Excellent for business events

43. Production Architecture

A realistic architecture may look like:

                       Client
                         │
                         ▼
                   API Gateway
                         │
                         ▼
                  Order Service
                         │
                         ▼
                    Order DB
                         │
                    Outbox Event
                         │
                         ▼
                 Outbox Processor
                         │
                         ▼
               ┌─────────────────┐
               │ Message Broker  │
               └────────┬────────┘
                        │
          ┌─────────────┼─────────────┐
          ▼             ▼             ▼
      Inventory     Notification   Analytics
       Service        Service       Service
          │
          ▼
 InventoryReserved
          │
          ▼
     Message Broker
          │
          ▼
     Payment Service

For a reliable production design, important concepts include:

Event contracts
Transactional Outbox
Idempotency
Retry
Dead-Letter Queue
Correlation ID
Distributed tracing
Schema versioning
Monitoring
Saga

44. Key Points

For interviews, remember:

  • EDA is an architectural style based on events.
  • An event represents something that already happened.
  • Events should normally use past-tense names such as OrderCreated.
  • Producer publishes the event.
  • Broker distributes/transports it.
  • Consumers subscribe and react.
  • Producers don't need direct knowledge of every consumer.
  • EDA commonly provides loose coupling and asynchronous processing.
  • Common technologies include Azure Service Bus, RabbitMQ and Kafka.
  • EDA frequently results in eventual consistency.
  • Consumers should be designed for idempotency where duplicate delivery is possible.
  • Failed events require appropriate retry and DLQ handling.
  • Transactional Outbox helps reliably coordinate database changes with event publishing.
  • Saga patterns help manage distributed business transactions.
  • Sagas can use choreography or orchestration.
  • Event contracts require versioning/schema evolution.
  • Correlation IDs and distributed tracing are important for observability.
  • REST/gRPC and EDA are complementary.

45. Interview Questions and Answers

Q1. What is Event-Driven Architecture?

Answer:

Event-Driven Architecture is an architectural style where services communicate and react through events. A producer publishes an event when something happens, such as OrderCreated, and interested consumers independently process that event.


Q2. What is an event?

Answer:

An event represents a fact that has already happened in the system.

Examples:

OrderCreated
PaymentCompleted
CustomerRegistered

Q3. What are the main components of EDA?

Answer:

The main components are:

Event Producer
Event
Event Broker
Event Consumer

Q4. What is the difference between a command and an event?

Answer:

A command requests an action:

ProcessPayment

An event announces a completed occurrence:

PaymentCompleted

Commands express intent; events express facts.


Q5. What is the difference between EDA and message-based communication?

Answer:

Message-based communication is a mechanism for exchanging messages between systems.

EDA is an architectural style where events drive system behavior.

EDA commonly uses messaging infrastructure, but not every message-based application is event-driven.


Q6. Why is EDA useful in microservices?

Answer:

It reduces direct runtime coupling between services, supports asynchronous processing, allows consumers to scale independently, and makes it easier to add new reactions to existing business events.


Q7. What is eventual consistency?

Answer:

Eventual consistency means distributed services may not reflect a change simultaneously, but they become consistent as events are processed.


Q8. How do you prevent duplicate event processing?

Answer:

Design consumers to be idempotent. A common technique is to assign every event a unique EventId and record processed IDs so redelivered events don't produce duplicate business effects.


Q9. What happens when event processing repeatedly fails?

Answer:

Use controlled retry policies. After the configured delivery/retry limit, problematic messages can be moved to a Dead-Letter Queue for investigation.


Q10. What is the Transactional Outbox Pattern?

Answer:

The business data and an outbox event are stored in the same local database transaction. A background publisher then sends the outbox event to the message broker. This helps prevent database updates from succeeding while the corresponding event is lost.


Q11. What is Saga in EDA?

Answer:

A Saga manages a business transaction that spans multiple services using a sequence of local transactions and, when required, compensating actions.

For example:

Create Order
    ↓
Reserve Inventory
    ↓
Process Payment
    ↓
Create Shipment

If payment fails, a compensating action might release the reserved inventory.


Q12. What is choreography vs orchestration?

Answer:

In choreography, services react to each other's events without a central workflow controller.

In orchestration, a central orchestrator coordinates the workflow and tells participating services which steps to perform.


Q13. Does EDA replace REST APIs?

Answer:

No.

Use REST/gRPC when an immediate request/response is required.

Use events when processing can happen asynchronously or when multiple independent services need to react to the same business occurrence.

Most microservice architectures use both.


Interview-Friendly Final Answer

Event-Driven Architecture is an architectural style where services communicate and react through events. An event represents something that has already happened, such as OrderCreated or PaymentCompleted. A producer publishes the event to infrastructure such as Azure Service Bus, RabbitMQ, or Kafka, and interested consumers process it independently. This provides loose coupling, scalability, extensibility, and asynchronous processing. However, it introduces challenges including eventual consistency, duplicate processing, event ordering, schema evolution, tracing, retries, and dead-letter handling. In production, patterns such as Transactional Outbox, idempotent consumers, Saga, correlation IDs, and distributed tracing are commonly important for building reliable event-driven microservices.

← Back to Articles