The Agile Echo

🌪️ What most people don't consider when discussing micro-services: DDD and Stream-aligned teams matter! 🤝

⚙️ Microservices are not just about creating smaller codebases. They are about creating independent, self-contained services that align seamlessly with your business's needs. The very famous debate around micro-services is most often discussed from a technical point of view; instead, we should first consider Bounded Context and our teams' organization structure.💡

Cover Image for 🌪️ What most people don't consider when discussing micro-services: DDD and Stream-aligned teams matter! 🤝
Dan the Dev
Dan the Dev

⏩ Introduction

At some point in the last decade, microservices have been considered game-changers in software architecture, and have taken the tech world by storm. Organizations worldwide transitioned from monolithic architectures to microservices, seeking benefits like improved scalability, agility, and maintainability. The allure of microservices lies in their promise to deliver independently deployable and highly specialized components, allowing teams to develop, deploy, and scale services with unprecedented flexibility.

But then, at some point, the realization that microservices also come with their own set of negative sides also spread out - and people recently started a new trend by suggesting to avoid microservices completely, or at least wait for when it actually makes sense.

The discussion about “when it makes sense” became finally important - which is great because every time we make a decision like that in software development, there is always a tradeoff somewhere - and discussing tradeoffs is the right thing to do because the most important thing is to pick conscious tradeoffs - not accidental ones.

So, let’s deep dive into the issue to understand why it’s important to take those aspects into consideration - before even discussing if and when splitting some services into microservices makes sense or not.

🧩 Know your business subdomains

Microservices are not just about creating smaller codebases. They are about creating independent, self-contained services that align seamlessly with your business's needs. Imagine your software system as a vast landscape, and microservices as the distinct territories within that landscape. Each territory (microservice) has its own rules, culture, and language.

What DDD suggests is that we can identify different territories in our company landscape - for example, in an e-commerce business we might identify Shop, Storage, and Shipping territories - and then each of those territories lives on its own, designing its own Product model containing only the subset of data they actually need.

Basically, we split the complexity of a very big and complex business into 3 different smaller businesses, the subdomains, dedicating their own specific smaller systems to each of them; the biggest advantage of this is that we can evolve what Storage needs without worrying about what Shipping needs, as soon as we support a standard communication way between the two territories.

A simple visual representation of the big Product table splitter into 3 services with different responsibilities.

If you are confident enough with the DDD Strategic approach, you probably noticed that this parallelism can be repeated for the organization subdomains: the entire company business is the landscape, and subdomains are the distinct territories within it.

The Shop, Storage, and Shipping I identified in the example - which is simplified but still meaningful - are nothing different than an implementation of 3 different bounded contexts.

Do you see the connection, now?

👨‍👩‍👦‍👦 Structure your teams accordingly

Thanks to subdomains, we now have a clear idea of which territories make sense to split our landscape - and if we follow subdomains, you can be sure that the isolation of those concepts will be a simplification compared to the hypothesis of keeping them all together.

But that is not enough: team structure is also important!

Imagine a group of explorers navigating through the territories of your landscape (microservices). Each explorer has a unique skill set and purpose. The success of your expedition depends on how well these explorers are organized and work together.

We absolutely want the explorers to be autonomous and not depend on anything else to achieve their goals so that they can get out of any issue without problems.

Imagine they are attacked by some animals and they need to fight to defend themselves - if they need to hide and wait for help, it will be a lot riskier and expensive to save them, while if they are able to at least fight for defend himself and run away, they can at least run away safely and then think to the next move.

In software development, we want stream-aligned teams (as suggested by Team Topologies): cross-functional teams focus on a single, impactful stream of work. It can be an entire product or service (the territory), or a single set of features/user journey/user persona (a portion of that territory). The team is empowered to build and deliver customer or user value as quickly, safely, and independently as possible, without requiring hand-offs to other teams to perform parts of the work - like analysis, release, monitoring, etc: the team covers all of them by itself.

👨‍👩‍👦‍👦 Put subdomains and stream-aligned teams together

Okay, so now we know the territories we have in our landscape, and we know that we want to have stream-aligned teams. What’s next?

It depends!

The smallest stream-aligned team I can think of in a standard software development context is made of 4 people:

  • Product Manager

  • UX Designer

  • Backend Developer

  • Frontend Developer

Let’s describe the ideal situation with a simple example.

Let’s say we have 2 territories in our landscape: on the team structure level, we will set up Team A, responsible for Territory 1, and Team B which will be responsible for Territory 2. On a microservices implementation level, we want to have at least 2 different microservices: Service 1 (for Territory 1) and Service 2 (for Territory 2), that will communicate with each other in an asynchronous way, without any dependency (Service 1 can work even if Service 2 is down, and vice-versa).

This microservices structure is not merely a technical decision, because it is widely impacted by our domain and subdomains - and we want to build a team structure that follows that subdomains.

Do you know why? Because Conway’s law exists!

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

