Ambassador and sidecar pattern

This pattern is used when we want to segregate common connectivity features such as monitoring, logging, routing, security, authentication, authorization, and more. It creates helper services that act as ambassadors and sidecars that do the objective of sending requests on behalf of a service. It is just another proxy that is located outside of the process. Specialized teams can work on it and let other people not worry about it so as to provide encapsulation and isolation. It also allows the application to be composed of multiple frameworks and technologies.

The sidecar component in this pattern acts just like a sidecar attached to a motorcycle. It has the same life cycle as the parent microservice, retires the same time a parent microservice does, and it does essential peripheral tasks:

  • Solution: Find a set of operations that are common throughout different microservices and place them inside their own container or process, thus providing the same interface for these common operations to all frameworks and platforms services in the whole system. Add an ambassador layer that acts as a proxy between applications and microservices. This ambassador can monitor performance metrics such as the amount of latency, the resource usage, and so on. Anything inside the ambassador can be maintained independently of the application. An ambassador can be deployed as a container, common process, daemon, or windows service. An ambassador and sidecar are not part of the microservice, but rather are connected to the microservice. Some of the common advantages of this pattern are as follows:
  • Language-independent development of the sidecar and ambassador, that is, you don't have to build a sidecar and ambassador for every language you have in your architecture.
  • Just part of the host, so it can access the same resources as any other microservice can.
  • Due to connection with microservices, there hardly is any latency
    Netflix uses a similar approach and they have open sourced their tool Prana (https://github.com/Netflix/Prana). Take a look at the following diagram:
  • Take care of: The following points should be taken care of as they are the most common pitfalls:
  • The ambassador can introduce some latency. Deep thought should be given on whether to use a proxy or expose common functionalities as the library.
  • Adding generalized functionalities in ambassador and sidecar is beneficial, but is it required for all scenarios? For example, consider the number of retries to a service, it might not be common for all use cases.
  • The language or framework in which ambassador and sidecar will be built, managed, and deployed strategy for it. The decision to create single or multiple instances of it based on need.
  • Flexibility to pass some parameters from service to ambassador and proxy and vice versa.
  • The deployment pattern: this is well suited when the ambassador and sidecar are deployed in containers.
  • The inter-micro service communication pattern should be such that it is framework agnostic or language agnostic. This would be beneficial in the long run.
  • When to use: This pattern is extremely helpful in the following scenarios:
  • When there are multiple frameworks and languages involved and you need a common set of general features such as client connectivity, logging, and so on throughout the application. An ambassador and sidecar can be consumed by any service across the application.
  • Services are owned by different teams or different organizations.
  • You need independent services for handling this cross-cutting functionality and they can be maintained independently.
  • When your team is huge and you want specialized teams to handle, manage, and maintain core cross-cutting functionalities.
  • You need to support the latest connectivity options in a legacy application or an application that is difficult to change.
  • You want to monitor resource consumption across the application and cut off a microservice if its resource consumption is huge.
  • When not to use: While this pattern does solve many issues, this pattern is not recommended in the following scenarios:
  • When network latency is utmost. Introducing a proxy layer would introduce some overhead that will create a slight delay, which may not be good for real-time scenarios.
  • When connectivity features cannot be generalized and require another level of integration and dependency with another service.
  • When creating a client library and distributing it to the microservices development team as a package.
  • For small applications where introducing an extra layer is actually an overhead.
  • When some services need to scale independently; if so, then the better alternative would be to deploy it separately and independently.