Choreography vs. Orchestration in Microservices: What’s the Right Choice?

dazevedo

Daniel Azevedo

Posted on November 23, 2024

Choreography vs. Orchestration in Microservices: What’s the Right Choice?

Hi devs,

Microservices architecture is all about breaking down systems into smaller, autonomous services that work together. But here’s the catch: how do these services coordinate their work? That’s where Choreography, Orchestration, and even the Event Broker pattern come into play.

These are different ways to manage workflows between services. Choosing the right one isn’t just about technical preferences—it’s about how your system evolves, scales, and handles complexity. Let’s break it down with examples in C# and explore how Event Brokers can improve Choreography.


Choreography: Let Services Dance Together

Choreography is like a dance. Each service knows its part and responds to events independently. There’s no central controller dictating the steps—it’s all about reacting to what’s happening around you.

This approach shines when services need to stay loosely coupled and adaptable.

Real-Life Example: Employee Onboarding

Let’s say you’re building an HR system to onboard new employees. You might have these services:

  1. Employee Service: Registers the new hire.
  2. IT Service: Sets up email accounts and devices.
  3. Payroll Service: Prepares salary details.

Here’s how they might communicate through events:

Step 1: Employee Service Registers a New Hire

public class EmployeeService 
{
    private readonly IEventBus _eventBus;

    public EmployeeService(IEventBus eventBus) 
    {
        _eventBus = eventBus;
    }

    public void RegisterEmployee(string employeeId, string name) 
    {
        Console.WriteLine("Employee registered!");
        _eventBus.Publish(new EmployeeRegisteredEvent { EmployeeId = employeeId, Name = name });
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: IT Service Listens to the Event and Sets Up an Account

public class ITService 
{
    public void HandleEmployeeRegistered(EmployeeRegisteredEvent eventData) 
    {
        Console.WriteLine($"Setting up IT account for {eventData.Name}...");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Payroll Service Prepares the Employee’s Payroll

public class PayrollService 
{
    public void HandleEmployeeRegistered(EmployeeRegisteredEvent eventData) 
    {
        Console.WriteLine($"Preparing payroll for {eventData.Name}...");
    }
}
Enter fullscreen mode Exit fullscreen mode

Adding an Event Broker to Choreography

While pure Choreography allows services to react to each other's events directly, this can become messy and hard to manage in complex systems. That’s where an Event Broker improves the model.

An Event Broker acts as a mediator between services, ensuring events are distributed reliably without services directly depending on one another.

Benefits of Event Brokers in Choreography:

  • Decoupling: Services don’t need to know about each other.
  • Scalability: The broker handles large volumes of events efficiently.
  • Resilience: Supports retries and failure handling.
  • Monitoring: Centralized logging and tracking of events.

Example with Azure Service Bus

Instead of services directly listening to events, the Event Broker becomes the communication hub.

  1. Employee Service publishes an event:
public class EventBroker 
{
    private readonly ITopicClient _topicClient;

    public EventBroker(ITopicClient topicClient) 
    {
        _topicClient = topicClient;
    }

    public async Task PublishAsync<T>(T eventMessage) where T : class 
    {
        var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventMessage)));
        await _topicClient.SendAsync(message);
        Console.WriteLine($"Event published: {typeof(T).Name}");
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Other services subscribe to these events via the broker:
public async Task SubscribeToEmployeeEvents(string subscriptionName, Action<Message> processMessage) 
{
    var subscriptionClient = new SubscriptionClient("ServiceBusConnectionString", subscriptionName);
    subscriptionClient.RegisterMessageHandler(async (message, token) =>
    {
        processMessage(message);
        await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
    });
}
Enter fullscreen mode Exit fullscreen mode

In this model, the IT Service and Payroll Service are subscribers to the Event Broker, and the broker ensures events are reliably delivered without direct service-to-service communication.


Orchestration: A Conductor Directs the Workflow

Now imagine a conductor leading an orchestra. That’s what Orchestration is all about—a single service controls the entire workflow, calling each service in turn.

This approach works well for processes that require strict order and visibility.

Orchestrator Example

public class OnboardingOrchestrator 
{
    private readonly IEmployeeService _employeeService;
    private readonly IITService _itService;
    private readonly IPayrollService _payrollService;

    public OnboardingOrchestrator(
        IEmployeeService employeeService, 
        IITService itService, 
        IPayrollService payrollService) 
    {
        _employeeService = employeeService;
        _itService = itService;
        _payrollService = payrollService;
    }

    public async Task OnboardEmployeeAsync(string employeeId, string name) 
    {
        Console.WriteLine("Starting onboarding...");
        await _employeeService.RegisterEmployeeAsync(employeeId, name);
        await _itService.CreateAccountAsync(employeeId);
        await _payrollService.SetupPayrollAsync(employeeId);
        Console.WriteLine("Onboarding complete!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Comparing the Patterns

Feature Choreography Orchestration Event Broker
Control Decentralized Centralized Centralized Event Distribution
Coupling Loose Tight Loose
Scalability High Limited by orchestrator bottlenecks High with reliable brokers
Error Handling Complex and distributed Centralized and simpler Managed by broker
Visibility Hard to trace Full control Improved logging and traceability

Final Thoughts

Microservices are all about choosing the right tool for the job. While Choreography offers loose coupling, adding an Event Broker helps keep the system manageable and robust. Orchestration, on the other hand, is ideal when you need centralized control and strict workflows.

Keep coding

💖 💪 🙅 🚩
dazevedo
Daniel Azevedo

Posted on November 23, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related