It’s almost accepted wisdom that Microservice architectures are universally good. Non-microservice architectures are seen as being Monolithic and exhibiting (among other things):
- A lack of agility
- Hidden complexity due to opaque design and tight coupling
- Uncertainty when estimating time and costs associated with change.
This leads organisations to fear investing in change and consequently inhibits innovation – a key business differentiator in today’s digital age.
What IS the BJSS view on Monoliths and Microservices?
We learn at pace about technologies and trends by being at the coal face of large-scale deliveries. Any opportunity to plumb the depths of BJSS's practitioners’ real-world experience is worth taking.
So we asked.
We talked with our technical people across a range of different roles; platform engineers, developers, testers and architects. We interviewed those from infrastructure and sysadmin backgrounds as well as those with a background in software engineering.
The answer turned out to be a familiar one. As is often the case, the journey to the answer proved far more valuable.
Many areas of technology and IT overload phrases and concepts, so let’s briefly describe what we mean when discussing Monoliths and Microservices.
A Monolithic application is characterised by a single, often large code base which provides all the functionality in a single tier encompassing: User Interfaces, Business Logic, Data Access and cross-cutting concerns such as Logging and Security.
Microservices in contrast represent a very different approach. A Microservice architecture decomposes the problem into a number of independent, appropriately sized, discrete services. Crucially the services can be developed, tested and deployed independently.
Monolith: The Verdict
The archetypal monolith encompasses a raft of areas of responsibility, covering all user journeys and use cases. New functionality is often bolted on over time, sometimes complementing the initial design and other times in-spite of it.
“Monoliths are generally bad - they become too large and unwieldy, but things don't usually start with the intention of being monoliths.”
Considering just three of the 'ilities:
Responsibility: Monoliths by definition represent an aggregation of all the things an application or system needs to do. By their nature therefore, they are responsible for a potentially large and varied number of actions. This leads to a proliferation of exposed interfaces, interdependencies and consequently poor separation of concerns.
Maintainability: Monoliths often evolve over time (years). With new functionality being introduced, the code base continues to expand with inconsistent adherence to coding standards. Code duplication rather than re-use is common, and the testability of solutions becomes increasingly difficult. Tight coupling between constituent parts of a monolith result in changes to one component affecting seemingly unconnected components (temporal coupling).
Deployability: Deploying updates to a monolith requires the full application to be rebuilt, retested and deployed. This is a daunting task in many cases, frequently compounded by a lack of a robust and comprehensive CI/CD pipeline. Regression test suites (if they exist) are too time consuming to support a ‘fail-fast’ methodology all of which contributes to undesirably long Cycle and Lead times.
However, for those having first-hand experience of the alternatives it’s clear Monoliths can still have their place.
“I think monoliths are misunderstood and not always bad."
"Don’t solve bad engineering with bad architecture.”
Experience has taught us that it’s not Monoliths that are the real problem, rather how they have been architected.
A well-architected solution need not be microservice-based. A well-built application, adopting good software design and development methodologies can form the basis of a solution that offers many of the purported advantages of microservices.
“Dogma does not beat good design – or rather, it shouldn’t.”
The backlash against Monoliths has been driven in part by organisations suffering from failed IT projects, delays and cost overruns. Microservices have become the de-facto solution in many places.
This dogmatic approach masks the underlying issue which is often one of insufficient software architectural oversight when scoping and designing systems. Blindly adopting Microservice architectures will not address the issues Monoliths are perceived to cause, and if executed poorly could well result in an even more problematic solution.
Microservices: The Verdict
"Microservices are a design principle for creating distributed, highly scalable, easily extendable systems.”
“Loose coupling between services allows services to be independently developed, maintained, and scaled with minimal impact.”
Looking at the same ‘ilities as before, this time from the perspective of Microservices:
Responsibility: Architecture is comprised of a number of independent small services, each having a single responsibility, areas of concern are readily isolated by design and dependencies are abstracted from the implementation.
Maintainability: A service’s code base is relatively small and focussed on a single domain. This yields more tractable code which is easier to PR and well suited to analysis tools providing actionable insights. Coding standards are easier to adopt, and re-use is encouraged through use of other loosely coupled services.
Deployability: Microservices are typified by incremental, small, fast, independent deployments, orchestrated by solid DevOps principles delivered by CI/CD pipelines. Regression tests run in a timely fashion supporting a ‘fail-fast’ way of working and allow for short Cycle and Lead times.
The word Monolith has become a shorthand for large intractable systems consumed with technical debt. However, BJSS has been working with Microservice architectures for long enough to understand that a Microservice architecture can have a cost.
"Microservices do not reduce complexity, they just move the complexity elsewhere.”
That cost manifests itself as solution complexity. The theme of complexity was a common one in our research and covers such aspects as: service interdependency, transactional operations, service version approaches, security and local development.
“Most projects are not Netflix or Amazon and do not have their requirements.”
Is that additional complexity worth it? Well that depends on the problem in hand. Netflix and Amazon are both renowned for their advocacy and adoption of Microservice architectures, but as the quote suggests, few projects have similar requirements to theirs, so with that in mind:
“Microservices should not be the default answer.”
Microservices introduce complexity, however they have potential to provide an architecture that enables a business to respond to change quickly and safely. If agility and innovation are key, then microservices may well be the ideal fit if you’re able to amortize the cost of the complexity over the lifetime of a project.
Microservice architectures can provide advantages, however realising those advantages comes at the cost of increased solution complexity. Many projects, particularly those deployed into change-heavy organisations repay the costs many times over, making the investment justified and essential.
Key is understanding the problem to be solved and architecting the necessary and sufficient solution. Delivering an elegantly architected microservices-based solution nine months after the competition has acquired a majority share of a new market is folly.
Monolith vs Microservice? On reflection it’s not really the right question, the answer however is: It doesn’t matter what you call it, architect the right solution, one that meets the client’s needs and do not be driven by architectural hype, fads and dogma.
“Architectural and software engineering purism just burns money.”
Listen to the podcast...
In this first episode of the BJSS Deployed Podcast, Lee Crossley and John Gill discuss the pros and cons of monolithic vs microservices architectures based on experiences gained on a range of recent engagements.