skip to content

Service Granularity & Sizing

Right-sizing services, since too small produces chatty call chains and too large recreates the monolith. You will learn the cohesion and coupling forces at play, smells such as entity services, and how granularity should be refactored over time rather than fixed up front.

part ofMicroservices architectureoverview, primer and where to startread it →
on this pageshow

questions

6

What is a 'nanoservice' anti-pattern, and why is a service that's too small often worse than a monolith?

level: juniorimportance: must knowfreq 70%

answer

  1. fixed cost per service
  2. distributed monolith
  3. SRP misapplied to deployment unit
  4. capability not verb
  5. operational tax > logic value

basics

~20 s

A nanoservice is a service split so small (like one endpoint) that it does barely any real work but still pays the full cost of being a separate service - network calls, its own database, deployment pipeline, on-call rotation. That overhead usually costs more than it saves.

solid answer

~30 s

Nanoservicing is when a team decomposes past the point where the service still owns a meaningful piece of business capability - e.g., a 'GetUserEmail' service with a single endpoint and no real logic. Every service, regardless of size, carries fixed overhead: its own deployment pipeline, health checks, logging/monitoring setup, network hop with latency and failure modes, versioning, and on-call burden. When the unit of work inside the service is tiny, that overhead dominates the total cost, and you end up with a 'distributed monolith' that's harder to operate than the monolith it replaced, without any of the independent-scaling or fault-isolation benefits.

go deeper

for a junior

Should recognize that 'more services = better' is false and give the basic intuition that each service has real operational cost, even without naming specific failure modes.

for a middle

Should name concrete fixed costs (deploy pipeline, monitoring, network hop) and connect nanoservicing to chatty communication and the need for distributed transactions.

for a senior

Should give a clear heuristic for right-sizing (bounded context / change-together test) and be able to spot nanoservicing in a real service diagram, proposing a concrete merge.

for a principal

