A look into the history, definition, and description of this modern approach to software development
TABLE OF CONTENTS
The History of Microservices
The Characteristics of Microservices A. Microservices are loosely coupled B. Microservices can be developed in any programming language C. Microservices feature a Decentralized Management Model D. Microservices both exhibit evolutionary and revolutionary traits
Microservices as catalysts for change A. Microservices vs. Monoliths B. Microservices vs. Legacy systems C. Microservices and APIs
Tips on Adopting a Microservice Architecture A. Constellations B. Creating a labeling system C. Challenges with adoption
When the same group met the next year, they decided to formally adopt the term “microservices”.
The term was then defined by Martin Fowler and James Lewis in their article on microservices as “an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.”
Fast forward to more than half a decade later, the term microservices has gone beyond its status as a buzzword in the industry. In fact, it is slowly becoming the default architecture style for building enterprise applications.
Let’s take a look at what makes microservices tick.
II. The Characteristics of Microservices
In 2014, the still undefined and unnamed microservices architecture was seeing some positive results, so much so that it was slowly becoming the default style for building enterprise applications during that time.
In their seminal article, thought leaders Martin Fowler and James Lewis both came up with the various characteristics that make up a microservices architecture. The article states:
“While there is no precise definition of this architectural style, there are certain common characteristics around organization, business capability, automated deployment, intelligence in the endpoints, and decentralized control of languages and data.”
They then follow that up by explaining what outlines the microservices style and how to implement it.
“The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.”
The book, Microservice Architecture, by Irakli Nadareishvili, Ronnie Mitra, Matt McLarty, and Mike Amundsen, expands on Fowler and Lewis’ definition, which states:
“A microservice is an independently deployable component of bounded scope that supports interoperability through message-based communication. Microservice architecture is a style of engineering highly automated, evolvable software systems made up of capability-aligned microservices.”
With these definitions, it is clear that microservices split a large application into smaller, more manageable parts. This affects the organizations implementing the architecture, as teams become split into technology layers such as UI, database, application logic, and more. This is a clear implementation of Conway’s Law.
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. — Melvin E. Conway
Conway’s Law explains how software systems and architectures almost always end up to be shaped like the organizational structure they were designed in.
This law also provides a theoretical framework for microservices.
“Many people think that the organization’s communication structure in Conway's Law represents the organization hierarchy. However, it rather represents how the various teams and organizations communicate with each other.” adds Rahul Rai, Author of Microservices with Azure by Packt.
Because of this, cross-functional teams emerge within the organization. Each team is then tasked to create specific products based on one or multiple services.
This is analogous to how microservices are loosely coupled, which is an essential characteristic for this type of architecture.
Microservices are loosely coupled
Loose coupling is when individual components within a system are detached from each other, working independently and offering benefits such as extensibility and scalability. It is the opposite of tight coupling.
Microservices have a strong sense of loose coupling, as you must be able to deploy a single microservice on its own without the need for coordination with other microservices. This enables frequent and rapid deployments, allowing developers to push out features and capabilities a lot faster.
Additionally, each microservice should have its own database and should only contain data relevant to the domain of the microservice itself. This will allow you to deploy individual services independently. Individual teams can now own the databases for the corresponding microservice.
Databases should be treated as private to each microservice. No other microservice can directly modify data stored inside the database in another microservice.
Microservices can be developed in any programming language
Certain programming languages would be a better fit for a particular set of problems. The choice of language could also go down to the team’s expertise.
Microservices seem to be naturally compatible with the idea of polyglot programming, where you can have multiple teams working on projects independently, and using a language of choice – either because it’s a personal preference, or because they find that programming language fits their purpose.
Microservices can be developed in any programming language as each service could run its own process, and would have an interface that accepts certain inputs to product given outputs – much like how an API operates. So long as the interface doesn’t change, you can implement a service in any language, and even utilize different data storage techniques.
“In our Building Evolutionary Architectures book, we actually introduced something called ‘Goldilocks Governance’. The idea was finding the ‘just right fit; for these things. Not too much, not too little. And the idea of Goldilocks governance is: ‘let's pick a few technology stacks – a simple one, a medium one, and a complex one – and standardize on those rather than one size fits all’ or, ‘one unique one for everybody’.”
“And I think microservices really facilitates that because it does have that extreme level of decoupling and the idea of bounded context, which keeps everything local from a technology standpoint. And you can integrate with things as you need to, without going down that over-engineering route.” Ford explains.
With the “loosely coupled” characteristic, polyglot programming further gives microservices a level of isolation, creating the ideal development environment where no incidental coupling between services is observed.
Ford shares an early microservice success story with a well-known to-do list application called “Vendor List” where each service was written in a different language.
“It is a bit extreme”, he comments, “but one of the things that you're trying to achieve in microservices is no incidental coupling between services – no shared stuff – because that breaks the bounded context. One sure-fire way to make sure nobody's actually sharing anything is to make somebody write in .NET and somebody else write it in Java.”
He adds that one of the great revelations in microservices is that simple things can have a simple tech stack, which then prevents development teams from over-engineering everything to a ridiculous degree, and making use of a language, database, or platform that’s more suitable for the problem.
Microservices feature a Decentralized Management Model
One of the main concepts of microservices is the use of a decentralized management model, giving teams the ability and liberty to to develop software components with different technology stacks. Rather than forcing a monoculture, this model allows teams to better build and deploy the code they created based on their own governance models and strategies.
With a higher degree of liberty and independence, development teams can solve problems with more efficiency, better focus, and greater velocity. Having said this, it is crucial for teams to develop a DevOps mindset, giving developers more control over their governed components.
Microservices both exhibit evolutionary and revolutionary traits
Microservices have grown to become a guiding principle for how modern software development is done. The evolution of software architecture to microservices came about when developers realized that they could break up the applications into smaller, more manageable systems, which paved the way for effective deployment pipelines.
And the first catalyst to this was the idea of continuous deployment.
We had continuous integration, and that was a good first step, but when Dave Farley and Jez Humble came out with the book Continuous Delivery, it was just remarkable. It finally gave us the answers on how to effectively deploy software." explains Mark Richards, co-author of the book Fundamentals of Software Architecture and founder of the site DeveloperToArchitect.com.
Continuous deployment and delivery, he adds, allowed for developers to finally address large monolithic applications that didn’t work.
The second evolutionary catalyst Richards mentioned was Eric Evans’ concept of domain-driven design.
"I’m bold enough to say that microservices would not exist without the bounded context concept which Eric Evans drove through domain-driven design. These two [catalysts] are ‘parents’ of microservices in a way." he explains.
Richards adds that microservices was the very first architecture style that came out which required users to consider data as part of the architectural design – which he considers as revolutionary.
"No other architecture style in existence has required this." Richards reveals.
The other aspect that made it revolutionary was the collaboration required for microservices to succeed.
"We’ve been trying to collaborate, not just communicate between each other, but really collaborate – working together on developing a cohesive system. Microservices requires this collaboration. Without it, things completely fall apart." he adds.
III. Microservices as catalysts for change
In this section, we’ll see how microservices are currently changing the landscape of software development in contrast and conjunction with existing architectures, concepts, and technologies.
Microservices vs. Monoliths
Traditionally, software developers built these large applications which we call monoliths. These monolithic applications would then house all the code for all the operations of a business -- which meant that if the requirements for the application would grow alongside the monolith.
However, enterprise applications often evolve into large and complex monolithic architectures that can often be quite challenging to maintain over time.
The solution to this was the service-oriented architecture (SOA), which emerged in the late 1990s as an enterprise-wide approach to software development.
It takes advantage of reusable software components or services, where each service within the architecture is composed of the code and integrations needed for a specific business function to operate.
SOA thus eliminated the need for point-to-point integration that developers had to recreate or duplicate for each new project. It allowed developers to simply reuse existing capabilities and connect these through the SOA ESB (enterprise service bus) architecture.
Just like the SOA, Microservices came about as a response to the traditional monolithic architecture of application design which focuses on the deployment of multiple services within a single application. However, when the number of the services increases, a monolithic architecture can turn complex. Adding additional new features adds further complexity and overhead.
In the traditional SOA model, applications are segregated into modular parts. On the other hand, the microservices pattern addresses the inherent problems associated with monolithic SOA architecture by breaking down the entire application development into a collection of small autonomous services. Here, the services implement a single business capability while it communicates over well-defined APIs.
Migration
Chris Richardson, author of Microservices Patterns, explains how organizations can migrate to microservices by “strangling” their monoliths.
“Instead of doing a ‘big-bang’ rewrite’ [of your application] – which is extremely time consuming and risky – you can actually incrementally build up a strangler application around the legacy application.” Richardson advises.
He adds that gradually migrating functionality one module at a time to a Strangler Fig Application allows for an incremental and iterative process. Martin Fowler applied the name “strangler fig” to this strategy, being inspired by the stranger vine found in rainforests. A strangler vine grows around a tree in order to reach the sunlight above the forest canopy. Sometimes, the tree dies, leaving a tree-shaped vine.
The Strangler Fig Application follows the same pattern, whereas developers would build new applications (vine) around the legacy application (tree) which eventually dies.
This could be a time consuming process, Richardson describes, but adds how this would make teams “focus on areas of the application that give [the business] the greatest return on investment – those parts of the application that you’re changing constantly”.
“You should focus on those parts of the application that have a module that's constantly being developed. You turn it into a service so that you can quickly develop it, or, maybe there's a module that's causing scalability or reliability issues, you migrate that into a service so that you can scale it independently.” Richardson adds.
However, this is not to say that microservices spell the end for the monolithic architecture.
Rahul Rai argues how microservices aren’t a cure-all to the challenges and pain points associated with monoliths.
"In fact, in most of the cases, monoliths are a better design choice, and some monoliths, such as the single process [monolith] or modular monolith, have a whole lot of advantages as well." Rai says.
He adds that it is much simpler to deploy a monolith, as it is easier to avoid many of the pitfalls associated with distributed systems. As a result, monoliths can have much simpler developer workflows.
Microservices vs. Legacy Systems
Let’s first define what a legacy system is.
A legacy system is based on older technology, old methods, application programs, or computer systems, which are related to, or part of a computer system that has been considered outdated. Despite their old-age, however, these legacy systems continue to be in use and are often running mission-critical applications and processes.
We can consider mainframe-based systems as legacy systems as an example. The term “legacy” signifies it has set the way and set some standards to follow. At the same time, it may imply that the system needs replacement as it is outdated.
A microservice architecture can be utilized in modernizing a legacy system. As mentioned above, you can break down the monolith, implement each functionality as a microservice, or extract already existing modules and turn them into standalone microservices.
Proxies are also used in legacy applications, which are used to change the implementation of a service but still present the traditional legacy interface to the other services, or to the customer.
Monolithic systems can use API proxies to communicate with legacy systems to perform functions that have yet to be migrated. The proxy masquerades as an actual service with microservices behind it. After these services are migrated, the proxies may be removed.
IT management consultant Erik Dietrich of Daedtech.com explains how his enterprise clients used microservices to facilitate legacy system migration through a method he describes as “thin slicing”.
“I see [microservices] as a fundamental piece of enablement to get away from a legacy system,” he says.
One of the most common failure patterns enterprises do to modernize their legacy systems is to bring in “some huge app development body shop to build an enormous piece of software”, Dietrich shares. This would eventually lead to the organization realizing that there isn’t going to be a “magic, switch-over moment” from their legacy systems to microservices.
That’s where “thin slicing” comes in to get some kind of win.
As mentioned above, Erik also shares how using proxies can be successfully utilized to perform the migrations.
“How do we get one little piece of this legacy system routed over to the new system? And inevitably, the answer there is some kind of adapter or proxy type concept. So, you put something in front of the legacy system – say in the form of a microservice – that you just call through into the legacy system.”
“And then once that's all structured well and going well, you put in some kind of feature flag where you can flip it over to start being serviced by the new system. And if that goes poorly, you just flip it off and go back to where you started.” Dietrich explains.
Microservices and APIs
An API strategy is used by companies to expose services, regardless whether they’re found within an on-premise monolithic system or cloud-native microservice architecture.
An API-led connectivity becomes crucial for organizations wishing to adopt microservices, as it will provide solutions for integrating services from their legacy IT stack. APIs would be used to bridge the gap between microservices and their traditional systems. These would also allow them to build and manage microservices easier.
If the APIs are well-managed, they could also make microservices more discoverable, and could then become reusable components which could open up their functionality to both internal and external stakeholders.
IV. Tips on Adopting a Microservice Architecture
In this penultimate section of the article, we’ll focus on how your organization can capitalize upon the use of microservices with tips, best practices, and advice to help you get started.
Group your microservices into constellations to reduce complexity
James Lewis, who defined the microservices architecture style in 2014, advises organizations to shift their perspectives when it comes to dealing with their complexity.
“I think the mistake people make is by trying to look at it too much in the round, in essence, right? Because depending on where you're standing, yes, things can look really, really complex. It's a bit like the night sky, right? You look at the night sky, you see all these stars and it looks like there's lots and lots and lots and lots of stars up there. And there are, but actually if you start to think of those stars and constellations, there's fewer constellations out there.” he says.
“I think that the service landscape in a large enterprise is sort of similar to that… that’s really complex. However, if you consider them as groups of things instead, [such as] how we grouped together into business capabilities, and then organize your teams around that, the people in the side of those capabilities, they don't need to see the whole night sky. They just need to be concerned with their solar system.” Lewis explains.
Creating a labeling system
To avoid potential disasters within a system, author of “Architecting for Scale” Lee Atchison shares the concept of using a labeling system called “service tiers”. “What we do is we have four tiers assigned: tier one through tier four. Tier one are your most business-critical services. And tier four are your least business-critical services. You assign each service to a tier, an example of a tier one business critical service is a service that is, you know, if this service fails, your application will fail. You don't have any choice. A classic example of that is a log-in surface. You can’t log into a website application if that application is not useful to you.” Atchison shares.
He says that, with this kind of system, you can identify and make plans for which problems you should prioritize and fix first. You could also effectively identify what order the problems are fixed, and how important the different parts of the application are. Atchison adds that the details are found within the middle interactions, between the tier one and tier four services.
“You’d be amazed at the number of times you find places where, let's say a tier two service has connections with an awful lot of tier three services that you didn't really realize were tier three services. And that combination in particular is pretty common. So, it gives visibility to these interactions that can affect availability and across teams... It's a way of labeling and understanding the importance of a service so you can apply processes to make sure that you're dealing with the interactions correctly.” he explains.
Challenges associated with MicroservicesWhile the benefits of microservices can be clearly surmised, there are still some challenges to be had with their implementation.
"With microservices, I can't be sure that all of those tasks I need to do to fulfill your request are living in the same space. They might be on another machine. They might be in another part of the company. They might actually be run by some third party that might be hosted in the cloud by a major vendor. So, now I have to design with the assumption that everything is far away, that everything is actually connected by some network requests and that network requests might even go down." Mike explains.
“So, while I make my services smaller, I'm actually increasing my network traffic, increasing my possible risks. And I have to design in that detail... So, understanding that change from monolith to microservice is really about managing the network and managing all the possible things that can go wrong. And that is something you design in your application.”
Managing a lot of microservices
While the general view is that microservices are the solution to address the complexities of microservices, they can also lead you “down the rat hole pretty quick”.
Deloitte Consulting Managing Director Mike Kavis says while microservices are great, “how do you manage 100 microservices especially if three teams are writing at the wrong level of granularity?”
“It can become a mess. I’ve seen spider grafts of microservices where it's like someone fell asleep drawing with a crayon. How do you manage all that? Microservices can create challenges too and they require new tools, processes, and new ways to monitor. You start getting things like AI ops. Humans can’t process 250 microservices running at the same time. We need to look at new ways of operations. There’s no easy ticket.” Kavis says.
He then advises how you don’t need more people to do microservices, as you’re delivering in small batches.
“You’re actually delivering more frequently and hopefully if you have an architectural vision you’re inheriting the work you did in the previous releases so you’re not creating from scratch all the time.”
The belief that adding microservices into your system will solve all your problems.
Making microservices the goal
They should be a means to an end, not the end itself. Organizations would also make the number of services created as a measuring stick to success.
Scattershot adoption
Teams building the architecture without any communication or coordination whatsoever.
Trying to fly before you can walk
Adopting a microservice architecture may be too technically challenging for those who haven’t mastered basic software development skills.
Focusing too much on technology
...and forgetting about key issues BEYOND the tools being used.
The more the merrier
Adding more and more microservices, which eventually creates a fine-grained architecture that could be hard to maintain.
Red flag law
Refusing to move on from development processes and structures used with monoliths.
V. Final Thoughts
Microservices closely follows the concept of Domain Driven Design, which means the architecture works by having bounded contexts or domains. Each individual service should then align to make your application work.
This architecture allows teams to scale a component at runtime independently. As such, the organization can plan and allocate resources to a particular segment of the application and make changes when needed.
Of course, one of the many challenges with this kind of infrastructure is when the number of microservices increases. Thus, it is imperative for the organization to plan ahead before taking on this kind of architecture. While the modular aspect of it can help decrease its complexity, things could get quickly out of hand especially with the increased number of deployed units and dependencies.
The bottom line is that the complexity of building an application won’t go away with microservices – it is just transformed or distributed – and this should still be managed and maintained.
Despite knowledge of these challenges however, developers across industries have increasingly embraced the benefits of microservices to speed up their development timelines and increase agility. They generally now have faster iteration cycles, the ability to utilize polyglot programming, and allow teams to take on new and better technologies quickly, rather than just waiting for the entire application to catch up.
Isaac Sacolick shares how to navigate a successful digital transformation in today’s business setting and the things that could set them up for failure as well.
Learn how to achieve true ROI by avoiding technical debt with Lonti's scalable, flexible, and maintainable low-code platform designed for long-term success.