RESTful API Design Principle: Deciding Levels of Granularity

Granularity is an essential principle of REST API design. As we understand, business functions divided into many small actions are fine-grained, and business functions divided into large operations are coarse-grained.

However, discussions about what level of granularity that needs to be in APIs may vary, we will get distinct suggestions, and even end up in debates. Regardless, its best to decide based upon business functions and its use cases, as granularity decisions would undoubtedly vary on a case by case basis.

This article discusses a few points on how API designers would need to choose their RESTful service granularity levels.

Image title

Coarse-Grained and Fine-Grained APIs

In some cases, calls across the network may be expensive, so to minimize them, coarse-grained APIs may be the best fit, as each request from the client forces lot of work at the server side, and in fine-grained, many calls are required to do the same amount of work at the client side.

Example: Consider a service returns customer orders in a single call. In case of fine-grained, it returns only the customer IDs, and for each customer id, the client needs to make an additional request to get details, so n+1 calls need to be made by the clients. It may be expensive round trips regarding its performance and response times over the network.

In a few other cases, APIs should be designed at the lowest practical level of granularity, because combining them is possible and allowed in ways that they suit the customer needs.

Example: An electronic form submission may need to collect addresses as well as, say, tax information. In this case, there are two functions: one is a collection of applicant’s whereabouts, and another is a collection of tax details. Each task needs to be addressed with a distinct API and requires a separate service because an address change is logically a different event and not related to tax time reporting, i.e., why one needs to submit the tax information (again) for an address change.

Levels of Granularity

Level of granularity should satisfy the specific needs of business functions or use cases. While the goal is to minimize calls across the network and for better performance, we must understand the set of operations that API consumers require and how they would give a better idea of the “correctly-grained” APIs in our designs.

At times, it may be appropriate that the API design supports both coarse-grained as well as fine-grained to give the flexibility for the API developers to choose the right APIs for their use cases.


The following points may serve as some basic guidelines for the readers to decide their APIs granularity levels in their API modeling.

  • In general, consider that the services may be coarse-grained, and APIs are fine-grained.
  • Maintain a balance between the amount of response data and the number of resources required to provide that data. It will help decide the granularity.
  • The types of performed operations on the data should also be considered as part of the design when defining the granularity.
  • Read requests are normally coarse-grained. Returning all information as required to render the page; it won’t hurt as much as two separate API calls in some cases.
  • On the other hand, write requests must be fine-grained. Find out everyday operations clients needs, and provide a specific API for that use case.
  • At times, you should use medium grained, i.e., neither fine-grained or coarse-grained. An example could be as seen in the following sample where the nested resources are within two levels deep.Image title

While the above guideline may understandably lead to more API deployment units, this can cause annoyances down the line. There are patterns, especially the API Gateway, that bring a better orchestration with those numerous APIs. Orchestrating the APIs with optimized endpoints, request collapsing, and much more helps in addressing the granularity challenges.

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.

Breaking a Monolith Into Microservices: Best Practices and Challenges


You Will Learn

  • What are the important features of microservices architectures?
  • What are the important challenges?
  • How do you breakdown a monolith into microservices?

Let’s start with the basics of a monolithic architecture, understand microservices architecture, and figure out what you should do to migrate from the former to the latter.

Monolithic Architecture

The salient features of monolith applications are:

  • Released, or taken to production, once every few weeks, months, years.
  • Generally, have a wide range of features and functionality.
  • Have a development team of over 50 people working on them.
  • Debugging problems that arise is a huge challenge.
  • It is almost impossible to bring in new technologies and technical processes, midway through the lifetime of such an application.

Monolith applications are typically huge and have millions of lines of code.

A monolithic application would look something like the following:

monolithic application

You have a large application talking to a large database.

Microservices Architecture

In a microservices architecture, instead of building a large application, we build a number of smaller applications, known as microservices.

Here is how you would split up the monolith MovieApplication:

Microservices architecture

As you can see here, the databases are also separated out.

Microservices architecture involves a number of small, well-designed microservices that exchange messages among themselves:Microservices architecture

Microservices Architecture Is Tough

While a microservices architecture looks very easy at a high level, implementing it is no trivial process.

There are a number of important decisions to make for moving to microservices architecture, such as:

  • What are the boundaries of the individual microservices?
  • How small should a microservice be, and what functionality should go into it?
  • What data needs to go into the database to which a particular microservice talks extensively?
  • How should the microservices communicate with each other?

Challenges With Microservices Architecture

The challenges that need to be tackled when setting up a microservices architecture are described below.

Quick Set Up Needed

You cannot spend a month setting up each microservice. You should be able to set up a microservice quickly.


Because there are a number of smaller components instead of a monolith, there needs to be automation in every activity, such as builds, deployment, monitoring, etc.


You have a potentially large number of smaller components to deploy and maintain. This number could be 100 today and 1000 tomorrow. You should be able to monitor and identify problems automatically. You need great visibility around all the components.

Bounded Context

Deciding the boundaries of a microservice is not an easy task. Applying Bounded Context principles from Domain Driven Design is usually a good starting point.

Your understanding of the domain evolves over a period of time. You need to ensure that the microservice boundaries evolve with time.

Configuration Management

You need to maintain configurations for hundreds of components across environments. It would be best to have a configuration management solution.

Dynamic Scale Up and Scale Down

The advantages of a microservices architecture can be realized only if the application can scale up and scale down easily in the cloud.

Pack of Cards

If the microservice at the bottom of a call chain fails, it can have knock-on effects on all the other microservices. Microservices should be fault tolerant by design.


When there is a problem that needs investigation, you might need to look into multiple services across different components. Centralized logging and dashboards are essential to make it easy to debug problems.


You cannot have a wide range of tools solving the same problem. While it is important to encourage innovation, it is also essential to have decentralized governance around the languages, platforms, technologies, and tools used for implementing, deploying, and monitoring microservices.

Going From Monolith to Microservices Is Not an Easy Switch

You may have noticed that after describing monolithic applications, we directly jumped into the challenges of microservices.

The reason we did not talk about the advantages of microservices first is that you need a reality check when you migrate from one architecture to another. You need to realize this is not something you can do in a few weeks or months.

Getting a microservices architecture right involves a few years of work. It’s not a switch, but a journey.

During that journey, both architectures live side by side.

You would hope that the number of applications using a microservices architecture grows over time.

Ask Why You Are Migrating From Monolith to Microservices

This is the most important question to ask! Don’t use microservices because it is a buzzword. Use it because your business needs it.

Why Are You Migrating from Monolith to Microservices? What Do You Want to Achieve?

  • Do you want to be able to adopt new technologies and processes faster?
  • Do you want faster release cycles for your application?
  • Do you want to scale more easily in the cloud?

You need to be very aware of which of these reasons is the biggest one for your migration.

The approach you use to actually migrate would differ, based on the exact reason for migration.

Let’s look at these approaches in a little more detail.

If Your Reason Is to Adopt New Technologies

Let’s say the reason you’re switching to microservices is the ability they provide to adopt newer technologies. In that case, you can start off with designing microservices for the next set of features you intend to implement. In other words, all the requirements for new feature implementation in the monolithic application are the best candidates to become microservices.

You need to answer questions such as:

  • How do you design the database?
  • How do make sure the communication between the old monolith and the new components is working?

If Your Reason Is to have Faster Release Cycles

Your business may not be happy with the pace at which new features are being released to production. In that scenario, you first need to identify those parts of the application, where there are frequent changes.

Once you do this, you can extract the fast moving parts and create microservices around them.

The idea behind this is that when there is a change, only release the related microservice.

If Your Reason Is to Scale With the Cloud

If the driving force behind the migration is scaling with the cloud, then you need to analyze what needs to be done to put your application in the cloud.

Start with research and proof-of-concept prototypes to understand the dependencies involved. You need to find out which dependencies are important to break and anticipate the problems you may face on making the application cloud-native.

More Than One

Your business might need microservices for more that one of the above reasons. Prioritize them and get started with the most important ones.

Clearly, the path to migration will not be the same for all. However, with whatever microservices that you design in your journey, make sure they address the challenges that we saw earlier, in an effective manner.

Do check out our video on this:

Or you can check it out on YouTube here.


In this article, we had a good look at the activities involved in moving from a monolith to a microservices architecture. We observed that it is not an easy journey, as the process involved in designing the two kinds of systems is radically different.

The actual journey of your migration will heavily depend upon the exact reason you want to do it. Ultimately, with whatever microservices you come up with, make sure they effectively address the challenges that exist in such a system.