Hello! Welcome to the first lesson of our new module on microservices. In the previous module, we explored the crucial machinery of asynchronous systems—message queues, distributed logs, and the delivery guarantees they provide. You now have a solid grasp of the building blocks for reliable communication between services.
Today, we take a step back from the implementation details to answer a more fundamental architectural question: when you decide to break a large application apart, where do you draw the lines? This is arguably the most critical decision in a microservices architecture. Getting it right sets you up for success; getting it wrong can lead to a "distributed monolith," which has all the complexity of microservices with none of the benefits.
Our goal is to learn how to identify domain boundaries to conceptually decompose a monolithic application into what are known as bounded contexts. This skill is central to modern system design and a key topic in senior engineering interviews. Given your experience architecting systems for smaller businesses, you're likely familiar with the pressures that drive this kind of decomposition, and this lesson will give you a strategic framework to manage it.
1. The Monolith's Breaking Point
For many projects, especially at the start, a monolithic architecture is the right choice. It's straightforward to develop, test, and deploy. However, as an application and the team working on it grow, this simplicity can turn into a significant liability.
The article "Microservice Decomposition Strategies" captures this transition perfectly.
Microservice Decomposition Strategies - by valuein
This article provides an excellent overview of the strategic thinking behind breaking up a monolith.
Please read the opening section, When Your Monolith Becomes a Liability. It paints a very relatable picture of the challenges that emerge at scale.
As the article highlights, the problems are multifaceted:
- Slow Deployments: A small change requires redeploying the entire application, leading to long, risky deployment cycles.
- Team Friction: Different teams working on different features can block each other, as all their work is coupled in a single codebase.
- Lack of Resilience: A failure in one non-critical module (like analytics) can bring down the entire system.
- Scaling Inefficiency: You must scale the entire application, even if only one small part is under heavy load.
A crucial insight, especially for a team lead, is that the primary driver for moving to microservices is often not just user scale, but team scale.
Moving from MONOLITHS to MICROSERVICES 🎂 → 🍰🍰🍰
In his video "Moving from MONOLITHS to MICROSERVICES," Gaurav Sen explains the key trigger for this architectural shift.
Watch the short segment from this clip where he discusses when to make the move. The key takeaway is that you do it when your team has scaled and needs to move independently.
When your architecture starts to hinder your team's ability to deliver value, it's time to consider decomposition. But how do you do it?
2. Finding the Seams: Domain-Driven Design
The most effective strategy for decomposing a monolith is rooted in Domain-Driven Design (DDD). DDD is an approach to software development that centers on the business domain. Instead of thinking first about databases, frameworks, or servers, you think about the business itself—its processes, rules, and language.
The core concept from DDD that we will use is the Bounded Context.
From Monolith to Microservices: A DDD Approach for a Wellness App
This article provides a fantastic, practical guide to using DDD for microservice decomposition.
Read the section that defines Domain-Driven Design, paying close attention to the definition of a Bounded Context. You'll find it in the blue quote box, from Key Definition.
As the text states, a Bounded Context is a conceptual boundary within which a specific domain model and language are consistent and well-defined. Crucially, in a microservices architecture, a bounded context maps directly to a service boundary. Each microservice owns one bounded context.
This idea is powerful because it stops you from breaking up your system along technical lines (e.g., a "UI service," a "database service," a "logic service") and pushes you to break it up along business lines.
A classic example is the concept of a "Customer."
- In the Sales context, a Customer is someone with a sales pipeline, potential value, and associated opportunities.
- In the Support context, a Customer is someone with support tickets, service level agreements (SLAs), and a history of reported issues.
These are two different models of the same real-world entity. Trying to force them into a single, all-encompassing Customer object in a monolith leads to complexity and confusion. Recognizing them as distinct models within separate bounded contexts is the key to clean decomposition.

