Monolith decomposer
Skill SkillMedev/legacy-modernization/skills/monolith-decomposer
Move old code to modern stacks without a risky big-bang rewrite.
npx -y skills add SkillMedev/legacy-modernization --skill monolith-decomposerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Finds and validates one bounded-context seam to extract from a monolith - gated on coupling-graph, co-change, data-ownership, and transaction-boundary evidence - and sequences an incremental strangler-fig extraction plan. Use when someone asks "where should we cut this monolith", "is this module ready to extract as a service", "plan the extraction of billing from the app", or is evaluating whether a candidate seam is clean. Do NOT use for designing the target service architecture, service communication, or greenfield service boundaries - use microservices instead; do NOT use to document the implicit business rules inside the code being moved - use business-rule-extractor instead. This skill decides where to cut and in what order.
SKILL.md
8.3 KB, as published. Nobody here has run it
Monolith Decomposer
Extract one bounded-context seam at a time, only after data ownership and coupling evidence prove the cut is clean. Cut along the wrong seam and you get a distributed monolith: the latency, failure modes, and operational cost of microservices with the coupling of a monolith - the single most expensive architecture mistake a team can make.
Operating procedure
Evidence gates come before design, and design before sequencing, because a seam that fails the data-ownership veto in Step 3 makes every downstream step wasted work.
Step 1: Gather inputs and confirm the motive
Collect: the candidate context (if any), the driver (independent scaling, deploy cadence, team ownership - the only three valid ones), team size, and current deploy pain. If the driver is slow deploys, flaky tests, or unclear modules, stop: modularize in-process first. A well-modularized monolith beats a badly-cut set of services on nearly every axis. Label an unverified driver as a guess and verify it before proceeding.
Step 2: Pick a candidate bounded context
Name one cluster of behavior with high internal cohesion and a thin, stable interface to the rest - a domain concept (DDD bounded context / aggregate), not an org-chart team or a technical layer. Extract exactly one per effort.
Step 3: Run the seam-finding procedure - three artifacts, then the veto
Do not prescribe a cut without all three:
- Coupling graph. Run madge / dependency-cruiser (or the language equivalent) scoped to the candidate. Count inbound call sites and shared symbols. Practitioner heuristic: a good seam has inbound call sites countable on one hand routing through few entry points and a shared vocabulary of a dozen types or fewer; dozens of scattered inbound edges means the seam is wrong or needs in-process consolidation first.
- Co-change report. From history:
git log --format= --name-only | sort | uniq -c | sort -rn, then check which files outside the candidate change in the same commits as files inside it. Files that always change together belong together - high cross-boundary co-change is a seam smell. Working thresholds: cross-boundary co-change in more than ~25% of the candidate's commits is a smell to resolve before extracting; under ~10% the seam reads clean (the artifact below shows both readings). - Transaction boundaries. List every transaction the candidate participates in and every table it reads/writes, with who else touches each.
The data-ownership veto: a service that does not own its data is not a service. If the candidate and the monolith both need write access to the same tables inside one transaction, the seam is wrong or not ready - stop and return to Step 2.
Step 4: Plan the data split
Decide which tables move, how foreign keys across the new boundary break (typically: replace with soft references validated asynchronously), and how cross-boundary joins are replaced (API composition or a local read model). Specify the migration mechanism - dual-write or CDC - plus a reconciliation check (row counts and checksums on both sides) before and after cutover. Never dual-write without reconciliation.
Step 5: Design the anti-corruption layer
Put a translation facade at the boundary so the extracted service speaks its own clean domain language and the monolith keeps its own. This lets either side fix its model without a coordinated big-bang change.
Step 6: Plan distributed failure modes per operation
Each former local call is now a network call that times out, retries, and partially fails. For every operation crossing the seam, decide whether it can be eventually consistent; add idempotency (pair with idempotency-enforcer), timeouts, circuit breakers (circuit-breaker-builder), and a trace that follows the request across the boundary. If any operation truly needs cross-service ACID, the seam is in the wrong place - return to Step 2.
Step 7: Sequence strangler-style, sized in weeks not months
Each increment must be independently shippable and reversible, ideally 1-3 weeks of work; an increment that cannot ship alone is two increments:
- Create the seam in-process - a clear interface/module inside the monolith - and prove every caller routes through it (grep for bypasses; fail CI on new ones).
- Move the implementation behind a network call with the old path behind a flag; run shadow/parallel traffic and compare outputs.
- Migrate data with dual-write or CDC; reconcile.
- Cut over via the flag; keep the old path warm.
- Delete the in-monolith code only after the service has served real production traffic through a full business cycle (including month-end or peak, whichever stresses it).
Worked artifact: seam evidence summary
SEAM CANDIDATE: Billing (invoices, payments, dunning)
Coupling graph (dependency-cruiser):
Inbound call sites: 4 (OrderService.checkout, AdminController x2, cron/dunning)
Shared types crossing boundary: 6 (Invoice, Payment, Money, CustomerRef, TaxLine, Currency)
Verdict: PASS - few entry points, small vocabulary
Co-change (last 12 months):
billing/* co-changes with orders/checkout.rb in 31% of billing commits <- investigate
billing/* co-changes with anything else in <5% of commits
Verdict: CONDITIONAL - decouple checkout's inline tax call first
Data ownership:
invoices, payments, dunning_events: written ONLY by billing PASS
orders.balance_cents: written by billing AND orders in one txn VETO
Resolution: move balance to billing-owned ledger; orders reads via API/event
Cross-seam operations: checkout->createInvoice (eventually consistent OK, idempotency
key = order_id), refund (sync, timeout 2s + circuit breaker). No cross-service ACID. PASS
Deliverable
Produce an extraction plan containing: the named bounded context, the three evidence artifacts with pass/veto verdicts, the table-by-table data split with migration mechanism and reconciliation checks, the anti-corruption layer sketch, a per-operation consistency and failure-mode table, and the staged strangler sequence with a rollback path per stage.
Do NOT
- Do NOT cut along the org chart or a technical layer; cut along a bounded context.
- Do NOT propose a seam from intuition - produce the coupling graph, co-change report, and table-ownership map first.
- Do NOT extract a service that shares write access to tables with the monolith inside one transaction.
- Do NOT do a big-bang cut; never delete the in-monolith path before the service has served real traffic through a full cycle.
- Do NOT dual-write or use CDC without a reconciliation check on both sides.
- Do NOT extract to fix slow deploys, flaky tests, or unclear modules - modularize in-process first; only independent scaling, deployment, or team ownership justify the network boundary.
- Do NOT extract more than one context per effort.
Quality bar
A seam is ready to extract only when all hold: it maps to a named bounded context; inbound call sites are few and pass through one interface with a small shared vocabulary; the candidate exclusively owns the tables it writes; a data-migration plan with reconciliation exists; every cross-seam operation has a defined consistency model with none requiring cross-service ACID; and the extraction is staged in-process seam → network-behind-flag → cutover → delayed delete, each stage reversible.
Escalation
Target-state service design and inter-service communication patterns belong to microservices. Pinning the legacy behavior before moving it belongs to characterization-test-writer; documenting its business rules to business-rule-extractor; database migration safety to migration-safety-checker.