Sidecar Design Pattern in Your Microservices Ecosystem

The sidecar design pattern is gaining popularity and wider adoption within the community. Building a microservice architecture that is highly scalable, resilient, secure, and observable is challenging. The evolution of service mesh architecture has been a game changer. It shifts the complexity associated with microservice architecture to a separate infrastructure layer and provides a lot of functionalities like load balancing, service discovery, traffic management, circuit breaking, telemetry, fault injection, and more.

Read my last post to understand the concepts behind service mesh, why it is needed for your cloud native applications, and the reasons for its popularity: The Rise of Service Mesh Architecture.

What Is a Sidecar Pattern?

Segregating the functionalities of an application into a separate process can be viewed as a Sidecar pattern. The sidecar design pattern allows you to add a number of capabilities to your application without additional configuration code for third-party components.

As a sidecar is attached to a motorcycle, similarly in software architecture a sidecar is attached to a parent application and extends/enhances its functionalities. A sidecar is loosely coupled with the main application.

Let me explain this with an example. Imagine that you have six microservices talking with each other in order to determine the cost of a package.

Each microservice needs to have functionalities like observability, monitoring, logging, configuration, circuit breakers, and more. All these functionalities are implemented inside each of these microservices using some industry standard third-party libraries.

But, is this not redundant? Does it not increase the overall complexity of your application? What happens if your applications are written in different languages — how do you incorporate the third-party libraries which are generally specific to a language like .NET, Java, Python, etc.?

Benefits of Using a Sidecar Pattern:

  • Reduces the complexity in the microservice code by abstracting the common infrastructure-related functionalities to a different layer.
  • Reduces code duplication in a microservice architecture since you do not need to write configuration code inside each microservice.
  • Provide loose coupling between application code and the underlying platform.

How Does the Sidecar Pattern Work?

The service mesh layer can live in a sidecar container that runs alongside your application. Multiple copies of the same sidecar are attached alongside each of your applications.

All the incoming and outgoing network traffic from an individual service flows through the sidecar proxy. As a result, the sidecar manages the traffic flow between microservices, gathers telemetry data, and enforces policies. In a sense, the service is not aware of the network and knows only about the attached sidecar proxy. This is really the essence of how the sidecar pattern works — it abstracts away the network dependency to the sidecar.

Sidecar Design Pattern

Inside a service mesh, we have the concept of a data plane and a control plane.

  • The data plane’s responsibility is to handle the communication between the services inside the mesh and take care of the functionalities like service discovery, load balancing, traffic management, health checks, etc.
  • The control plane’s responsibility is to manage and configure the sidecar proxies to enforce policies and collect telemetry.

In the Kubernetes and Istio world, you can inject the sidecars inside a pod. Istio uses the sidecar model with Envoy as the proxy.

Envoy from Lyft is the most popular open source proxy designed for cloud native applications. Envoy runs along side every service and provides the necessary features in a platform agnostic manner. All traffic to your service flows through the Envoy proxy.

The shift from monolith to microservices has enabled organizations to deploy applications independently and at scale. In a container and Kubernetes world, the sidecar design pattern is more compatible. The sidecars abstract away complexity from the application and handle functionalities like service discovery, traffic management, load balancing, circuit breaking, etc.

You can learn more about the sidecar pattern here:

Authentication and Authorization in Microservices

Microservices architecture has been gaining a lot of ground as the preferred architecture for implementing solutions, as it provides benefits like scalability, logical and physical separation, small teams managing a part of the functionality, flexibility in technology, etc. But since microservices are distributed the complexity of managing them increases.

One of the key challenges is how to implement authentication and authorization in microservices so that we can manage security and access control.

In this post, we will try to explore a few approaches that are available and see how we should implement them.

There are three approaches that we can follow:

Local Authentication and Authorization (Microservices are responsible for Authentication and Authorization)

      • Pros
        • Different authentication mechanisms can be implemented for each microservice.
        • Authorization can be more fine-grained
      • Cons
        • The code gets bulkier.
        • The probability of each service using different authentication is very low so code gets duplicated.
        • The developer needs to know the permission matrix and should understand what each permission will do.
        • The probability of making mistakes is quite high.