3. Strategies for Identifying Bounded Contexts
Identifying bounded contexts is more of an art than a science, but there are several practical strategies you can use.
Decompose by Business Capability
This is often the most intuitive starting point. Think about what your business does, not how it does it. A typical e-commerce application has several clear business capabilities:
- Product Catalog Management
- Inventory Management
- Shopping Cart & Ordering
- Payment Processing
- Shipping & Fulfillment
- User Account Management
Each of these is a strong candidate for a bounded context and, therefore, a microservice.
Decompose by Subdomain
DDD further refines this by categorizing parts of the business domain:
- Core Domain: The part of your business that is your key competitive advantage. This is where you should invest the most custom development effort. For Amazon, this might be its recommendation engine and logistics.
- Supporting Subdomain: Necessary for the business to function but not a competitive differentiator (e.g., invoicing in an e-commerce store).
- Generic Subdomain: A problem that is already solved and can often be bought off-the-shelf (e.g., sending emails, authentication).
This categorization helps you decide where to focus your resources. You build your core, might build or buy your supporting, and almost always buy or use an open-source solution for your generic subdomains.
Microservice Decomposition Strategies - by valuein
Let's return to the "Microservice Decomposition Strategies" article for a formal definition of these approaches.
Read the two paragraphs defining these strategies.
The following diagram illustrates this process beautifully, showing how a monolithic architecture's high-level functions are broken down first into bounded contexts, which are then implemented as one or more microservices.

Look for Transactional Boundaries
This is a potent technical signal. In the previous module, we discussed the challenges of distributed systems. If you find that to complete a single business operation you need a complex, distributed transaction (like a saga) across multiple proposed services, it’s a red flag that your service boundaries might be wrong. A well-defined bounded context should be able to handle most of its core operations atomically, within its own boundary.
4. Incremental Migration: The Strangler Fig Pattern
Decomposing a monolith is not a "big bang" rewrite. That approach is famously risky and often fails. A much safer, more pragmatic approach is to do it incrementally. The most well-known strategy for this is the Strangler Fig Pattern.
Sam Newman, a leading expert on microservices, provides a clear explanation of this pattern.
Monolith Decomposition Patterns • Sam Newman • GOTO 2019
In this clip from his talk "Monolith Decomposition Patterns," Sam Newman explains the Strangler Fig pattern.
Watch the segment from his explanation of the pattern's origin and concept. The core idea is to wrap new functionality around the old system, intercepting calls and diverting them.
The process works like this:
- Identify a bounded context within the monolith you want to extract (e.g., Payment Processing).
- Build a new, independent microservice for this functionality.
- Place a proxy or API Gateway in front of the monolith. Initially, it just passes all traffic through to the monolith.
- Configure the proxy to intercept calls related to the new functionality (e.g.,
/api/payments) and route them to your new microservice instead of the monolith. - Once the new service is stable and handling traffic, you can begin to remove the old payment code from the monolith.
- Repeat this process for the next bounded context. Over time, the new services "strangle" the old monolith until it can be retired.
This approach allows you to migrate gradually, reduce risk, and continue delivering value to customers throughout the process.
Conclusion
Today, you've learned the strategic framework for the most critical first step in a microservices journey. You've moved beyond the technical implementation of individual components to the architectural vision that guides how they fit together.
Key Takeaways:
- The move from monolith to microservices is primarily driven by the need to scale your team and increase development velocity and resilience.
- Domain-Driven Design (DDD) provides the intellectual toolkit for decomposition.
- The Bounded Context is the central concept: a boundary within which a business model is consistent. Bounded Contexts are the ideal candidates for your microservices.
- You can identify these contexts by decomposing along business capabilities, analyzing subdomains (core, supporting, generic), and respecting natural transactional boundaries.
- The Strangler Fig Pattern is a proven, incremental strategy for migrating from a monolith to microservices while minimizing risk.
You now have a solid conceptual foundation for designing a microservices architecture. In our next lesson, we will get more technical and compare the different ways these newly defined services can communicate with each other, focusing on the trade-offs between REST, GraphQL, and gRPC.