top of page
Startup Development Team

When to Use Microservices - A Deep Dive


software architecture diagram 3D

Why does Netflix famously have thousands of microservices?


By the same token, why did Amazon, not too long ago, drop microservices architecture from its Video Monitoring system?


The topic of microservices has been under discussion and has been mulled over for well over 15 years now. Yet, for every one resource that gives you some solid advice, there are a thousand that miss the mark.


In this deep dive, I want to give you a full understanding of microservices, when to use them, and equip you with the tools to explain it all to your business stakeholders as well as other developers and architects.


Understanding when to use microservices versus other architectural styles is extremely helpful for software developers/engineers and is a must for technical/solutions/software architects. I explore what else is a must in my Unlocking the Career of Software Architect guide.


Some History


The proliferation of software systems into the mass market began in the 90s. Although personal computers have existed since the 70s, the 90s - with the advent of the World Wide Web - really marked the period when many foundational software development concepts crystallized. Before that timeframe, clear architectural patterns and principles had not yet been formalized.


At some point in the early 2000s, with the rise of large-scale distributed applications, a need emerged for a more structured and well-organized approach.


This gave rise to the layered or "N-tier" architectural style, most notably expressed in one of its offshoots—the MVC (Model-View-Controller) pattern. With N-tier architecture, the system is divided into multiple physical or logical tiers, with functionality such as Presentation, Business Logic, and Data Access residing in their own tier and communicating with other tiers through clearly defined input/output boundaries.


As things progressed and the demand for scale, resilience, and other architectural characteristics of applications increased, new paradigms began to emerge.


Architectural styles such as Space-Based Architecture, Service-Oriented Architecture (SOA), Service-Based Architecture (SBA), and the "Layered Monolith" became popular. While the scope of this article doesn't cover each of these in detail, it's important to note that around 2010, a new style began to take shape in the industry - Microservice-Based Architecture, which in itself was an evolution of SBA.


At that time, many large enterprises were using SOA, while smaller companies were mostly building monoliths. As the need for scalability increased, even for smaller players, microservices gained popularity, prompting teams to ask one key question over and over:


"Should we use microservices or stick with a monolith?"

This is the question we want to focus on in this article. The answer, of course, depends on specific use cases. At the same time, my aim is to provide you with the decision-making tools to help you and your team answer this question in an informed way.



monolith to microservices?


The Story of a Monolith


Think of a monolithic application as an application that is self-contained. It has everything that it needs in order to run. Well, almost everything… There most likely will be an external database, cache, and message queues - among other types of machinery.


The point is that all of your business logic, APIs, and communication with the outside world is done through one system, which is also most likely being deployed as a single deployable artifact.


In other words, all of your business functionality is in one place. Historically, this is how we built applications. A single codebase, a single deployable, with a team being able to reason about the system as one unit.


The MVC (Model-View-Controller) approach was and still is very popular when structuring a monolithic system.


monolith


The Quirks of the Monolith


The monolithic application can in some ways be a beautiful thing but it does come with a set of limitations and challenges. These challenges are magnified with time and as the system grows.


  1. The system becomes harder to maintain as its size and complexity increase.

  2. It becomes more difficult to understand what the different components do.

  3. The likelihood of errors, bugs, and obscure side effects rises with that complexity.

  4. Scaling the application becomes challenging.

  5. The interdependencies on internal and external components grow, making the system more tightly coupled.

  6. Onboarding new team members becomes increasingly difficult as the system's complexity grows.


Think about the last time you joined a team and had to understand the monolith they are building. Remember that? Exactly…


Over time, the application can (and often - does) turn into the proverbial ball of mud.


Microservices - The Alternative


To solve the challenges that come with a monolithic application, a new paradigm has emerged - Microservices. Although it was new as a concept, it really sprang out of the idea of Service Based Architecture.


The idea behind SBA is the usage of multiple, more-or-less, finely grained service units that are independently deployable and communicate with each other over the network.


Microservices are a more well-defined, granular, modern version of SBA. There is a stricter definition of many aspects of what constitutes a "service" within Microservices as opposed to a service within SBA.


Here are some of those differences at a high level:

Feature

Service-Based Architecture (SBA)

Microservices Architecture

Service Granularity

Coarser-grained services, handling broader business domains

Fine-grained services, each focused on a single responsibility

Service Count

Fewer, larger services

More services, each smaller and more focused

Independence

Services are somewhat independent but may share resources

Services are highly independent with no shared resources

Decoupling

Loosely coupled, but may share databases or dependencies

Strictly decoupled; services own their data and lifecycle

Data Management

Services may share databases

Each microservice has its own dedicated database

Deployment

Services are deployed together more often

Each microservice is independently deployable

Communication

Often uses synchronous communication (e.g., REST)

Can use both synchronous (REST, gRPC) and asynchronous (messaging)

Scaling

Scalability is limited to scaling the entire service

Individual microservices can be scaled independently

Technology Stack

Typically a unified technology stack

Polyglot - each microservice can use a different technology stack

Architecture Evolution

Evolution of SOA, but simpler

More modern, cloud-native approach to distributed systems

DevOps and Automation

Not strictly tied to DevOps

Relies heavily on DevOps and CI/CD pipelines


microservices


Summarizing all of the above -

a microservice is a single deployable unit that has a specific and limited functionality it performs. It talks to other microservices over the network and is independent of those other microservices in terms of change, maintenance, and deployment.

Let's dig a little deeper though…


What does "Micro" really mean in the context of a microservice?


Defining The "Micro" in Microservice


Surprisingly (or maybe, not so surprisingly) - one of the biggest challenges in a microservices-based architecture is with defining what "micro" means. In other words, strictly defining what functionality should a microservice own and what functionality should it not own - is a matter of analyzing each use case on its own merit.


As a rule of thumb though, a microservice is something that has a single responsibility and has well-defined business and system boundaries.


Domain Driven Design (DDD) is a framework and discipline that is highly helpful with determining those boundaries.


What DDD aims to do is decomposing technical and business systems into their primary units (domains, bounded contexts, and subdomains). In doing so, the proposition is that it will be easier to reason about the entire ecosystem and therefore easier to map technical representation of a system onto business functions.


If you are not familiar with the concept of DDD, I am including a number of great resources on that at the end of this article.


Furthermore, when it comes to defining the scope and boundary of a microservice, there is both a loose definition and a strict definition of a microservice in terms of responsibilities and boundaries.


Loose - Each service is reflecting either a business domain or a subdomain. For example: User Service, Order Management Service, Notification Service. 


Strict - Decomposition into the most fine-grained functionality where each service represents a single type functionality. For example, GetUser, PlaceOrder, SendNotification.


In practice, many organizations lean towards the "loose" definition when using traditional VM or container based applications.


On the other hand, when using serverless runtimes and functions as a service (FasS) such as AWS Lambda or Google Cloud Functions - often, the stricter breakdown of services is used where each "service" is as small as possible.


What is a "Service"?


Now that we have a grasp on what is meant by "micro" in the context of a microservice - let's tackle the second part of that concept - the "Service".


A service is a self-contained unit that exposes actions that can be performed on behalf of a client. In other words, a service has both a clearly defined input and a clearly defined output.

As we talked about at the beginning of this article, in the past, we had both SOA and SBA. However the services in both service-oriented and service-based architecture were:

  • Coarse-grained and broad in scope (sometimes an entire business domain)

  • With SOA, there is the concept of an enterprise service bus - ESB - through which all services communicate

  • No single definition about what should go into a service

  • With SBA - no concrete guidelines on how services communicate

  • No well defined guidelines for service overlap, duplication, and dependency


So the concept of a service existed before microservices. However, it was not as clearly defined in terms of its scope, responsibility delineation, and boundaries.


Microservices Benefits and Challenges


The Benefits


As you can already figure out from what we talked about previously, the advantages of using a microservice architecture are plenty. Namely:

  • Applying best practices to architecture and service design

    • Single responsibility

    • High cohesiveness

    • Loose coupling

  • Simpler and less error-prone maintenance as functionality is better organized

  • Each service can scale independently

  • Each service can deploy independently

  • Each service can be worked on by different teams

  • Service SDLC is independent of other services

  • Promotes service reuse

  • Easier to reason about each service

  • Minimizes unnecessary and complicated dependencies within a particular service


The Challenges


distributed application


At the same time, there are a number of key challenges that you need to consider when embarking on a microservice-based architecture. 

  • It's often difficult to define the scope and boundary of each microservice. You won't always get it right. Sometimes, it's outright impossible to get it right, which pivots the system towards duplication, overlap in responsibility, and lack of clearly defined delineation between services.

  • The deployment and operational model becomes evermore complex as instead of deploying one service, you now need to deploy, monitor, and troubleshoot multiple services.

  • The infrastructure becomes more complex. You now need to be running multiple runtimes. Potentially, you need multiple databases. 

  • There are many cross-cutting concerns that are shared between the different microservices. Monitoring, auditing, security, transaction management, logging all need to be accounted for and are more complex within the distributed environment of a microservice architecture.

  • Microservices architecture is a distributed system. As such, it brings all of the challenges of running a distributed (as opposed to a centralized) application over a network. Network reliability (or lack thereof), latency, and transport cost are all things you need to consider. These are only some of the network-specific things you need to take into account. To get a better idea of the challenges that come with networks, it helps to familiarize yourself with the 8 fallacies of distributed computing.

  • It becomes easier to reason about each single microservice but difficult to reason about the ecosystem of all services together. The more microservices you have to manage, the more things are bound to get out of hand.

  • Your team might not be ready and/or experienced in building, maintaining, and running multiple services. Your team topology must align.

  • The financial cost of running a microservice can be significantly higher at face value.

So with all of that said, how do you ensure the success of a microservice architecture? How do you prevent failure? Most importantly - how do you know when to use a monolith and when to use microservices?


Here are some rules of thumb.


