Decomposition and Boundaries
Architecture defines components and their relationships. The fundamental question — where do the boundaries between components go? — sits at the heart of every architectural decision.
Software decomposition is the process of breaking complex systems into smaller, more manageable pieces. It’s the act of drawing the lines that separate one responsibility from another, and it applies to every architectural style: monolith, modular monolith, microservices, micro-frontends. The principles are the same. In a distributed system the boundaries get enforced naturally by the network — for a monolith, you have to enforce them with discipline.
Forces That Shape Boundaries
When deciding how to decompose, architects weigh several forces that often pull in different directions. Good decomposition acknowledges all of them and trades off consciously.
Domain functionality — the business-shaped boundary
The strongest single force is the business domain itself. Domain-Driven Design teaches that the problem space — the actual business reality you’re modeling — should drive the decomposition of the solution space. We’ll go much deeper on DDD in a later section; for now, the headline is: business-shaped boundaries are usually the most stable.
Take an e-commerce platform. Domain analysis surfaces these business capabilities, which suggest natural service boundaries:
Each is a coherent business capability that can be owned by a team and shipped as a component or service. Aligning architectural boundaries with these natural business boundaries gives you systems that are easier for non-engineers to discuss and easier for engineering teams to evolve.
Quality attributes — the non-functional pull
Performance, security, availability, scalability, maintainability — quality attributes routinely pull boundaries in directions the domain wouldn’t on its own.
Consider a social network where the domain model suggests separating “user profiles” from “user activity” into different bounded contexts. Performance requirements may push you the other way: co-locate them in one service so you can render the news feed without an expensive cross-service call. Or take a financial trading system — domain logic might keep “Trading” as a single context, but security requires splitting order entry, risk validation, and trade execution into separate services with hard boundaries.
A working list of how quality attributes pull boundaries:
| Attribute | Definition | Pull on decomposition |
|---|---|---|
| Performance | Response time, throughput | Larger components to avoid network hops; co-locate hot paths |
| Scalability | Handle increased load | Finer decomposition for independent scaling |
| Security | Protection against threats | Extra boundaries for access control; isolate sensitive data |
| Availability | Uptime and fault tolerance | Isolate critical from non-critical; redundancy boundaries |
| Maintainability | Ease of modification | Clear stable interfaces; separation of concerns |
| Deployability | Ease of releasing changes | Independent deployable units, aligned with change cadence |
Technical and organizational constraints
Real systems have to live with deployment environments, legacy systems, platform limits, and technology choices. And then there’s Conway’s Law: “organizations that design systems are constrained to produce designs that are copies of those organizations’ communication structures.” Team structure, communication patterns, skills, and ownership shape system evolution whether you plan for it or not.
Other factors
Guiding Principles
The forces above tell you what to consider. The principles below help you evaluate whether you got it right.
High cohesion, low coupling
This principle, first articulated by Larry Constantine in the 1970s, is still the cornerstone of good decomposition. It applies at every level — function, class, module, service, system.
Cohesion types, best to worst:
- Functional — elements perform one well-defined task. Best.
- Data — elements work on the same data structures. Good.
- Change — elements that change for the same reasons. Good.
- Temporal — elements accessed or changed at the same time. Weak; usually a missing abstraction.
Coupling types, best to worst:
- Data — components exchange only simple data. Best.
- Contract — components exchange data structures. Acceptable; common in well-designed APIs.
- Control — one component controls another’s flow. Problematic.
- Content — one component reaches into another’s internals. Worst.
The dependency rule
Higher-level entities — core business rules — should not depend on lower-level details like databases, frameworks, or external APIs. Clean Architecture’s load-bearing principle: keep business logic stable while implementation details are free to evolve.
In practice:
- Business entities don’t depend on databases.
- Use cases don’t depend on UI frameworks.
- Core domain logic doesn’t depend on external services.
Hexagonal architecture is the canonical visualization: business logic in the center, surrounded by ports/adapters that handle external concerns.

Information hiding
Well-designed boundaries expose only what consumers actually need, hiding implementation details behind stable interfaces. David Parnas formalized this in the 1970s. Information hiding:
Good interfaces are minimal, stable, and shaped by consumer needs — not by what was convenient on the implementation side.
Common Anti-patterns
Boundaries Have to Evolve
Initial decomposition decisions are rarely perfect. Domain understanding deepens, team structure shifts, performance needs change, new technologies appear. Systems that can’t evolve their boundaries calcify and eventually get rewritten.
Design for observability of boundaries:
Closing the Loop
Drawing boundaries is part analysis, part craft. The most successful architects know there’s no single perfect decomposition — only a decomposition that fits the current context, constraints, and goals.
When you’re choosing boundaries, the test is whether they make future change easier or harder. Start simple, learn from real use, and evolve boundaries as your understanding grows. The architectures that last longest are the ones that can adapt their boundaries while keeping their identity.
Recap
- Decomposition is where the lines go, and every architectural decision is some version of that question.
- Domain boundaries are usually the most stable; quality, technical, and organizational forces pull them in other directions.
- High cohesion, low coupling — Constantine’s principle — is still the rubric for evaluating any boundary.
- The dependency rule keeps business logic stable as implementation details change.
- Information hiding is what makes large systems manageable; design interfaces from the consumer’s side.
- Watch for distributed monoliths, anemic components, god components, duplicated cross-cutting concerns, and premature decomposition.
- Boundaries have to evolve. Architecture tests, observability, and gradual migration patterns let them.