A while back, I wrote a post about the Sidecar pattern. It has become one of my most popular posts. One of the comments I got on the post was, "how is it different than the Ambassador pattern." So in this post, I will highlight the Ambassador pattern, and I will also show the differences with the Sidecar pattern.
The Ambassador pattern is a helper service that sends network requests on behalf of other applications. It is typically used with legacy applications or applications that are hard to modify. You create an Ambassador when you need to add features like logging, connection configuration, metering , and monitoring to a legacy application. Think of it as an out of process proxy. It can also be helpful when features, like security, need to be maintained by a central group within an organization. Ambassadors can also be used to write common features that can be used across different languages or frameworks, so mixed-language environments. The Ambassador service is deployed with the application and acts as the proxy for service calls.
In this instance, the Ambassador is deployed as a Sidecar. Ambassadors can be a specific kind of Sidecar that are used with hard to change applications whereas a Sidecar can be generally applied to extend the functionality of an application.
- Need to build a standard set of client connectivity features for multiple languages or frameworks
- The ability to offload crosscutting concerns to the Ambassador
- The ability to bring legacy application forward by proxying connectivity to remote services
- Latency overhead, having to work through a proxy.
- Impact of generalized features in the Ambassador (retries may not be appropriate in a legacy app).
- Deployments may become complicated having to deploy a proxy in addition to the legacy app.
Here is an example that shows how this pattern can be used to enhance a legacy application. The Ambassador takes the incoming request and modifies it to enhance it for downstream services. It then takes the response and modifies it for the application.
This is a great pattern to have in your toolbox for when you are trying to modernize an application. It may not be feasible to rewrite your application at the moment. That shouldn’t stop you from modernization. It is also a good pattern when you want to develop some common functionality for components written in different languages. A good book for these patterns is Designing Distributed Systems (Affiliate Link).