Volume 1

Q077: Large Scale Frontend Migration Strategy

Difficulty: SeniorFrequency: HighAnswer time: 8-12 minutes

What Interviewers Want To Evaluate

This question tests whether you can move a large frontend system without stopping product delivery. Interviewers want planning, risk reduction, compatibility layers, progressive rollout, testing, metrics, communication, and cleanup discipline.

Senior engineers are expected to migrate frameworks, routers, design systems, state libraries, build tools, test stacks, API clients, package managers, and deployment pipelines. The technical work matters, but the strategy matters even more.

Short Interview Answer

A large frontend migration should be incremental, measurable, and reversible. I would define the goal, inventory current usage, choose a migration path, create compatibility layers if needed, migrate low-risk surfaces first, add automated tests and telemetry, use codemods for repetitive changes, keep old and new systems running during transition, and remove the old path once adoption is complete. The key is reducing risk while keeping teams productive.

Detailed Interview Answer

Large migrations fail when they are treated as a single code change. Real migrations happen while product teams keep shipping features, bugs keep arriving, and priorities keep changing.

Start by clarifying the migration driver:

Are we reducing bundle size?
Improving developer speed?
Replacing an unsupported library?
Improving accessibility?
Moving to a new routing model?
Reducing production incidents?
Unlocking future architecture?

Without a clear reason, the migration becomes hard to defend when the work gets slow.

Inventory and Scope

Before changing code, inventory usage. Count call sites, packages, routes, teams, owners, edge cases, and test coverage. Identify critical flows such as checkout, login, dashboards, exports, admin actions, and onboarding.

This inventory helps choose migration order. Low-risk pages are good pilots. High-risk pages need stronger verification.

Compatibility Layer

For many migrations, a compatibility layer is the difference between a safe rollout and a rewrite. It can let old and new systems coexist while teams migrate gradually.

Examples include:

adapter around old and new API clients
bridge component for old and new design tokens
route wrapper that supports both data loading models
shared event contract during analytics migration
temporary wrapper around old state and new state

The compatibility layer should be temporary and tracked. Otherwise it becomes permanent complexity.

Migration Strategy

Choose the smallest safe path. Sometimes this means vertical migration by route. Sometimes it means horizontal migration by component type or shared package.

A route-by-route migration works well when pages are isolated. A component-by-component migration works well when the same primitive is used everywhere. A package-by-package migration works well in monorepos with clear ownership.

Testing and Release Safety

Testing should match risk. Unit tests cover pure transforms and adapter behavior. Integration tests cover component contracts. E2E tests cover critical user flows. Visual tests catch design-system regressions.

For production rollout, use feature flags, canary releases, staged deployments, and telemetry. Measure error rate, Web Vitals, route latency, bundle size, interaction delay, and support tickets.

Codemods

Codemods are useful when the change is repetitive and mechanical. They reduce manual mistakes and make migration speed more predictable.

However, codemods should be reviewed carefully. A codemod that changes thousands of files can hide subtle behavior changes. Run it on a small set first, inspect output, then expand.

Communication

Migration work is cross-team work. Engineers need clear guidance: what is changing, why it matters, how to migrate, how to ask questions, and when old APIs will be removed.

Good communication includes examples, migration guides, owner lists, status dashboards, and release notes.

Common Mistakes

A common mistake is trying to migrate everything in one branch. That creates merge conflicts, review fatigue, and high rollback risk.

Another mistake is completing the “new” implementation but never deleting the old one. The system then carries two mental models indefinitely.

Senior Trade-Offs

A slower incremental migration reduces risk but may extend the period where two systems coexist. A faster big-bang migration reduces coexistence time but increases release risk.

The right choice depends on product criticality, test coverage, team capacity, and how coupled the old system is.

Code or Design Example

A migration plan can be represented as explicit states. This makes ownership and readiness visible.

type MigrationState =
  | { status: "not-started"; owner: string }
  | { status: "pilot"; owner: string; route: string; rollbackPlan: string }
  | { status: "in-progress"; owner: string; migrated: number; total: number }
  | { status: "blocked"; owner: string; reason: string }
  | { status: "complete"; owner: string; cleanupDone: boolean };

type MigrationMetric = {
  route: string;
  errorRate: number;
  p75InteractionMs: number;
  bundleKbDelta: number;
};

This makes the migration observable rather than purely narrative.

Example Migration

Suppose a team is moving from a custom client router to Next.js App Router. A safe plan might start with non-critical routes, establish shared layout conventions, define data loading rules, migrate route groups gradually, monitor hydration errors, and keep redirects stable.

The team should not migrate authentication, checkout, or high-traffic dashboards first unless there is a strong reason and strong coverage.

Lead Engineer Perspective

A lead engineer should create the migration map, align teams, define review standards, and watch for product pressure that creates half-migrated code.

The lead should also decide when to stop. Some legacy surfaces may not be worth migrating if they are about to be deleted.

Debugging Migration Regressions

When a regression appears, compare old and new behavior under the same inputs. Check route data, rendering order, effects, analytics events, feature flags, cache keys, auth headers, and error boundaries.

Keep rollback paths practical. A rollback that requires another migration is not a rollback.

Revision Notes

Large migrations need goals, inventory, pilots, compatibility, tests, telemetry, communication, and cleanup.

Key Takeaways

A senior migration answer should sound like risk management plus engineering execution. The goal is not just reaching the new stack. The goal is reaching it without breaking users or exhausting teams.

Follow-Up Questions

  1. How do you choose pilot routes?
  2. When do you use a compatibility layer?
  3. How do you prevent permanent dual systems?
  4. What metrics prove migration success?
  5. How do you handle ownership across teams?
  6. When should you use codemods?
  7. How do you reduce merge conflicts?
  8. How do you plan rollback?
  9. What should migration docs include?
  10. How do you decide not to migrate something?

How I Would Answer This In A Real Interview

I would describe a migration as a staged program, not a giant pull request. I would define the business and technical goal, inventory the system, create adapters where useful, run a pilot, migrate in batches, measure production impact, communicate clearly, and remove the old path after adoption.