Ambassador, Sidecar, and Adapter Pattern

Deploy parts of the application as a separate process/container - sidecar and other related patterns

Published on Tuesday, August 9, 2022

Offload everyday tasks for connectivity such as monitoring, routing, logging, and security (usually as a sidecar).
Ambassador Pattern

Deploy parts of the application as a separate process/container.
Sidecar

Transform the output of the application without changing the application itself.
Adapter

Different Definitions

There are few opinions on the differences between ambassador and sidecar patterns. Differences are based on:

  • Number of apps external services can serve
    • Does only one app uses external services or perhaps many?
  • Lifecycle of the external services
    • Does the external service "lives and dies" by the main app?
  • Functionality
    • Is the external app dedicated only to connectivity?

I think most differences of opinions come from the fact that you can observe these patterns:

  • Container Orchestration Patterns (Kubernetes Patterns)
    • You can use your main and sidecar apps in a single pod.
  • Cloud Patterns
    • Without containers, you can put sidecar apps anywhere.
    • Why would you not just run another process on that machine if you have VM?
    • Serverless sidecar app, maybe?
  • Object-Oriented Software Design Patterns
    • There are no Ambassador and Sidecar patterns in the original GOF Book, but there is the Adapter pattern.

Problems

Cloud apps, SOA/microservices, etc., require many features such as monitoring, routing, logging, and security. It is time-consuming and sometimes impossible for legacy applications to add these features. If you decide to go with microservice architecture, how often will you implement retry, circuit breaker, etc.? Even if you use a library like The Polly Project, do you want to set up everything from scratch for each microservice/distributed app? If you offload a lot of setups for every new microservice to something like Yeoman, you still have to maintain them.

Further, network and security calls may be managed by different teams entirely. A lot of communication between teams is necessary if everything is bundled together. There is always a risk with large codebases, unfamiliar technologies, etc.

Solutions

Extract frameworks and libraries for communication, monitoring, etc. Put them in the external "Ambassador" process that serves as a proxy between your app and other services. Deploy Ambassador in the same host or nearby (with low latency).

Extract various services, like state management, actor models, messaging, secret managing, etc., and put them into the external "Sidecar" process that serves as an external unit of your app. Deploy Sidecar in the same host or nearby (with low latency).

Considerations

  • How are you going to deploy the main app and the sidecar application?
    • Kubernetes have native support for this kind of case.
  • What kind of communication are you going to use?
    • Rest and gRPC are currently the de-facto standard.
  • Is a sidecar the best solution?
    • Can you implement a solution as a single process?
    • Maybe a library is a better solution?
  • What kind of optimization is necessary?
    • Will a sidecar add too much latency?
  • Do you have the resources to deploy sidecar services and manage them?
    • Even if it is an appropriate solution, maybe the maintenance cost is too high.

References