On the contrary, when it comes to a specific subdomain, the decision to use microservices to split it into even smaller pieces it’s mostly technical and can be discussed by the team itself. For example, if Team A thinks that it’s worth isolating a piece of Service 1 for some reason, it’s totally up to them and should be invisible on the outside of that subdomain: autonomous teams, remember?

In conclusion, you need to know your domain and subdomain first, then consider your team and organize it according to the subdomains and the number of people in it - finally, you will prefer microservices at a subdomain level, to achieve independence for the team, and let each team decide whether an even smaller split is needed within their subdomain, for technical reasons.

Until next time, happy coding! 🤓👩‍💻👨‍💻

Dan’s take 🙋🏻‍♂️

Every time I come into a microservices discussion, I feel like some topics are missing or very underestimated: of course, when thinking about microservices, is fine to think of possible cons like HTTP requests due to network, data consistency, or global testing, etc. But before getting to those technical decisions, we need to face organizational and team structural problems, related to the Domain-Driven Design Strategic approach, and Team Topologies concepts like Stream-Aligned teams.

In the past, we were used to building a single software system to serve the entire company's needs: typically, this big monolith becomes a mess, with tables that contain a gigantic number of columns because “hey, in the Product model we need all the info to be able to show and sell the product, add it to a cart, but also all the pieces of information about storage, shipping, etc”.

Moving on with our explorer parallelism, in the old days we tried to explore the entire landscape by organizing our people by skills: we could have an Explorers team, Technician team, and Farmers team, for example. Each team organizes its work by itself, and when one needs something from another, send a request and wait for the response when possible.

With stream-aligned teams, instead, we create a single team with all the skills: if we try to do this for the entire landscape, we come up with a very big team containing all the Explorers, Technician and Farmers we have - the problem with that is that is just too much people, and due to how communication works we would be too slow - that’s why we add DDD subdomains to the equation and split people into multiple cross-functional teams, at least one for each territory (subdomain) we identify.

A simple visual representation of cross-functional explorers teasms in different landscape.

I know some of you might think that not the situations are the same - typically, we can think of the explorer mission in two different ways in software development (mainly):

  1. If we are a consultancy company, we probably work by the project: this means our explorers will have an exploration that has a target (a scope and a time frame, typically) - we need to take the best outcomes for that scope in that time frame for our customers, like if someone pays us to send our explorers to get some food in the forest

  2. If we work in a product company, it’s like the explorers are in a neverending exploration of the territory we assigned them, and they keep exploring it to get the most (money) out of it in all the different ways we can find according to our skills (business models)

While consultancy contexts are typically harder, especially from the scope and time point of view, it would still be a good idea to set up the organization by stream-aligned team - it could be one team for the project, for example. The fact that a project typically has an end date has no impact on this.

To conclude my thoughts, there are a couple of typical patterns that I want to highlight from the ideal situation described above:

What if we do have not enough people to build multiple teams?

Then you already have a decision about microservices at a subdomain level: keep everything together. Build modular monolith microservices, where every subdomain is easily identifiable, so that code is more maintainable even if all together and it’s ready to be spliced out whenever the time comes. Every microservices split here is mostly technical because splitting in microservices for each subdomain would be a useless overhead for a single team.

What if we discover that Territory 1 could contain another subdomain?

This probably means you discovered a new possible income stream for the company, which is great! While things are still small, nothing needs to change: Team A can work on both. Once the two streams are big enough, and the workload is too big for a single team, you can add a second team to that Territory: at first, you might want to make both teams work on the entire Territory on both streams (two teams sharing the backlog), then, once the second stream is big enough to be on its own, you can even think to split it into two different territories to ensure their independency.

When cognitive load isn’t considered, teams are spread thin trying to cover an excessive amount of responsibilities and domains. Such a team lacks the bandwidth to pursue mastery of their trade and struggles with the costs of switching contexts.

[Matthew Skelton, Team Topologies]

Go Deeper 🔎

📚 Books

  • Domain-Driven Design and Microservices - Domain-Driven Design (DDD) concept was introduced by first Eric Evans in 2003. The concept of microservices did not exist at that time. So basically DDD was introduced to solve the problem of a large monolithic code base. This book explores the two topics together.

  • Implementing Domain-Driven Design - Implementing Domain-Driven Design presents a top-down approach to understanding domain-driven design (DDD) in a way that fluently connects strategic patterns to fundamental tactical programming tools. Vaughn Vernon couples guided approaches to implementation with modern architectures, highlighting the importance and value of focusing on the business domain while balancing technical considerations.

  • Team Topologies - In Team Topologies IT consultants Matthew Skelton and Manuel Pais share secrets of successful team patterns and interactions for IT through four fundamental team topologies and three interaction modes.

📩 Newsletter issues

📄 Blog posts

🎙️ Podcast episodes

👨🏻‍🏫 Online courses

Did you enjoy this post?

Express your appreciations!

Join our Telegram channel and leave a comment!Support Learn Agile Practices

Also, if you liked this post, you will likely enjoy the other free content we offer! Discover it here: