Why microservices - part 4: the last third of the success triangle: architectural requirements for rapid, frequent, reliable and sustainable development

success triangle  

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:

  • Part 1 - the need to deliver software rapidly, frequently, and reliably
  • Part 2 - the need for sustainable development
  • Part 3 - two thirds of the success triangle - process and organization
  • Part 5 - the monolithic architecture

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 developer experience in a high-performance IT organization

The research by the authors of Accelerate found that developers in high performing IT organizations can:

  1. “… make large scale changes to the design of the system without having to depend on other teams to make changes or without creating work for those other teams …”
  2. ”.. complete their work without communicating and coordinating with people outside their team… ”
  3. “… do most of our testing without requiring an integrated environment …”
  4. “… deploy or release our application independently of other applications/services it depends on …”

Architectural requirements for rapid, frequent and reliable software development

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:

  • Loosely coupled and modular
  • Testable
  • Deployable

Let’s look at each of these attributes in turn and see why they are required.

Loosely coupled and modular

Consider the first two aspects of the developer experience:

  • “… make large scale changes to the design of the system without having to depend on other teams to make changes or without creating work for those other teams …”
  • ”.. complete their work without communicating and coordinating with people outside their team… ”

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.

Testable

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:

  • It must be straightforward to specify the intended behavior of the SUT (the System-under-test which is a fancy word for the thing you are testing)
  • The SUT must be testable in isolation especially it if has dependencies that would otherwise make testing more complicated
  • The tests should run on a developer’s laptop
  • The tests should execute quickly so that the lead time (time from commit to deploy and describe in part 1) is short
  • Once the tests pass you must be confident that the SUT is ready to be released to users

Deployable

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.

Architectural requirements for sustainable software delivery

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.

What’s next

The next article looks at the monolithic architecture and how well it meets these requirements.


success triangle  


Copyright © 2024 Chris Richardson • All rights reserved • Supported by Kong.

About Microservices.io

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.

Upcoming public workshops: Microservices and architecting for fast flow

In-person: Berlin and Milan

DevOps and Team topologies are vital for delivering the fast flow of changes that modern businesses need.

But they are insufficient. You also need an application architecture that supports fast, sustainable flow.

Learn more and register for one of my upcoming public workshops in November.

NEED HELP?

I help organizations improve agility and competitiveness through better software architecture.

Learn more about my consulting engagements, and training workshops.

LEARN about microservices

Chris offers numerous other resources for learning the microservice architecture.

Get the book: Microservices Patterns

Read Chris Richardson's book:

Example microservices applications

Want to see an example? Check out Chris Richardson's example applications. See code

Virtual bootcamp: Distributed data patterns in a microservice architecture

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 CCMHVSFB to sign up for $95 (valid until November 8th, 2024). There are deeper discounts for buying multiple seats.

Learn more

Learn how to create a service template and microservice chassis

Take a look at my Manning LiveProject that teaches you how to develop a service template and microservice chassis.

Signup for the newsletter


BUILD microservices

Ready to start using the microservice architecture?

Consulting services

Engage Chris to create a microservices adoption roadmap and help you define your microservice architecture,


The Eventuate platform

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.


Join the microservices google group