Docs Monolith to Services

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.