We are transitioning from a monolithic "Old Codebase" to a new Module Federation architecture split into 3 repositories: Core, WMS, and ASRS. A major risk is the "Moving Target" problem: the Old Codebase continues to evolve (bugs, features) while we are trying to migrate code to the new architecture.
- Single Source of Truth: At any point in time, a specific module (e.g., "Inbound Receiving") must have exactly one "Master" location. It is either the Old Repo OR the New Repo, never both.
- Minimize Double Entry: Avoid manually implementing the same feature in two places.
- Vertical Slicing: Migrate feature-by-feature rather than layer-by-layer.
This strategy involves freezing specific sections of the old application, migrating them, and then routing traffic to the new implementation.
- Goal: Establish the Host application (Shell), Authentication, and Navigation.
- Status:
- Old Codebase: Active Master for Auth/Shell.
- New Codebase: Under Construction.
- Sync Strategy: Double Entry (Manual).
- Since the architecture is changing (Monolith -> Federated Host), you cannot simply copy-paste Auth logic.
- Rule: Any change to Authentication or Global Styles in the Old Codebase must be manually re-implemented in the New Core immediately.
- Mitigation: Keep this phase as short as possible.
- Goal: Move the WMS functionality to the new
wmsremote. - Status:
- Old Codebase: FROZEN for WMS.
- New Codebase: Active Development for WMS.
- Sync Strategy: Freeze and Squeeze.
- Announce Freeze: "Starting Dec 1st, no new features for WMS in the Old Repo. Critical bugs only."
- Bulk Port: Copy WMS code to the new repo. Refactor for Federation.
- Emergency Fixes: If a critical bug occurs in Old WMS:
- Fix it in Old Repo (to save Production).
- Immediately apply the same fix to the New Repo.
- Cutover: Once WMS is ready in the new repo, update the Old App (or Gateway) to load the new WMS Remote.
- Goal: Handle business logic that must stay in sync but cannot be migrated yet.
- Strategy: Shared NPM Packages.
- Identify complex logic used by both (e.g.,
TaxCalculator,BarcodeParser). - Extract this code from the Old Repo into a shared NPM package (e.g.,
@company/logic). - Publish this package.
- Install this package in BOTH the Old Repo and the New Repo.
- Benefit: A bug fix in the package updates both systems via
npm update.
- Identify complex logic used by both (e.g.,
When a request comes in for a change, use this flowchart:
| Scenario | Action |
|---|---|
| New Feature for WMS (Migration started) | Reject in Old. Implement ONLY in New Repo. |
| Critical Bug in WMS (Migration started) | Fix in Old -> Manually Port to New. |
| Change to Shared UI (Button, Input) | Extract to UI Kit. Create/Update shared UI library. Update both repos. |
| Global Auth Change | Double Entry. Implement in Old. Re-architect/Implement in New. |
If the new repo was started as a copy of the old one (preserving git history), you might be able to use git cherry-pick to move commits over.
- Note: If directory structures differ significantly (which is likely), this will require manual conflict resolution.
In the Old Codebase, wrap the module being migrated in a Feature Flag.
if (FLAGS.useNewWms) { window.location.href = "/new-wms"; } else { renderOldWms(); }- This allows you to test the new module in production with a subset of users while keeping the old one as a backup.
Assign one developer as the "Migration Warden".
- Their job is to watch the commit log of the Old Repo every morning.
- If they see a commit touching files in the "WMS" folder, they flag it and ensure it is accounted for in the New Repo.
- Week 1-2: Build New Core (Host). Manual Sync of Auth/Styles.
- Week 3: Freeze WMS in Old Repo. Extract shared logic to NPM.
- Week 4-6: Port WMS to New Repo. Reject new WMS features in Old Repo.
- Week 7: Cutover. WMS is now live from New Repo. Old WMS code is deleted.
- Week 8: Repeat for ASRS.
You asked about refactoring inside the old project first before splitting the repositories. This is a valid, often safer approach, especially if the current codebase has high coupling (spaghetti code).
Instead of creating new repositories immediately, you reorganize the existing monolith into strict "Domains" (folders) that mimic the future repositories.
- IDE Power: Refactoring tools (Rename, Move File, Find Usages) work perfectly across the entire codebase.
- Type Safety: TypeScript checks everything instantly. No need to publish
@core/typespackages yet. - Low Infra Overhead: You don't need to set up 3 CI pipelines or Webpack Module Federation configs until the code is ready.
- Delayed Value: You don't get independent deployments until the very end.
- "Hidden Coupling" Risk: It is very easy to accidentally import a file from
CoreintoWMSthat works in a monolith (because it's all one bundle) but will crash in Module Federation (e.g., importing a React Context that relies on a specific Provider being up the tree).
If you choose this path, you MUST enforce boundaries using tooling, or you will fail when you try to split.
- Create Structure:
/src /Core (Can only import libraries) /WMS (Can import Core, but NOT ASRS) /ASRS (Can import Core, but NOT WMS) - Enforce with ESLint:
Use
eslint-plugin-boundariesordependency-cruiserto fail the build ifWMSimportsASRS.// .eslintrc.json example "rules": { "import/no-restricted-paths": [ "error", { "zones": [ { "target": "./src/WMS", "from": "./src/ASRS" }, { "target": "./src/Core", "from": "./src/WMS" } // Core shouldn't depend on features ] } ] }
- Choose "Refactor-First" if: Your current codebase is highly coupled (spaghetti). Splitting it now would result in 1,000 build errors.
- Choose "Strangler Fig" (Repo Split) if: Your codebase is already reasonably modular, and your main pain point is deployment velocity.