Module 5: Framework and Language Migration

Module 5: Framework and Language Migration

Module 5: Framework and Language Migration

Capsule description

The previous module taught you refactoring within the same framework — changing structure without changing the framework. This module scales up the ambition: what happens when you need to change frameworks completely? Flask→FastAPI, sync→async, unittest→pytest, requests→httpx. These migrations are the most costly and risky projects teams face — and the most transformative when executed well.

A framework migration isn't a big refactoring — it's a different category of work. It involves changing APIs, patterns, dependencies, and often the complete structure of the project. Without a process, it becomes a chaotic rewrite. With a process, it becomes a series of verifiable steps.

In this module you're going to learn that process: the plan → safety net → migrate → validate cycle, the strangler fig pattern for gradual coexistence, and how Claude Code accelerates each step. The case study is Flask→FastAPI, but the process applies to any migration.


Module Context

Where are we?

Guide #8, Phase 2: Refactoring, Module 5 of 6.

Phase 2: Refactoring (Modules 4-6)
├── Module 4: Multi-File Refactoring ✅
│   → Rename, extract, move, interface changes
├── Module 5: Framework Migration ← YOU ARE HERE
│   → Flask→FastAPI, strangler fig, migration testing
└── Module 6: Context Management for Large Projects
    → 1M tokens, chunking, CLAUDE.md

What you already know

From Module 4 you arrive with mastery of coordinated refactoring: rename, extract, move, interface changes, and regression tests. A framework migration uses all these techniques — but at the framework scale.

Where are we headed?

Module 6 solves the practical problem that emerges with migrations of large projects: context management. And Module 8 integrates migration as part of the full modernization of a legacy project.


Professional Objective

By the end of this module, you'll be able to plan and execute a framework migration step-by-step, using the strangler fig pattern for gradual coexistence and equivalence tests to validate that the behavior is preserved.

By the end of this module you'll be able to:

  • ✅ Design a migration plan with phases, checkpoints, and a rollback strategy
  • ✅ Apply the migration cycle: plan → safety net → migrate → validate → repeat
  • ✅ Execute a Flask→FastAPI migration endpoint by endpoint
  • ✅ Implement the strangler fig pattern for old/new coexistence
  • ✅ Write migration tests that verify equivalence between versions
  • ✅ Plan a rollback for when something goes wrong

Module Progression

Module Map

CapsuleTopicWhat you'll learn
02Migration StrategyThe plan→test→migrate→validate cycle and how to design a migration plan
03Flask→FastAPI Step-by-StepA practical endpoint-by-endpoint migration with Claude Code
04Strangler Fig PatternOld/new coexistence: migrating gradually without a big bang
05Migration TestingTests that verify equivalence between old and new
06Project: Flask→FastAPI MigrationMigrate a complete app step-by-step

Learning flow

You start with the strategy (how to plan a migration), then the practical execution (Flask→FastAPI step by step), then the coexistence pattern (strangler fig), and finally testing (verify that old=new). The project integrates everything into a real migration.


The Core Principle

Gradual always beats big bang.

Never migrate everything at once. Migrate one endpoint, verify, migrate the next. The strangler fig pattern is the right way to migrate: old and new coexist, the traffic moves gradually, and the old is removed when everything is migrated.


A Real Migration: Big Bang vs Gradual

To anchor the module, consider a typical case:

Task: Migrate payments-api (8 endpoints, ~3K lines, in production) from Flask 1.x to FastAPI. Deadline: two weeks.

Approach A: Big Bang

Week 1, Monday-Thursday → Rewrite the 8 endpoints in FastAPI
Week 1, Friday → "Manual" tests, they seem to work

Week 2, Monday → Deploy to staging. Authentication fails
                  (FastAPI handles auth differently).
Week 2, Tuesday → Fix auth. Validation fails
                  (Pydantic stricter than Flask).
Week 2, Wednesday → Fix validation. An endpoint fails
                       that nobody had tested in years.
Week 2, Thursday → Team decision: revert staging.
                    "Let's reschedule the migration."

Result: 2 weeks lost, FastAPI isn't in production,
           the team's confidence affected.

Approach B: Strangler Fig (this module)

