How to Plan a Phased Migration and Ensure Data Consistency for Legacy System Refactoring

The article outlines a step‑by‑step architecture redesign for a 20‑year‑old monolithic production system, detailing problem analysis, a phased microservice migration using the "killer" pattern, data‑sync strategies, distributed transaction handling, observability, rollback mechanisms, and practical interview‑style insights.

Architectural Methodology
Architectural Methodology
Architectural Methodology
How to Plan a Phased Migration and Ensure Data Consistency for Legacy System Refactoring

01 Problem Analysis

The legacy core production system has been running for over 20 years, with tightly coupled modules, outdated technology stack, poor scalability, low concurrency, and high operational risk, making upgrades extremely difficult.

Key pain points identified are:

High coupling and unreasonable module boundaries.

Obsolete technology stack that cannot support containerization or service orchestration.

Slow performance, low concurrency, and low availability.

Large functional scope makes a full rewrite costly; a gradual replacement is preferred.

Architectural vision derived from these pain points includes:

Full microservice transformation guided by Domain‑Driven Design (DDD) to define bounded contexts such as Order, Product, User, Inventory, and Payment.

Upgrade to the Spring Cloud Alibaba ecosystem and adopt a DevOps platform.

Address non‑functional requirements: support 50 k QPS with 200 ms average response, use caching, async processing, rate‑limiting, and high‑availability patterns (K8s, auto‑scaling, gray‑release, canary, automatic rollback).

Introduce the "killer" pattern to replace modules incrementally while ensuring data consistency during coexistence.

02 Phased Migration Plan

(1) Preparation and Foundation

Service boundary identification : Apply DDD to extract aggregates and bounded contexts, sketching microservice boundaries for Order, Product, User, Inventory, Payment, etc.

Data model design : Define mapping between old monolithic tables and new service tables, add logical sharding tags, and plan CQRS/API combos for cross‑store queries.

Middleware selection : Deploy API gateway (Spring Cloud Gateway), service registry (Nacos), configuration center (Nacos), tracing (SkyWalking), message queues (Kafka, RocketMQ).

Dual‑write mechanism : Use Canal + Kafka to capture binlog from the legacy database and asynchronously write to new services.

(2) Replace Non‑Core Services First

Start with low‑risk, independent modules such as user profile management or notification service to build confidence and validate the new stack.

Strategy – Killer Pattern : Create new microservices that expose the same APIs, route a small portion of traffic to them, and gradually increase the share until the legacy module can be retired.

// Legacy system "seam" example (pseudo‑code)
public class LegacyReportService {
    // Old tightly‑coupled method
    // public Report generateReport(LegacyParams params) { ... }

    // Refactored version with feature toggle
    public Report generateReport(LegacyParams params) {
        if (FeatureToggle.isNewReportEnabled()) {
            // Call new modern report service API
            NewReportApiClient client = new NewReportApiClient();
            NewReportRequest request = convertParams(params);
            return client.generateReport(request);
        } else {
            // Fallback to legacy logic
            return legacyGenerateReport(params);
        }
    }
}

Parallel operation and traffic shifting are achieved by configuring the API gateway to direct a small percentage of requests to the new service, monitoring correctness, then scaling up to 100 %.

Data consistency checkpoint : When read‑write consistency reaches ≥99.99 %, traffic can be fully switched and the old service decommissioned.

(3) Core Service Extraction

Strategy – Anti‑Corruption Layer (ACL) : Build a façade that translates legacy interfaces (SOAP/RPC) into clean REST/GraphQL contracts, protecting new services from legacy complexity.

Key ACL design points:

Contract‑first API design using OpenAPI/Swagger.

Adapter pattern for protocol, data‑model, and error‑code conversion.

Caching with Redis or Memcached for read‑heavy data, with invalidation via CDC or message queues.

Strategy – API Facade : Aggregate calls to multiple legacy systems (e.g., order, logistics, payment) into a single endpoint, using CompletableFuture (Java) or Promise.all (Node.js) for parallelism, and integrate timeout and circuit‑breaker (Sentinel, Hystrix) for resilience.

(4) Full Cut‑over and Old System Retirement

Switching strategy : Canary traffic shifting combined with request mirroring; gradually increase traffic percentages (1 %, 10 %, 50 %, 100 %).

Fallback switch : Keep the monolith’s downgrade path; any anomaly triggers a one‑minute rollback to the old system.

After a stabilization period, the dual‑write can be disabled, and all reads/writes flow through microservices. A final full‑plus‑incremental data sync migrates remaining historical data.

03 Interview‑Style Takeaways

• Choose a non‑core, loosely coupled module as the first "killer" target to gain confidence.

• Identify clear integration points in the legacy code and insert thin API‑proxy layers that can be toggled on/off for rollback.

• Migrate core domains (order, payment, inventory) by first handling read scenarios, then extending to writes, using vertical sharding and Saga (Seata or event‑driven compensation) for eventual consistency.

• Implement bidirectional dual‑write: legacy writes to a message queue consumed by new services, and new services write back to the legacy DB via ETL/CDC tools.

• Develop a data‑reconciliation service that runs nightly (or on a custom schedule) to verify consistency between old and new stores; resolve mismatches before full cut‑over.

• After the new system runs in read‑only mode for a month (supporting reporting), decommission the legacy system.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

migrationcloud nativeMicroservicesKafkadata consistencyDDDCanalSaga
Architectural Methodology
Written by

Architectural Methodology

Guides senior programmers on transitioning to system architects, documenting and sharing the author's own journey and the methodologies developed along the way. Aims to help 20% of senior developers successfully become system architects.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.