Monolith to Services
Plumego is designed with a clear assumption:
Most systems start as a monolith — and should stay that way for a while.
This is not a limitation.
It is an architectural strategy.
This document explains how Plumego supports intentional growth from a single service to multiple services, without rewriting the system or abandoning core principles.
The Problem with Starting as Microservices
Many teams adopt microservices too early.
Common motivations include:
- Scalability concerns
- Organizational fashion
- Fear of future growth
- Tool-driven decisions
In practice, early microservice adoption often leads to:
- Distributed monoliths
- Increased operational complexity
- Fragile contracts
- Slower development
- Harder debugging
Plumego intentionally optimizes for clarity first, distribution later.
Plumego’s Default: A Structured Monolith
Plumego encourages starting with a well-layered monolith:
- Clear boundaries
- Explicit dependencies
- Stable domain and usecase layers
- Framework at the edge
This monolith is not a “ball of mud”.
It is a modular system that can be reasoned about locally.
Why a Well-Structured Monolith Scales Further Than You Think
A monolith with:
- Strong boundaries
- Proper dependency direction
- Isolated domain logic
Can support:
- Significant feature growth
- Multiple teams
- Independent development streams
Often, the bottleneck is not scale —
it is architecture discipline.
Plumego focuses on discipline first.
The Key Insight: Boundaries Come Before Services
Services are deployment boundaries, not architectural ones.
If boundaries are unclear in a monolith:
- They will not become clearer when distributed
- Network calls will replace function calls
- Complexity will increase, not decrease
Plumego emphasizes defining logical boundaries long before physical ones.
Preparing a Monolith for Future Splitting
A Plumego monolith is “service-ready” if:
- Domain logic is isolated
- Usecases are explicit
- Infrastructure is replaceable
- Dependencies point inward
- HTTP is only at the edge
When these conditions are met, splitting becomes mechanical, not conceptual.
What Actually Changes When You Split
When moving from monolith to services, less changes than expected.
What stays the same
- Domain models
- Usecase logic
- Error semantics
- Core invariants
What changes
- Deployment topology
- Communication mechanism
- Infrastructure wiring
Plumego’s architecture keeps these concerns separated.
Splitting by Capability, Not by Layer
A common mistake is splitting services by technical layer:
- One service for HTTP
- One for domain
- One for persistence
This almost always fails.
Instead, split by capability or business context.
Example:
- Order service
- User service
- Billing service
Each service contains its own:
- HTTP layer
- Application layer
- Domain layer
- Infrastructure adapters
This preserves internal coherence.
How Plumego Supports This Transition
Plumego helps by:
- Keeping the HTTP layer thin and isolated
- Avoiding global state
- Encouraging explicit input/output models
- Making application logic transport-agnostic
This allows:
- Replacing in-process calls with network calls
- Introducing RPC or messaging
- Keeping the core logic unchanged
Communication Between Services
Plumego does not prescribe a communication mechanism.
Options include:
- HTTP
- gRPC
- Message queues
- Event streams
The choice depends on:
- Consistency requirements
- Latency tolerance
- Organizational constraints
What matters is that communication replaces well-defined boundaries, not ad-hoc calls.
Avoiding the “Distributed Monolith”
A distributed monolith occurs when:
- Services are tightly coupled
- Changes require synchronized deployments
- Internal APIs mirror internal functions
Plumego’s emphasis on boundaries helps prevent this by:
- Forcing explicit contracts
- Encouraging independent evolution
- Making coupling visible
Organizational Alignment
Architecture reflects organization.
Plumego’s approach aligns well with:
- Small to medium teams
- Gradual team growth
- Clear ownership of capabilities
Splitting services too early often reflects organizational uncertainty, not technical need.
When to Actually Split
Consider splitting when:
- Teams are blocked by shared code ownership
- Independent scaling is required
- Failure isolation becomes critical
- Deployment frequency diverges across capabilities
Not because:
- “We might need it later”
- “Everyone else is doing microservices”
Plumego encourages evidence-based decisions.
Summary
Plumego’s approach to system growth is:
- Start with a disciplined monolith
- Define boundaries early
- Delay distribution
- Split by capability, not by layer
- Preserve core logic during transition
Microservices are a tool, not a goal.
Plumego helps you use that tool only when it actually solves a problem.
Next
With the Architecture section complete, you can move on to:
→ Guides — applying Plumego to real-world problems
→ Patterns — recommended, battle-tested ways of working
Both build directly on the architectural foundations you now understand.