All patterns
Foundational
Modular Monolith
One deployment with strict module boundaries
A single deployable artifact divided into well-bounded modules that communicate through explicit APIs, not shared database tables. A stepping stone before microservices.
Growth scalemedium complexity
Architecture diagram
High-level component relationships
Key components
Bounded modules
Each owns its models and public interface
Module APIs
Internal contracts — no direct cross-module DB access
Shared kernel
Cross-cutting auth, logging, config (minimal)
Schema separation
Logical DB boundaries even in one database
Data flow
- External request hits a module's public API
- Cross-module needs go through defined module interfaces
- Each module owns its persistence boundary
Pros
- Safer evolution than a big ball of mud monolith
- Single deploy and simpler ops than microservices
- Modules can later extract to services with less rewrite
- Transactions still possible within one process when needed
Cons
- Discipline required — boundaries erode without enforcement
- Still one scaling unit and one runtime failure blast radius
- Build times grow as modules accumulate
When to use
- Growing product that may need services later
- Multiple teams on one codebase
- You want DDD boundaries without Kubernetes complexity
When to avoid
- Tiny app where modules add ceremony
- Hard requirement for independent service scaling today
Real-world examples
- Shopify's modular evolution
- SaaS platforms pre-split
Related technologies
Java modulesNestJS feature modulesPackage-by-feature