This skill should be used when the user asks "monolith vs microservices", how to "split into services", set "service boundaries", find the right "service granularity", design an "API gateway / BFF", do "service discovery" or add a "service mesh", or worries that services are "too chatty" / "too fine-grained" — including when a team is pushed to adopt microservices or Kafka between services "to be ready to scale" and the right answer may be a modular monolith. It gives the recipe for carving a system into services (or deciding not to) and wiring how they find and call each other. Use it whenever a design has more than one service — or someone is tempted to add more — even if the user doesn't say "microservices".
npx skills add https://github.com/proyecto26/system-design-skills --skill service-decomposition
Decide how to carve a system into deployable services — or whether to — and how
those services find and call each other. This is the "application layer" of a
design: it sits between the edge (dns/load-balancing/content-delivery) and
the data tier. Getting the *granularity* wrong is one of the most expensive
mistakes in distributed systems, in both directions.
> The trap cuts both ways. One giant service can't scale teams or components
> independently; a swarm of tiny ones drowns you in network hops, partial
> failures, and undebuggable cross-service traces. The skill is finding the
> sweet spot for *this* system at *this* size — not maximizing service count.
A second service is on the table; teams need to deploy independently; one part has
a wildly different scaling profile than the rest; or an existing system is "too
chatty" / hard to change. Also when someone proposes "microservices" by default.
A new product / small team / unproven domain — start with a monolith (or a
modular monolith) and split later when a real seam and a real reason appear.
Splitting prematurely buys distributed-systems cost (network failure, eventual
consistency, ops) to solve a problem you don't have yet (YAGNI, GUIDE #7). Don't
add a gateway/mesh/discovery layer before you have services that need them.
between services? (→ consistency-coordination)
cross-module transactions, one team.
Use when: you want clean seams *without* network cost yet — the best default
for "we might split later."
bounded context. Use when: independent deploy/scale/ownership genuinely pays
for the distributed-systems tax.
request/response, simple but couples availability) or asynchronous (decoupled
but eventually consistent). This block decides *sync-or-async per seam*; it does
not own the async mechanics — once a seam is async, **invoke
messaging-streaming** for the delivery guarantees, ordering, backpressure, and
DLQ semantics that make it safe. Don't pick async from the one-line "no immediate
answer needed" rule without opening those failure modes. Most systems are a mix.
auth, routing, rate limiting, aggregation) vs direct exposure.
etcd/Consul/ZooKeeper) and optionally a service mesh (sidecars for mTLS,
retries, traffic shaping) vs library-level clients.
| Option | What it solves | What it worsens | Change it when |
|---|---|---|---|
| Monolith | Simplicity; in-process calls; easy transactions/debugging | Couples deploy/scale; one team bottleneck; blast radius | Teams/scale profiles diverge → modular monolith → split a seam |
| Modular monolith | Clean boundaries, no network cost, split-later optionality | Still one deploy; discipline required to keep modules clean | A module needs independent deploy/scale → extract it to a service |
| Microservices | Independent deploy/scale/ownership per capability | Network failure, eventual consistency, distributed debugging, ops | Coordination/latency cost exceeds the independence benefit → merge |
| Sync comms | Simple mental model, immediate result | Availability couples (caller fails if callee does); latency stacks | A call doesn't need an immediate answer → async (messaging-streaming) |
| API gateway / BFF | One front door for auth/routing/rate-limit/aggregation | A new tier + potential SPOF/bottleneck; can become a mini-monolith | It accretes business logic → push logic back into services |
| Service mesh | Uniform mTLS/retries/observability without app changes | Real operational + latency overhead (sidecars) | A handful of services → a library/gateway is enough |
calls; tail latency compounds and a single slow dependency stalls the chain.
*Mitigate:* coarser boundaries, batching, async where an answer isn't needed
now, and circuit breakers (→ resilience-failure).
transaction. *Mitigate:* saga / outbox, or keep the data in one service so
the transaction stays local (→ consistency-coordination).
cascade. *Mitigate:* backoff+jitter, budgets, circuit breakers (→ resilience-failure).
crosses 6 services is invisible. *Mitigate:* distributed tracing + correlation
IDs from day one (→ observability, distributed-logging).
does. *Mitigate:* redundancy, client-side caching of discovery, health checks.
ownership? If none are real yet, stop: a (modular) monolith wins.
extract the one seam that has a real reason — not "everything is a service".
logic that owns it stay together (minimizes cross-service transactions).
answer; async otherwise (→ messaging-streaming).
auth/routing/aggregation; discovery/mesh when service count makes static
wiring painful.
cascades, and tracing before committing.
Change it when…` table with one row per choice you made here (e.g. the
option, its store, its failure policy); the last column is a concrete trigger
(a number or observable signal). Then name what breaks first.
Do
Don't
Each sync hop adds a same-datacenter round trip (~0.5 ms) **plus the callee's own
work**. 10 serial hops is only ~5 ms of *network* — the real cost is the compounded
p99/serialization/queueing/retry tail: each hop multiplies the chance of
hitting a slow dependency, so end-to-end p99 degrades far faster than the mean.
Size the call-graph depth and the per-hop p99 (not just the network) before
splitting, with explicit p99 budgets. → back-of-the-envelope.
A service boundary is a contract: the owned data (which service is the source
of truth for each entity), the API it exposes (→ api-design), and the
events it emits (→ messaging-streaming). Write down "who owns user records,
who owns orders" before drawing service boxes — shared mutable data across a
boundary is the #1 decomposition smell.
Default to the generic recipe above. If the user names a cloud, read
references/providers/<provider>.md for the managed gateway / discovery / mesh
mapping, limits, and trade-offs. If no file exists for that provider, the generic
recipe is the answer.
To visualize the service tier (gateway → services → their data, with sync vs async
edges and trust boundaries), use the in-plugin architecture-diagram skill.
api-design — *pairs with* this: decomposition sets the boundaries, api-design defines each service's contract.messaging-streaming — *pairs with* this for async/event-driven comms between services (the alternative to sync coupling).consistency-coordination — *owns* the cross-service consistency story (saga/2PC) and the coordination theory behind service discovery (leader election, etcd/Consul/ZooKeeper); link there, don't re-teach.resilience-failure — *depends on* this: circuit breakers, timeouts, bulkheads keep a chatty mesh from cascading.observability + distributed-logging — *feed into* this: tracing + correlation IDs are what make a multi-service request debuggable.scaling-evolution — *feeds into* this: extracting a service is a scaling move on the "split a seam" rung.system-design — the orchestrator.references/deep-dive.md — bounded contexts & how to find seams, the strangler-fig migration from monolith, gateway vs BFF vs mesh, sync-vs-async decision detail, saga/outbox for cross-service writes, and the granularity anti-patterns (nano-services, distributed monolith, shared database).references/providers/{generic,aws,azure,gcp}.md — gateway / service-discovery / mesh service mappings, limits, and pitfalls per environment.Use when you have a written implementation plan to execute in a separate session with review checkpoints
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take proyecto26/service-decomposition from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.