Global Authentication and Authorization (

    • It is an All or Nothing approach if the authorization for a service is there then it is accessible for all else none)

      • Pros
        • Authentication and authorization so there’s no repetition of code.
        • A future change to the authentication mechanism is easy, as there’s only one place to change the code.
        • Microservices’ code is very light and focuses on business logic only.
      • Cons
        • Microservices have no control over what the user can access or not, and finer level permissions cannot be granted.
        • Failure is centralized and will cause everything to stop working.

Global Authentication and Authorization as a part of Microservices

    • Pros
      • Fine-grained object permissions are possible, as microservices can decide what user the will see or not.
      • Global authentication will be easier to manage the lighter the load becomes.
      • Since authorization is controlled by the respective microservice there’s no network latency and it will be faster.
      • No centralized failure for authorization.
    • Cons
      • Slightly more code for developers to write, as they have to focus on permission control.
      • Needs some effort to understand what you can do with each permission.

In my opinion, the third option is the best one, as most of the applications have a common authentication mechanism, thus global authentication makes perfect sense. Microservices can be accessed from multiple applications and clients and they might have different data needs so global authorization becomes a limiting factor on what each application can see. With local authorization, microservices can make sure that the client application is only authorized to see what it needs to see.

My organization implemented the same approach in one of the projects that we were working on recently. We built an authentication service that was mainly responsible for integration with the LDAP system for verifying the user and then contacting the RBAC (Role-Based Access Control) service to populate the permission matrix based on the role the user is playing in the context of the application, e.g. the same user can be a normal user in one of the applications and an admin in another. So we need to understand the context from which the user is coming in and RBAC is the place where we decode the context and populate the relevant set of permissions. The permission matrix was then sent to the microservice as a part of claims in the JWT token. Microservices only apply to those permissions and return what is required to be returned. Please see the below diagram to see how we orchestrate the flow.

Microservice authentication and authorization

Architecture Flow for Authentication and Authorization


The above solution, where authentication is global and microservices control the authorizations of their content based on the permissions that are passed to it, is one of the possible solutions for handling authentication and authorization modules in microservices development. Also, we can enhance this solution by building a sidecar in a service mesh-type architecture, where we offload the authorization to the sidecar.

How Are Your Microservices Talking

In this piece, which originally appeared here, we’ll look at the challenges of refactoring SOAs to MSAs, in light of different communication types between microservices, and see how pub-sub message transmission — as a managed Apache Kafka Service — can mitigate or even eliminate these challenges.

If you’ve developed or updated any kind of cloud-based application in the last few years, chances are you’ve done so using a Microservices Architecture (MSA), rather than the slightly more dated Service-Oriented Architecture (SOA). So, what’s the difference?

As Jeff Myerson wrote:

“If Uber were built with an SOA, their services might be:GetPaymentsAndDriverInformationAndMappingDataAPIAuthenticateUsersAndDriversAPI

“Whereas, if Uber were built instead with microservices, their APIs might be more like:


“More APIs, smaller sets of responsibilities.”

With smaller sets of responsibilities for each service, it’s easier to isolate functionality. But what are microservices and how do MSAs compare to SOAs and monolithic applications?

What Are Microservices?

Simply put, microservices are a software development method where applications are structured as loosely coupled services. The services themselves are minimal atomic units which together, comprise the entire functionality of the entire app. Whereas in an SOA, a single component service may combine one or several functions, a microservice within an MSA does one thing — only one thing — and does it well.

Microservices can be thought of as minimal units of functionality, can be deployed independently, are reusable, and communicate with each other via various network protocols like HTTP (more on that in a moment).

Today, most cloud-based applications that expose a REST API are built on microservices (or may actually be one themselves). These architectures are called Microservice Architectures, or MSAs.

On the continuum from single-unit, monolithic applications to coarse-grained service-oriented architectures, MSAs offer the finest granularity, with a number of specialized, atomic services supporting the application.