Should discuss how nanoservicing interacts with org design (Conway's Law), cloud cost, and propose a governance mechanism (architecture review, service creation checklist) to prevent it recurring across many teams.

## What nanoservicing is A microservice architecture decomposes a system into independently deployable units, each ideally owning one bounded, cohesive slice of business capability along with its own data store. **Nanoservicing** is what happens when a team pushes this decomposition too far, splitting services along technical lines (a single endpoint, a single database column, a single CRUD verb) rather than along capability lines. A textbook example is splitting a 'User' domain into separate services for `CreateUser`, `UpdateUserEmail`, `UpdateUserAddress`, and `DeleteUser` — each with its own repository, deployment pipeline, and a slice of the same underlying table — when in reality these operations are one cohesive 'manage user profile' capability that a single team owns and that almost always changes together. ## Where it comes from Nanoservicing usually emerges from good intentions taken past their useful range. - The **Single Responsibility Principle**, correctly applied at the class or module level, gets misapplied at the deployment-unit level as 'each service should do exactly one thing,' and 'one thing' gets interpreted as 'one function call' instead of 'one business capability.' - It's also a reaction to **monolith pain** (long build times, tangled ownership, fear of touching shared code) and to **conference-driven development** that equates 'more services' with 'more modern.' - Teams new to microservices often lack a felt sense of the **fixed operational cost** every service carries, so they don't see the tax they're signing up for. ## The fixed overhead every service pays Every service — no matter how small — pays a fixed overhead: - its own **CI/CD pipeline** - its own **container image** and base-image patching - its own **health checks**, dashboards and alerts - its own **on-call runbook** - its own **versioning** and backward-compatibility contract - at least one **network hop** to reach it (with associated latency, timeout tuning, retry policy and circuit breaker) When the unit of business logic inside the service is tiny — one field update — that fixed cost dwarfs the value delivered. You get more services to patch for CVEs, more pipelines to keep green, more dashboards nobody looks at, and a request that used to be one in-process function call becomes a network round trip with its own failure modes. The promised benefits of microservices — independent scaling, independent deployability, fault isolation — rarely materialize at this granularity because these tiny services are so tightly coupled in their data and lifecycle that they must be deployed and reasoned about together anyway; you've paid for distribution without buying the isolation it's supposed to buy. ## Production symptoms - **Chatty inter-service communication** is the most visible production symptom: a single user action (e.g., 'update my profile') now requires the caller (a BFF, gateway, or another service) to orchestrate calls to four or five nanoservices, and if any one call fails partway through, you need compensating logic to undo the ones that already succeeded — essentially hand-rolling a distributed transaction (a saga) for something that used to be one local ACID transaction. - **On-call load spikes because incidents multiply**: an outage in 'UpdateUserEmail' doesn't just break email updates, it breaks every workflow depending on the chain of calls leading to it, and diagnosing this requires distributed tracing across many hops instead of reading one stack trace. - **Deploy coordination gets worse, not better**: because these services are so entangled, changing 'user' behavior often requires touching several nanoservices in lockstep, so the 'independent deployability' that justified splitting them in the first place doesn't hold. ## The corrective heuristic This pattern is documented widely enough to have a name — 'nanoservices' or the 'distributed monolith' antipattern — and practitioner accounts (echoing Sam Newman's writing in 'Building Microservices,' which shaped much of the mainstream vocabulary around service granularity) describe teams merging a dozen single-purpose services back into two or three cohesive services once the operational tax became visible in cloud bills, on-call fatigue, and slowed feature delivery. The corrective heuristic is to size a service around a bounded context or business capability — something that: 1. a small team can own end-to-end 2. changes for one reason 3. is large enough to amortize its fixed operational cost against real business value delivered

  • How would you decide whether two candidate services should actually be merged into one?
    Look at whether they change for the same reason and are usually deployed together - if 90% of changes to service A require a coordinated change to service B, they belong in one deployable unit. Also check data ownership: if they need each other's tables to do their job, that's a strong signal they're one bounded context artificially split. Finally, look at team ownership - if one team maintains both, splitting them buys no organizational independence, only operational cost.
  • Does 'one team, one service' mean a team should never own more than one service?
    No - a single team commonly owns several services if those services represent genuinely separate bounded contexts with different data and change cadences, e.g., a platform team owning both 'notifications' and 'audit-logging.' The rule is about avoiding services so fine-grained that a single business capability is fragmented across owners or coupled at the data layer, not about capping services per team.
  • Can nanoservicing ever be the right call?
    Rarely, but it can make sense for a capability with genuinely independent scaling needs and infrequent, isolated changes - e.g., a thumbnail-generation service invoked by many unrelated systems, which scales on a totally different curve and rarely changes in lockstep with its callers. The key test is whether the isolation buys real operational value that outweighs the fixed cost, not just conceptual purity.

Like splitting a restaurant kitchen into a 'salt station,' 'pepper station,' and 'plate-wiping station' - each hire is real overhead (scheduling, training, a doorway to walk through) for a task that takes two seconds, and now every dish needs five people to hand it down the line instead of one cook finishing the plate.

saying these in an interview costs you the question

  • Treats 'small service' as an unconditional goal without weighing operational cost
  • Can't explain why a service boundary exists in business terms, only technical ones
  • Doesn't mention the fixed cost every service carries (pipeline, monitoring, on-call)
  • Proposes a saga/distributed transaction as normal for what is really one aggregate's write
  • No mention of chatty communication or cascading failure as a consequence

context

open as a page

A team notices that a single request to their order-checkout API triggers 15 synchronous calls across 6 microservices before it can respond. What is this smell usually called, what causes it at the granularity level, and how would you address it?

level: middleimportance: must knowfreq 75%

basics

~20 s

This is called 'chatty' service communication - too many small back-and-forth network calls needed to do one piece of work. It usually means services were split too finely along lines that don't match how work actually flows, so simple operations require calling many of them in sequence. Fixes include combining related services, batching calls, or having one service own more of the workflow.

open as a page

What is the 'entity service' (a.k.a. CRUD-service) anti-pattern when decomposing a system into microservices, and why does it undermine the benefits microservices are supposed to deliver?

level: middleimportance: must knowfreq 65%

basics

~20 s

An entity service is a microservice built around one database table (like 'Customer' or 'Order') that just exposes create/read/update/delete endpoints for that table, with no real business logic. It looks like a clean split by 'noun,' but it pushes all the actual decision-making into whichever caller uses it, so business logic ends up duplicated or scattered across many services instead of owned by one.

open as a page

How do cohesion and coupling act as opposing forces when you're deciding how large or small to make a microservice, and what heuristics help you find the right boundary?

level: seniorimportance: must knowfreq 70%

basics

~20 s

Cohesion means things that change together and belong together should live in the same service. Coupling means how tangled services are with each other. You want high cohesion inside a service and low coupling between services. Getting the size right means grouping things that truly belong together, and not more.

open as a page

What are the concrete costs of a microservice architecture that's too coarse-grained ('macroservices' or mini-monoliths) versus one that's too fine-grained, and how do you decide which risk to accept for a given team and system?

level: seniorimportance: should knowfreq 60%

basics

~20 s

Too coarse means services are basically small monoliths - hard to scale or deploy independently, one team's bug blocks everyone. Too fine means way too many tiny services - huge operational overhead, slow chatty calls, hard to reason about the whole system. The right size depends on team size, how independently pieces need to change, and how much operational complexity the team can actually handle.

open as a page

How should service granularity evolve over the lifetime of a system, and what concrete signals tell an engineering organization it's time to split a service apart or merge services back together?

level: principalimportance: should knowfreq 55%

basics

~20 s

Granularity isn't a one-time decision - as a system and its teams grow, the 'right' size for a service changes. You split a service when a real, measurable reason shows up (different scaling needs, a new team owning part of it, slow deploys from unrelated changes). You merge services back when they always change together and the split is just adding overhead without any benefit.

open as a page