Choosing the size of a microservice isn’t just about code. it’s about team structure, business capabilities, and how the system will evolve over time.
Get it wrong, and you either end up with:
- The Mini-Monolith → big, complex, slow to deploy, and hard for one team to own.
- The Distributed Hairball → dozens of tiny services that constantly call each other, making debugging a nightmare.
Start with the Business Domain (Domain-Driven Design)
Most experienced teams begin with DDD to find bounded contexts areas where the business language, rules, and data make sense together.
Example – E-commerce:
Bounded contexts that naturally map to microservices:
- Catalog → product data, categories, availability
- Ordering → order creation, updates, status tracking
- Payments → payment processing, refunds, compliance
- Shipping → delivery tracking, carriers, schedules
Why it works:
- Keeps each service focused
- Prevents mixing unrelated rules
- Data ownership is clear
Look at Change Patterns
If two features always change together, they probably belong in the same service.
If they change at different speeds or are handled by different teams, splitting makes sense.
Example:
- Catalog changes once a month → stable
- Checkout changes weekly → fast-moving
- → Keep them separate so catalog updates don’t block checkout releases.
Align to Team Boundaries (Two-Pizza Rule 🍕)
A service should be small enough for one small team (5–8 people) to fully own and deploy it without coordinating with other teams.
Example:
If both the Marketing and Payments teams constantly commit to the same codebase, that service is probably too big.
Data Ownership Is Non-Negotiable
Each microservice should own its own database.
If two services write to the same table, they’re still coupled, no matter what the code says.
Example:
Payments owns the Transactions table.
If Orders needs payment info, it calls Payments or subscribes to its events. it doesn’t write directly to that table.
Watch for Chatty Communication
If one user request calls more than 2–3 services synchronously, you may have gone too granular.
Fix:
Use event-driven architecture — publish an event like OrderPlaced and let other services (Payments, Notifications, Loyalty) react independently.
Start Bigger, Split Later
Most large companies don’t start with dozens of microservices.
They begin with a modular monolith or a few chunky services and split when needed:
- Scaling issues
- Release coordination pain
- Regulatory/security isolation needs
Example:
A SaaS platform starts with Users + Billing + Analytics in one service.
When Billing needs PCI compliance, they split it into its service, with minimal disruption.
Summary
When deciding microservice boundaries:
- Start with bounded contexts from Domain-Driven Design.
- Group features by change patterns — if they change together, keep them together.
- Align services to small, independent teams (Two-Pizza Rule).
- Enforce data ownership — one service, one database.
- Avoid excessive synchronous calls — prefer async/event-driven.
- Start larger, split only when needed for scaling, compliance, or deployment independence.
The goal isn’t to have the smallest services.It’s to have well-defined, loosely coupled, independently deployable services that match your business needs and team structure.
💬 Over to you — Have you worked on a project where microservices were way too small or too big? How did it go?
Top comments (0)