Microservices vs. SOA vs. MonolithicSource: Samarpit Tuli’s Quora Answer: “What’s the difference between SOAs and Microservices?”

Some Challenges

From this, one starts to get a sense of how asynchronous communication at scale could serve as a benefit in the context of apps that pull and combine data from several APIs. Still, while most organizations are considering implementing their applications as MSAs — or already have — the task, especially when refactoring from MSAs or monoliths, is not exactly straightforward.\

For example, 37% of respondents building web apps reported that monitoring was a significant issue in one sample. Why?

Some clues can be seen in some of the challenges cited by those refactoring legacy apps to MSAs — overcoming tight coupling was cited by 28% of respondents, whereas finding where to break up monolithic components was cited by almost as many.

These types of responses suggest a few different, but actually related, conclusions:

  1. Monitoring services built on MSAs is more complicated (as opposed to SOAs or Monolithic apps) because of multiple points of failure (which exist potentially everywhere a service integrates with another).
  2. Tight coupling suggests components and protocols are inflexibly integrated point-to-point in monolithic apps or SOAs (making them difficult to maintain and build functionality around).
  3. Breaking up monolithic apps or large SOA components into atomic, independent, reusable microservices is challenging for exactly those first two reasons.

Also, what sort of problems can one expect when your application scales? We’ll look at these and suggest a solution below. But there’s one question that underlies all of the above concerns: Once we do manage to break up our apps into atomic services, what’s the best way for these services to communicate with each other?

Some Microservices Communication Patterns

In her article “Introduction to Microservices Messaging Protocols,” Sarah Roman provides an excellent breakdown of the taxonomy of communication patterns used by and between microservices:


Synchronous communication is when the sender of the event waits for processing and some kind of reply, and only then proceeds to other tasks. This is typically implemented as REST calls, where the sender submits an HTTP request, and then the service processes this and returns an HTTP response. Synchronous communication suggests tight coupling between services.


Asynchronous communication means that a service doesn’t need to wait on another to conclude its current task. A sender doesn’t necessarily wait for a response, but either polls for results later or records a callback function or action. This typically is done over message buses like Apache Kafka and/or RabbitMQ. Asynchronous communication actually invokes loose coupling between component services, because there can be no time dependencies between sending events and a receiver acting on them.

Single Receiver

In this case, each request has one sender and one receiver. If there are multiple requests, they should be staggered, because a single receiver cannot receive and process them all at once. Again, this suggests tight coupling between sender and receiver.

Multiple Receivers

As the category indicates, there are multiple receivers processing multiple requests.

We believe that, while each of these methods (in combination) have their purpose within an MSA, the most loosely coupled arrangement of all is when microservices within a distributed application communicate with each other asynchronously, and via multiple receivers. This option implies that there are no strict dependencies between the sender, time of send, protocol, and receiver.


The pub-sub communication method is an elaboration on this latter method. The sender merely sends events — whenever there are events to be sent— and each receiver chooses, asynchronously, which events to receive.

Apache Kafka may be one of the more recent evolutions of pub-sub. Apache Kafka works by passing messages via a publish-subscribe model, where software components called producers publish (append) events in time-order to distributed logs called topics (conceptually a category-named data feed to which records are appended).

Consumers are configured to separately subscribe from these topics by offset (the record number in the topic). This latter idea — the notion that consumers simply decide what they will consume — removes the complexity of having to configure complicated routing rules into the producer or other components of the system at the beginning of the pipe.

diagram of apache kafka producers writing to and consumers reading from a topic

We argue that, when asynchronous communication to multiple receivers is required, Apache Kafka is a promising way to go, as it solves the problem of tight-coupling between components and communication, is monitorable, and facilitates breaking up larger components into atomic, granular, independent, reusable services.

Why Apache Kafka?

Routing Rules Configured by Consumer

When the routing rules are configured by the consumer (a feature of pub-sub and Apache Kafka generally), then, as mentioned, there is no need to build additional complexity into the data pipe itself. This makes it possible to decouple components from the message bus (and each other) and develop and test them independently, without worrying about dependencies.