Microservices - How to Win?


  • Consider starting with a modular monolith at start and breaking it apart if necessary. It saves time & effort, and allows to focus on actual business functionality at the project's onset

  • Have a clear idea of what is it you are trying to solve

  • Start small….one piece/microservice at a time

  • Keep each service as independent of other services as possible. Loose coupling or lack of coupling, rather, is key.

  • Ensure team/organization structure is aligned

  • Be aware of and follow established best-practices and patterns

  • Evolve the Data Model accordingly - your database or model may need to split as well

  • Ensure that operations/monitoring/support is aligned

  • Document the architecture in and of its details

Microservices - How to Fail?


  • Build a "distributed monolith", which is the worst of both worlds. The distributed monolith is a type of architecture where you create microservices but they end up being intertwined and highly coupled.

  • Not adjusting the team structure and model to play well with microservice ownership.

  • Having all services modify data in a single database or data model.

  • Not having a clear idea and blueprint of what you want to achieve with this architecture.

  • Not having clear boundaries between services and responsibility clearly defined.

  • Not evolving DevOps and CI/CD for catering to independent microservice deployment

  • Not documenting your architecture and service details


When Should You Actually Do Microservices?


Every use case is, again, different, and you do need to take the specific context of your team, product, and organization into account.


However, there are a few rules of thumb for when it makes sense to create a microservice architecture.


Organizational Topology


Sometimes, your team or organizational topology mandates it. In other words, if your team has grown and split into multiple teams, it often makes sense to split a system to reflect that structure.


Different NFRs and Architectural Requirements


It makes sense to use microservices when you need the ability for different parts of the system to have different architectural characteristics. For example:


  1. You need the ability to scale different parts independently. For instance, your users module receives 10 requests per second, but your order module needs to support 1000 requests per second on average.

  2. There are different SLAs and SLOs for different parts of the system. For example, you need to have a Service Level Agreement of a sub-second response time for part A of the application, but Part B has to have an SLA of not more than 200ms of response time.

  3. Different security perimeters - one part of the application is accessed by the outside world (for example a server-side rendered website) and another part is internal only (ie - an audit mechanism).

Separate Deployment and Release Cadence


When you need to be deploying one part of your system on a more frequent basis then other parts, it makes sense to split that part into its own microservice.


Beyond Microservices - The Modular Monolith or The Modulith



modular monolith


In the past few years, the industry has shifted from teams jumping on the microservices bandwagon to either jumping off of it or becoming increasingly skeptical of microservice architecture.


This has been happening as many of the teams that have begun to implement or have implemented such an architecture in recent years have begun to feel its downside in terms of cost, complexity, and challenges.


This has been culminating with some popular use cases, such as Amazon foregoing a microservice based architecture for video monitoring.


One emerging alternative to microservices is the "Modular Monolith" or Modulith, which aims to bring the best of both worlds of the monolith and microservices together.


The idea behind the modulith is that the system deploys as a single unit but is composed from independent modules that mimic a microservice architecture in terms of loose coupling, high-cohesiveness, and granularity.


In essence, the modulith aims to:

  • Rely on self-contained modules

  • Make use of a single deployment mechanism

  • Ease the decomposition into microservices if the need arises

  • Find the balance between a microservice and a monolithic architecture


Summary


Microservices offer significant advantages in terms of scalability, flexibility, and independent development, but they also bring complexity and operational overhead. A monolith can be a good starting point, especially if your system or team is small. A modulith (Modular Monolith) can offer the best of both worlds, allowing for easy evolution into microservices as the system grows. 


To ensure success with microservices, you need a strong grasp of boundaries, team alignment, and infrastructure readiness. In the end, choosing between a monolith and microservices depends on your specific use case, team structure, and scalability needs.


Consider your architectural characteristics and Non Functional Requirements as well as the costs and risks when deciding on whether to go with one type of architecture or another.


Lastly, before deciding on any kind of an architectural roadmap - consider the goals you are aiming to achieve and the best way to achieve them. Analyze, document, and design potential solutions. Ask "why" go with that particular architecture or another. This type of planning will clarify a lot, will reduce risk on making the wrong decision, and will shed some light on the right path forward.


Some Useful Resources

Architectural Characteristics



Domain Driven Design

More on Microservices

Case Studies


MVC Pattern


Fallacies of Distributed Computing


 

Mastering architectural styles, like microservices, is just one piece of the puzzle for becoming a successful software or solutions architect.

The role of an architect goes far beyond technical expertise. It also involves the of making strategic trade-offs, understanding non-functional requirements, and bridging the gap between technology and business.

If you are looking to grow and excel in this role, I have put together a comprehensive guide that breaks down the key skills, responsibilities, and knowledge areas every aspiring and experienced architect needs.

From architectural patterns to effective business communication, I am demystifying everything you need to navigate and thrive in your career as a software architect.

If you want to become a software/solutions architect or learn how to thrive as one, check the guide out: Unlocking the Career of Software Architect


Comments


bottom of page