Choreography vs Orchestration

I have been getting into this debate quite often; which approach is preferred - Choreography vs Orchestrator. As always, it depends - Here is my take on it…

Modules:

  • App: Like an UI module, where user trigger’s an action like:Create an account
  • Action #N: Specific modules, which has one specific action to be performed like: sending email, mail atm cards - once an account is created.
  • Coordinator: Module, which handles/triggers all the downstream actions (#n) - when an event is recived from App.

Orchestrator

alt Components

Here the coordinator is the orchestrator - which has the knowledge of the business rules - like: what are the set of actions that need to be performed when a specific event occured. If you observe, the arrows are pointing from coordinator towards actions. So, the coordinator need to understand the details of each and every API (per Actions) - their base URL/REST end points. And if each of them takes in differnt params - then all this information would sit inside the coordinator module.

The cooridnator has become the central brain. And now it has tight coupling with all the Actions. And if a new action should be added, we will have changes to the coordinator module. After a point of time - this module will become the “God like” service. And every new Actions team would have to come to coordinator team (more meetings/discussion/followps) - to have their action integrated with the coordinator. Any changes to the coordinator module would become extremely hard - as there is so much coupling. And in addition failures of each action should be handled with special case - adding more and more actions specific details/code into the coordinator module.

On deployment and version management: If there are specific changes to an Actions - URI or params. Either the action module - can never depricate their existing uri and params, as it is used by coordinator module. Or, coordinator module would have to understand the versions (of action) and act accordingly. Both can get a bit too messy. And choosing one or either of them - would require some tradeoffs (debates) to be made somewhere.

BTW: When we are just starting of - coordinator might be the easiest way to get things done (read, move faster). But as we scale out - we should look for approaches which would enable better decoupling.

Pros:

  • Better control in coordinating the Action modules
  • Handling failures would be easiers - in one place
  • One place to look at the flow chart
  • Good for transaction driven and places where actions are not idempotenent

Choreography:

alt Components

In this approach, lets take a broker like KAFKA as an example. When a new event is created its publised to a KAFKA queue with a specific TOPIC. There could be multiple subscribers (actions) - which would subscribe to the topic. The subscribers have their specific logics and subscibe to specific topics. At any point of time, any new actions can be added into the system without the knowledge of the App module. Look at the red arrows - there are NO arrow pointing from App towards specific Actions - so app doesn’t have any dependency on Action. We could also have custom subscribers (Actions) - which would run a pipeline for the data science team - this would enable us to generate observability data on the loads and trends.

Deploy: In this approach both app and action moudles can be indeopendently deployed and upgraded. The schema registry would have the contract details - topic vs the payloads.

Schema Registry: Every payload schema: should be published in the schema repository. We can use libraries like “Protocol Buffers” or “Apache Avro” for describing payload schemas.

Cons:

  • Handling errors might become very tricky. You would need an external monitoring infrastructure to track this.
  • If there are depenencies across actions - then you should think twice on using this pattern. Though there are ways to solve it - like: using sub topics.
  • Debugging can become a bit more hard. Needs distributed tracing to correlate/debug.

Conclusion:

Personal preference is to lean towards choreographed approach - as they are more loosely coupled and are more flexibble and amenable to change. Again: it all depends on your use case - if you are building a low latency system - which should catch errors and react to it really fast based on lots of buisinees logic, then orchestrator might be a better approach.

References:

Book : Building Microservices by Sam Newman

Jacob Aloysious
Jacob Aloysious
Software Enthusiast

35yr old coder, father and spouse - my interests include Software Architecture, CI/CD, TDD, Clean Code.

Related