Built-in Support for Asynchronous Messaging

All of the above makes it reasonably simple to decouple components and focus on a specific part of the application. Asynchronous messaging, when used correctly, removes yet another point of complexity by letting your services be ready for events without being synced to them.

High Throughput/Low Latency

It’s easier to have peace of mind about breaking up larger, SOA-type services into smaller, more atomic ones when you don’t have to worry about communication latency issues. Aiven managed Kafka services have been benchmarked and feature the highest throughput and lowest latency of any hosted service in the industry.

Why Managed Apache Kafka?

Apache Kafka was built to leverage the best of what came before while improving on it even more.

However, Apache Kafka can be challenging to set up. There are many options to choose from, and these vary widely depending on whether you are using an open-source, proprietary, free, or paid version (depending on the vendor). What are your future requirements?

If you were choosing a bundled solution, then your choice of version and installation type, for example, may come back to haunt you in the future, depending on the functionality and performance you later decide you need.

These challenges alone may serve as a compelling argument for a managed version. With the deployment, hardware outlay costs and effort and configuration out of your hands, you can focus entirely on the development for which you originally intended your Kafka deployment.

What’s more, managed is monitorable. Are you tracking throughput? You need not worry about where the integration points are in your app to instrument custom logging and monitoring; simply monitor each of your atomic services’ throughput via your provider’s Kafka backend and metrics infrastructure.


What sort of problems can you expect when your application scales? Bottlenecks? Race conditions? A refactoring mess to accommodate for them?

A managed Kafka solution can scale automatically for you when the size of your data stream grows. As such, you needn’t worry when it’s time to refactor your services atomically, and you needn’t force your teams to maintain blob-style, clustered services with complicated dependencies just for the sake of avoiding latency between them.

Centralized, No-Fuss Management

If you’re managing your own cluster, you can expect to be tied down with installs, updates, managing version dependencies, and related issues. A managed solution handles all of that for you, so you can focus on your core business.

High Availability

Apache Kafka is already known for its high availability, so you never have to worry about your services being unable to communicate because a single node supporting your middleware is down.

Kafka’s ability to handle massive amounts of data and scale automatically lets you scale your data processing capabilities as your data load grows. And a managed solution has redundancy built right in.

Wrapping Up

We looked at some common challenges of refactoring from SOAs to MSAs: monitorability, tight coupling of components, and the challenges of breaking up larger monolithic or SOA components into microservices.

We considered different types of communication and looked at how a pub-sub mechanism serves asynchronous message transmission between multiple services. Finally, we examined how a managed Apache Kafka solution may be an excellent candidate for such a use case.q

Questions to Ask Before Choosing Microservices

One of the companies I worked with had over 300 microservices, all set up with CI/CD pipelines, Consul service discovery, and decoupled system integration using messaging and queues. I’m now working with a mid-size company where I’ve introduced a few microservices, but I’ve since then started to wonder: When should I and when shouldn’t I go down this path? I don’t have a definitive answer here, so I’m just going to throw a few questions and for us to discuss.

  • Is my business suitable for more monolithic or distributed systems? Think product portfolio and revenue streams: The more complex your current business model is, the more you are probably leaning towards distributed systems.
  • Will business logic get updated later on? Do I need a centralized logic engine or data mapping engine (e.g. Dell BOOMI)?
  • If distributed systems are the way to go, do I use microservices or modularized applications?
  • How frequently is the data updated? How frequently is the data retrieved? Do I need the data to be eventually consistent or always consistent? This will affect more than just your application structure — it will affect how you implement caching as well.
  • Is service discovery going to be a problem? Will it be a messy mesh of endpoints to manage and maintain?
  • Are my devs comfortable with the structure we are heading to?
  • Is there an integration expert/architect that can lead the project and follow through?
  • What if one of the service endpoints fail? How do I recover? How do I monitor all these effectively?
  • How do I manage security settings and authentication across all the services?