Day 1 → Plan: migration order by ascending complexity.
        /health → /version → /accounts → /transactions →
        /reports → /payments (the ones that touch money last).

Day 2 → Set up a proxy. Migrate /health.
        Equivalence tests green. 100% of the /health traffic
        now passes through FastAPI.

Day 3-4 → Migrate /version and /accounts.
          Each with equivalence tests.
          If something fails, FASTAPI_ROUTES = ROUTES - {endpoint}
          (rollback of one endpoint in 30 seconds).

Day 5-7 → Migrate /transactions and /reports.
          Tests pass. The team gains confidence.

Day 8-9 → Migrate /payments with extra care.
          Exhaustive equivalence tests (every edge case).

Day 10 → 24h of monitoring with 0 requests to Flask.
         Cutover: remove Flask and the proxy.

Result: complete migration, zero incidents, confidence
           reinforced, FastAPI code in production.

Same work. Same team. Radically different results.

The difference isn't implementation speed — it's sequence, verification, and rollback. Capsules 02-05 teach you each component.


Connection with the Project

This module's project: Flask→FastAPI Migration

You're going to receive a small Flask application (4-6 endpoints) and migrate it to FastAPI step-by-step. Each step: migrate an endpoint, write an equivalence test, verify. In the end, both versions produce identical responses.

Connection with the guide

In Module 8 (Capstone Project), the migration may include a framework change as part of the complete modernization.


Limits: What We WON'T Do

  • ❌ Language migration (Python→Go) — Only frameworks within the same language
  • ❌ Database migration — Only the application layer
  • ❌ Deployment of the migration — Only the code, not the infrastructure
  • ❌ Performance benchmarking — We verify functional equivalence, not performance

Traps to Avoid While Taking This Module

Five predictable misunderstandings. Anticipate them before you start.

1. "Migration = rewrite"

No. Migration preserves behavior while changing the framework. Rewrite starts from scratch and can change behavior. Mixing them is the #1 cause of failed migration projects. Capsule 02 develops the distinction.

2. "Tests at the end"

No. Equivalence tests go before each migrated endpoint. Without prior tests, you don't know whether the migration preserved behavior. Capsule 05 teaches you to write them effectively.

3. "Big bang is faster"

No. It seems faster on day 1, but the total cost (debugging, rollback, incident) is 3-5× higher. Capsule 04 (strangler fig) shows why gradual wins.

4. "Rollback is planned if it fails"

No. Rollback is planned before migrating the first endpoint. If you have to design the rollback in the middle of an incident, it's already too late. Capsule 04 gives you the pattern.

5. "The new framework is objectively better"

