This is part 4 in a series of blog posts about why and when to use the microservice architecture. Other posts in the series are:
In this post, I discuss the final third of the software development success triangle: architecture. Let’s start by looking the day to day life of a developer in a high-performance IT organization.
The research by the authors of Accelerate found that developers in high performing IT organizations can:
If you analyze these aspects of the developer experience, you will discover that a high-performing IT organization needs an architecture with the following quality attributes:
Let’s look at each of these attributes in turn and see why they are required.
Consider the first two aspects of the developer experience:
On the one hand, having a cross-functional team eliminates some types of coordination. For example, developers no longer have to coordinate with QA or operations. But on the other hand, Conway’s law states that an architecture mirrors the organization that creates it. A loosely coupled organization requires a loosely coupled, modular architecture.
A developer must be able to develop and test their module without regularly requiring other modules owned by other teams to be changed in lock step. A module’s interface should be designed so that it encapsulates (i.e. hides) the module’s implementation. That’s because, decisions that are hidden behind the interface can be changed without affecting other modules. Of course, not all changes can be hidden but it’s a design smell if a module’s interface is unstable.
Moreover, developers should use principles such as DRY/SOCs and the Common Closure Principle to design modules so that they do not share concepts. For example, let’s imagine that a business rule was implemented by multiple different modules. If that business rule changed then those modules would need to be changed in lockstep even though there were no interface changes. To prevent this problem, a business rule should be implemented by a single module. Also, business rules that often change together should also be implemented by a single module.
The third aspect of the developer experience is “We can do most of our testing without requiring an integrated environment” The ability to test locally requires an architecture that is testable. There are several different aspects to testability:
The fourth and final aspect of the developer experience is “We can and do deploy or release our application independently of other applications/services it depends on.” The ability to deploy locally requires an architecture that is deployable. There are several different aspects to deployability: First, the architecture must support frequent and reliable deployments. As I described in part 1, high-performance IT organizations deploy many times a day into production with very few outages.
Second, the architecture must enable a team to deploy and release their changes independently of the other teams. Once a module’s tests pass, a team must able to deploy and release that module without any kind of planning or coordination with other teams. Moreover, they need to be confident that it will continue to work in production.
Now that you have seen that rapid, frequent and reliable delivery requires a loosely coupled modular architecture that’s testable and deployable, let’s now look at the architectural requirements for sustainable development.
As I described in part 2, sustainable development requires you to regularly upgrade your application’s technology stack. You must replace technologies that are destined for obsolescence with newer technologies. Replacing a library that is used by one module is relatively easy. However, many needed upgrades are potentially global in scope. Over the lifetime of a long-lived application you might, for example, need to change the language, the database, or the application framework.
For example, let’s imagine that around 2007, you had picked Ruby on Rails because it appeared to be competing effectively against Java. Today, you might want to migrate to Rust. The problem is, is that a big bang (total) rewrite of a large application to replace Ruby with Rust would be a massive undertaking. It would not deliver any value until the rewrite was completed. As a result, this kind of rewrite is rarely done and instead organizations choose to continue with an increasingly obsolete technology until it becomes an emergency.
What’s needed is an architecture that lets you incrementally upgrade your application’s technology stack. This concept builds on the idea of modularity that was described earlier. The difference is, however, that a module’s interface must also encapsulate decisions that are traditionally global, such as its language, database, or application framework. Once each module’s technology stack is hidden by the interface, you can upgrade an application’s technology stack one module at a time.
The next article looks at the monolithic architecture and how well it meets these requirements.
Microservices.io is brought to you by Chris Richardson. Experienced software architect, author of POJOs in Action, the creator of the original CloudFoundry.com, and the author of Microservices patterns.
Take a look at my Manning LiveProject that teaches you how to develop a service template and microservice chassis.
My virtual bootcamp, distributed data patterns in a microservice architecture, is now open for enrollment!
It covers the key distributed data management patterns including Saga, API Composition, and CQRS.
It consists of video lectures, code labs, and a weekly ask-me-anything video conference repeated in multiple timezones.
The regular price is $395/person but use coupon JUNVCEJE to sign up for $195 (valid until February 1st, 2023). There are deeper discounts for buying multiple seats.
Chris offers numerous resources for learning the microservice architecture.
Chris teaches comprehensive workshops, training classes and bootcamps for executives, architects and developers to help your organization use microservices effectively.
Avoid the pitfalls of adopting microservices and learn essential topics, such as service decomposition and design and how to refactor a monolith to microservices.
Delivered in-person and remotely.
Want to see an example? Check out Chris Richardson's example applications. See code
Engage Chris to create a microservices adoption roadmap and help you define your microservice architecture,
Use the Eventuate.io platform to tackle distributed data management challenges in your microservices architecture.
Eventuate is Chris's latest startup. It makes it easy to use the Saga pattern to manage transactions and the CQRS pattern to implement queries.
Note: tagging is work-in-process
anti-patterns · application api · application architecture · architecting · architecture documentation · dark energy and dark matter · deployment · development · devops · docker · implementing commands · implementing queries · inter-service communication · loose coupling · microservice architecture · microservice chassis · microservices adoption · microservicesio updates · multi-architecture docker images · observability · pattern · refactoring to microservices · resilience · sagas · security · service api · service collaboration · service design · service discovery · service granularity · service template · software delivery metrics · success triangle · team topologies · transaction management · transactional messaging