architect/microservices-vs-monolith/SKILL.md
--- name: microservices-vs-monolith description: Use this skill whenever the architect subagent is asked to decide between microservices and a monolith, evaluate service decomposition, determine how to split a system, or assess whether to break apart an existing application. Triggers on: "microservices vs monolith", "should we use microservices", "how to split this into services", "service decomposition", "when to break apart", "modular monolith", "service boundaries", "how many services". Alway
npx skillsauth add achreftlili/deep-dev-skills architect/microservices-vs-monolithInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Make a rigorous, context-driven recommendation on system decomposition — preventing both premature microservices and monoliths that can't scale.
Start with a monolith. Move to services only when you have a specific, demonstrated reason.
Most teams that start with microservices regret it. Most teams that start with a well-structured monolith and extract services when needed succeed. This is not a controversial opinion — it is the consensus of experienced architects.
Score each signal: For microservices (+1) or For monolith (0)
| Signal | Question | Threshold for microservices | |--------|----------|----------------------------| | Team size | How many engineers? | >50 engineers, multiple autonomous teams | | Deploy frequency | How often do parts need independent releases? | Different subsystems deploy >2x/day independently | | Scale asymmetry | Do different parts need radically different scaling? | Yes — e.g., checkout 100x traffic vs. admin panel | | Tech heterogeneity | Do different parts need genuinely different tech? | Yes — e.g., ML inference (Python) + OLTP (Go) | | Fault isolation | Must one part failing not affect others? | Yes — e.g., payments must stay up if recommendations fail | | Org structure | Do teams already work independently on different domains? | Yes — Conway's Law is real | | Data isolation | Do different domains have completely separate data? | Yes — clean domain boundaries already exist | | Current pain | Is the monolith actively causing problems? | Build time >15min, deploys block teams, scaling is impossible |
Score 0–3: Build a monolith
Score 4–5: Build a modular monolith
Score 6–8: Microservices are justified
A single deployable unit. Everything in one codebase.
When to choose:
Structure it well:
src/
├── modules/
│ ├── users/ (self-contained: routes, service, repo)
│ ├── orders/
│ └── payments/
├── shared/ (minimal — only truly shared utilities)
└── main.ts
Keep modules loosely coupled internally — this makes future extraction easy.
A single deployable unit with enforced module boundaries. No cross-module direct calls — modules communicate through defined interfaces.
Benefits over a pure monolith:
Benefits over microservices:
modules/
├── users/
│ ├── api/ (public interface — only this is callable from outside)
│ ├── internal/ (private — no other module touches this)
│ └── events/ (events this module emits)
├── orders/
└── payments/
Independently deployable services, each with its own data store.
When justified: score ≥ 6 on the signal table above.
Service decomposition principles:
Avoid these decomposition mistakes:
Use Domain-Driven Design to find boundaries:
Example for e-commerce:
✅ Good boundaries:
- Order Service (place, track, cancel orders)
- Inventory Service (stock levels, reservations)
- Payment Service (charge, refund, dispute)
- Notification Service (email, SMS, push)
- User Service (auth, profile, preferences)
❌ Bad boundaries:
- "CRUD Service" (technical, not domain)
- "Database Service" (antipattern)
- Order + Inventory combined (too coupled)
| Pattern | Use for | Technology | |---------|---------|------------| | Sync request/response | Real-time reads, user-facing queries | REST or gRPC | | Async events | State changes, cross-domain notifications | Kafka, SQS, RabbitMQ | | Saga pattern | Distributed transactions across services | Choreography (events) or Orchestration |
Avoid distributed transactions (2PC). Design for eventual consistency where possible.
Always produce:
Wrong to use microservices if:
Wrong to stay monolith if:
testing
Set up Vitest 2.x with TypeScript for unit and component testing using test/describe/it, vi.fn/vi.mock/vi.spyOn, component testing with Testing Library, coverage (v8/istanbul), workspace config, and snapshot testing.
testing
Set up pytest 8.x with Python for unit and integration testing using fixtures (scope, autouse, parametrize), async tests (pytest-asyncio), mocking (unittest.mock, pytest-mock), coverage (pytest-cov), conftest.py patterns, and markers.
testing
Set up Playwright 1.49+ with TypeScript for E2E testing using page object model, fixtures, test.describe/test blocks, assertions, selectors, network mocking, CI configuration, and trace viewer.
testing
Set up Jest 30+ with TypeScript for unit tests, integration tests, mocking (jest.fn, jest.mock, jest.spyOn), coverage configuration, custom matchers, snapshot testing, and setup/teardown patterns.