Skip to main content

Nanoservices (Overly Fine-Grained Services)

Nanoservices over-decompose a system into trivially small services whose coordination and operational overhead dwarf any benefit. Right-size services around business capabilities using DDD bounded contexts, and merge services that change or call together.

Nanoservices are the result of taking microservices too far — decomposing a system into a swarm of services so small that each does almost nothing on its own. The cost of connecting, deploying, and operating them overwhelms the value of having split them.

Why It Happens

Teams over-apply the "small is good" heuristic, equating smaller with more microservice-y. Without a principled boundary (like a bounded context), "single responsibility" is misread as "one function per service." Sometimes it's resume-driven or trend-driven. The result is dozens or hundreds of services where a handful of well-sized ones would do.

Why It Hurts

Every service boundary adds cost: a network hop, serialization, separate deployment, monitoring, on-call, and failure modes. When services are tiny, that fixed overhead dominates the actual work they do. A single user action fans out into long chains of cross-service calls, multiplying latency and failure probability. Operational burden explodes — more pipelines, dashboards, and certificates than the team can manage. Changes that should be local now span many repos and deploys. Performance suffers from constant network and serialization overhead. The supposed agility of microservices turns into drag.

Warning Signs

  • Services that expose a single trivial function or wrap one table.
  • More code spent on glue, clients, and config than on logic.
  • One request triggers deep chains of inter-service calls.
  • The number of services far exceeds the team's ability to operate them.

Better Alternatives

Right-size services around business capabilities, not technical fragments. Use domain-driven design and bounded contexts to find boundaries that own a meaningful slice of behavior and data. Keep things that change together in the same service to minimize cross-service chatter. A modular monolith or coarser services is often the better default until scale or team structure truly demands finer splits.

How to Refactor Out of It

Map services to business capabilities and identify the trivially small ones. Merge nanoservices that always change or deploy together, or that sit on the same chatty call chain, into cohesive services aligned to bounded contexts. Eliminate hops that exist only to cross artificial boundaries. Establish a sizing principle — a service should own a capability and its data, be independently deployable, and justify its operational cost. Fewer, well-bounded services usually deliver the agility nanoservices promised but never gave.