And once you’ve answered all these questions, you probably also want to make a calculation on the cost side — this should include both infrastructure and resource costs (your dev team, your DevOps team, training, and ongoing maintenance).

Let me know what you think!

Microservices: Are They for Me?

Microservices are one of the biggest buzzwords of recent years. However, it turns out that it is a bit like teenage sex: everyone talks about it, but nobody really knows how to do it. What does it take to make good use of this architecture? What conditions do we have to meet so that it’s something more than just an item on your CV? Read the article to find out.

Nothing New Under the Sun

Several years ago, conferences were all about Service Oriented Architecture. In a nutshell, it consists of building large systems with many logically divided services integrated with each other. The idea was to eliminate the main problems related to monolithic architecture. Most SOA implementations were based on, or shifted over time toward, the Enterprise Service Bus. The bus was responsible for communication routing, document mapping, handling different types of endpoints, auditing, and security. The idea was noble, but the versatility of the solution turned out to be a double-edged sword. After some time, the bus turned into another monolith. Centralization, bottlenecks, both in terms of development and efficiency, and a single point of failure contributed to the growing criticism of the solution. I know cases where a 60-80-person team working on the bus turned out to be insufficient and a part of the communication had to be point-to-point so as not to block business projects.

The architecture of microservices, which is a de facto implementation of the SOA style, is based on the conclusions drawn while using the ESB model. The way of communication has changed dramatically. Replaced by point-to-point information exchange, the omnipotent bus is no longer the core of the solution. This is supposed to eliminate bottlenecks and enable independent development of projects.

Micro Is Not So Small

How big is micro? Counting the number of lines of code is one of the most questionable methods of assessing the size of an application. But it will be sufficient for now. The most common answer to the question, “how many lines of code should a statistical microservice have?” is “1000.” I don’t want to act like an oracle and judge whether it’s right or wrong. But let’s resort to math for support (back to the beginning of primary school). Let’s assume that the average size of one monolithic application (developed by a 20-30-person team) is half a million lines of code. If we divide it into components of a thousand lines each, in theory, we will get 500 services. This is not much less than the giants like Netflix or Uber have. Across the whole company. Developed by nearly two thousand engineers. And we have 30. Does it mean that you have to employ additional 1,970 people in order to switch to a new architecture? Or is it better to change the level of granularity?

Assuming that 3-5 people can work on one service, let’s divide our monolith, for example, into 8 applications. On average, each of them will have about 60 thousand lines. And this is getting more realistic. As a programmer, I can easily grasp an application of this size in detail. You can also implement a specific part of the business and effectively develop it with a small Agile team.

But you may start wondering, what is actually wrong with microservices? Why should I trust others? First of all, it is worth noting that their solutions work very well, which may be indicative that their reasoning is right. It is the availability of the platform that is the main reason for choosing this particular granulation. In the case of using synchronous communication between services, a phenomenon referred to as “temporal coupling” takes place. In order to continue processing a business transaction, it is necessary to obtain a response from the second service, which may request a response from the third one and so on. The greater the “synchronous depth of the system,” the smaller its availability.

I Don’t Have Users, Are Microservices the Answer?

There are many myths surrounding microservices. If I were to believe everything I hear about them at conferences, I would probably insist that breaking up monoliths into microservices is the answer to public debt and world hunger. I don’t even have to tell you that it’s nonsense (Or maybe I have to? Don’t blindly believe everything that you hear at conferences!).

What is the difference between microservices and the classical distributed system? Listening to informal discussions, one can conclude that it is an IT equivalent of boasting about the price or size of a car. “How many microservices do you have? Well, we have 400.” Frankly speaking, I’d rather have 40 decent ones than 400 sloppy ones just to have something to brag about in front of my friends. But who am I to tell you. The basic difference between microservices and the classical distributed system boils down to autonomy. The dispersed system, although it implements the process by means of many separate systems, conceptually resembles a monolith. All systems are updated with a single implementation and often do not even support the unavailability of collaborators (applications which they communicate with). This is completely different with microservices. Each service has its own lifecycle. Works on individual applications are carried out independently and implemented without coordination. It is often the case that a service we depend on is not available, because the implementation of a new version is in progress.