Sometimes. Migrating to FastAPI has concrete advantages (native async, Pydantic, automatic OpenAPI), but also costs (the team's learning curve, ecosystem migration). Validating that the migration has a clear ROI before starting is the responsibility of whoever proposes it, not assumed.


Diagnosis: Ready for the Module?

Question 1: Have you migrated a project from a framework before? If so, how did it go?

If it went badly: note what failed. It was probably a big bang (capsule 04) or without equivalence tests (capsule 05). The module corrects the pattern for you.

If never: this is your first learning. The module project is the controlled practice.

Question 2: Do you know the difference between migration and rewrite?

If yes: you're going to avoid trap #1.

If no: the "What we won't cover" section above is your starting point.

Question 3: Do you design a rollback plan before starting to change code?

If yes: you work with professional safety.

If no: trap #4 applies to you. Capsule 04 gives you the pattern.


Evidence of Success

Before moving on to Module 6 (Context Management), you should be able to:

  • ✅ Migrate a Flask→FastAPI endpoint with verified equivalence
  • ✅ Implement strangler fig for gradual coexistence
  • ✅ Write tests that verify old==new for the same input
  • ✅ Have a rollback plan before starting
  • ✅ Your migration plan has phases with clear checkpoints
  • ✅ Tell migration apart from rewrite with clear criteria

Key Concepts of the Module

A preview of the central concepts so you arrive with the vocabulary:

Migration Strategy

The disciplined process of plan → safety net → migrate → validate → repeat. It's not a rigid workflow — it's the sequence that prevents incidents when migrating. Capsule 02 develops each phase.

Strangler Fig Pattern

A gradual migration pattern where old and new coexist. A proxy or middleware decides what traffic goes to each. The old is "strangled" when 100% of the traffic goes to the new. Capsule 04 gives you the implementation.

Equivalence Tests

Tests that compare old and new with the same inputs and verify equivalent outputs (status + body + side effects). They're your safety net during the migration. Capsule 05 teaches you to write them.

Cutover

The moment when you remove the old. It requires meeting a specific checklist: 100% of endpoints migrated, 100% of tests green, 0 requests to the old for X time. Capsule 04 develops the cutover.

Rollback Strategy

A documented plan to go back to the old if something fails. In strangler fig, the rollback of one endpoint is trivial (FASTAPI_ROUTES = ROUTES - {endpoint}). Capsule 02 teaches you to document it.

Migration Coexistence

The period where old and new operate simultaneously serving different endpoints. It requires deciding: do they share the DB? do they share the cache? do they share sessions? Capsule 04 develops the trade-offs.


Summary

  • This module scales refactoring to the level of complete frameworks
  • Flask→FastAPI is the case study, but the process applies to any migration
  • Gradual > big bang — strangler fig pattern, endpoint by endpoint
  • Equivalence tests verify that old and new produce the same result
  • Claude Code accelerates the conversion but human validation + tests are irreplaceable
  • Migration ≠ rewrite — preserving behavior is the heart
  • A rollback plan is designed before the first change, not during an incident
  • The difference between the "2 weeks lost" and the "clean migration" from the initial scenario is exactly this module

Next capsule: 02 — Migration Strategy — the plan→safety net→migrate→validate cycle as the backbone of any migration. We start here because without strategy, the rest of the module is execution without direction.


Migration as a Decision, Not a Reflex

Before starting the module, it's worth naming something: not every migration should be done. The instinct to "modernize to the latest stack" can lead to migrations that don't have a clear ROI.

Before migrating, the team should be able to answer affirmatively to at least 2 of these questions:

  1. Is there a concrete pain point with the current framework? (Performance, scaling, maintainability — not "Flask feels old")
  2. Does the team have the technical capacity for the new framework? (Not just "the lead knows it")
  3. Do the new framework's features solve real problems? (Native async is relevant if the project needs it)
  4. Is the total cost (weeks of migration + learning curve) less than the current pain?
  5. Is the new framework's library/ecosystem mature for the use case?

If the answers are all negative, it's better to postpone. Migrating a healthy framework because "FastAPI is trendy" can consume 4-6 weeks of the team's time with no proportional return.

This module teaches you to execute a migration well. The decision of whether to migrate is outside the technical scope — but it's the most important question that should be asked before applying the techniques you learn here.


How to Work Through This Module

  1. Capsule 02 is the foundation. Without understanding the plan→safety net→migrate→validate cycle, the technical capsules are execution without sight.
  2. Capsule 03 is the concrete practice. Flask→FastAPI step by step — follow it with your own Flask project open beside you.
  3. Capsule 04 is where the operational magic happens. Strangler fig + cutover. Read it even if you're in a hurry to "just execute."
  4. Capsule 05 is the insurance. Without equivalence tests, you don't know whether the "new" does the same as the "old."
  5. The project integrates everything — and it's the only way to internalize the cycle. Executing it with a small project trains you for a big one.

Estimated time:

Capsule 01 (this one)  →  10 min reading
Capsule 02             →  20 min
Capsule 03             →  30 min + practice
Capsule 04             →  20 min
Capsule 05             →  20 min + exercises
Project (06)           →  3-4 hrs

Total: ~5-6 hours

Additional Resources

  1. Strangler Fig Pattern - Martin Fowler - The original gradual migration pattern
  2. FastAPI Documentation - Official FastAPI documentation
  3. Flask Documentation - Official Flask documentation
  4. Migrating Flask to FastAPI - Real Python - Practical migration guides
  5. Database Migrations with Alembic - For schema migrations that accompany the framework change
  6. Feature Flags for Safe Migrations - Feature flags as a gradual migration tool

Module 5, Capsule 01 — Refactoring & Legacy Code with Claude Code Guide