Autonomy is one of the best things microservices can offer. It enables truly agile and scalable development of the system. Discussions such as the following are now becoming a thing of the past: “You can’t implement project X now, because project Y is still being tested.” Unfortunately, this independence also makes microservices by far the most difficult architecture I worked with. The need to constantly work in the “design for failure” model and to anticipate any communication problems in advance is what baffles even the best programmers and architects. On the other hand, if the business is not ready to work in such a model and insists on staying in the release model, microservices lose one of their greatest assets. You have to foot the bill, but the problems remain unsolved.

Where Are the Limits?

One of the most challenging tasks when it comes to implementing microservices architecture is to define their limits. The first point of reference is the Bounded Context concept known from Domain Driven Design. In every context, there is usually a domain expert, who is often the business owner of the processes taking place there. As a result, reducing the size of the application to a specific business area which can be managed by one person translates into better organization and consistency than if you need to reconcile different interest groups. Data ownership and stages in the business process should also be considered. If two seemingly disconnected contexts affect the same data, this may mean that the division is artificial. However, it may also be necessary to designate a third independent context to manage data used in other processes.

These are the main criteria for dividing services, but the list is not exhaustive. If one function can be much more effectively implemented in a different technology (e.g. in a different language) than the main service, separating them should be considered. The same applies to scalability. If you know that certain functions will be used very intensively, moving them to a separate component may be a good idea. Security is the third aspect to consider. If the requirements in this area differ significantly from one function to another, putting them into one application may not be the best idea.


What are the basic applicability criteria for microservices? Consider this architecture if:

  • the business you work with is ready to abandon the classic release model.
  • individual business units are able to implement projects autonomously.
  • you need dynamic and asymmetric scalability.

Make sure you leave a comment below.

Microservices Best Practices

As more and more development teams are becoming aware of the benefits of microservices and service-oriented architecture, we need to make sure we’re not just barreling ahead with little to no plan. It’s essential to think about the consumers of these services; we need to craft good developer experience in order to make working with microservices easy and maintainable.

In this article, we’ll look at some microservices best practices suggested by Michele Titolo (Capital One)from her talk at DockerCon 2016.

What Is a Microservice?

Let’s start off with a clear definition of what a microservice is:

  • A small service that does one thing well
  • Independent
  • Owner of its own data

Microservices exist in a larger ecosystem. It’s important to not just think about the one microservice. We need to make sure we think about how it connects to the larger system of the network.

Make Microservices Easy to Use

The needs of consumers of microservices all overlap. How can we ensure we’re making a great microservice for everyone?

There are a few things that are essential to creating a good developer experience with a microservice, and you should put enough effort into them to make sure you’re doing a good job with them:

  • Documentation: Be clear and concise.
  • Version and revision history: Provide historical records of when things changed and why.
  • Live documentation: If possible, offer live responses (for example: APIs —> JSON response).

Other initiatives that can help make a big difference are:

  • Creating a dependency graph
  • Auto-generating documentation
  • Integration monitoring tools
  • Logging

We need to be able to surface errors before our service goes down.

Make Sure Your Microservices Can Coexist

In the end, it all comes down to two things:

Here are a few good questions you can ask yourself in order to check that you’re developing your microservice in a sustainable way:

  • How does my microservice fit in with the others?
  • Are my services capable of working together? Think date formats and so on.
  • Am I taking single responsibility too far? Don’t try to force yourself into breaking up your monolithic apps. Sometimes it makes sense to not break everything up.

Your Best Practices for Microservices Checklist

Finally, if you want to build friendly, sustainable microservices, here’s a good checklist:

  • Helpful documentation
  • Built with monitoring and troubleshooting in mind
  • Easily deployable and scalable
  • Easy to consume
  • Coexists with established conventions

Always be sure to make your service easy to deploy and scale. Provide consistent error messaging and make sure your microservice consumers can hit the API directly in a nonproduction environment.