Technical Case Study of Migrating a Transaction System from Windows/.NET/SQL Server to Linux/Java/MySQL

This article presents a comprehensive technical case study of a large‑scale migration that replaces a Windows/.NET/SQL Server stack with a Linux/Java/MySQL architecture, detailing system decomposition, order service redesign, code conversion scripts, data synchronization challenges, testing strategies, deployment and rollback procedures.

Hujiang Technology
Hujiang Technology
Hujiang Technology
Technical Case Study of Migrating a Transaction System from Windows/.NET/SQL Server to Linux/Java/MySQL

Background

The company needed to move from a Windows system deployment, .NET development, and SQL Server database to an open‑source stack based on Linux, Java, and MySQL to reduce technical debt and support scaling.

System Overview

Domain Division

Order domain – order query, creation, modification, delivery, amount allocation, reconciliation.

Marketing domain – product management, coupon management, promotion rules, rule engine.

Settlement domain – merchant management, contracts, billing rules, clearing, distribution.

After‑sale domain – reverse refunds and returns.

Order Service Flow

Validate order creation parameters.

Fetch product, user, order tracking, and settlement information.

Load promotions and coupon data, calculate marketing rules (moved to the marketing system).

Populate order context, compute amounts, and validate.

Concurrent check for coupon usage.

Persist order data using step‑wise transactions.

Payment notification (zero‑amount direct payment).

Publish order‑creation‑complete message via MQ.

After refactoring, the order service achieved ~870 TPS under a pressure test.

Migration Practices

Data Isolation and Service‑ification

All direct database accesses (e.g., Kettle extracts) were replaced with service APIs to avoid coupling and simplify future migrations.

Bulk Code Conversion

a) Python script to convert .NET entity classes to Java

def processConvertJavaByDir(paths, namespace):
    list = os.listdir(paths)
    for i, file in enumerate(list):
        subpath = os.path.join(paths, file)
        if os.path.isdir(subpath):
            processConvertJavaByDir(subpath, namespace)
        elif os.path.isfile(subpath) and subpath.endswith(".cs"):
            targetContent = genTargetContent(subpath, namespace)
            targetFile = os.path.join(paths, file.replace(".cs", ".java").replace("Entity", "Bo"))
            if os.path.isfile(targetFile):
                os.remove(targetFile)
            open(targetFile, mode='w', encoding='utf-8').write(targetContent)

b) PO entity and DAO method batch replacement using markers

@Data
@EqualsAndHashCode(callSuper = true)
public class OrderConfigPo extends BasePo {
    /*<AUTOGEN--BEGIN>*/
    /**
     * Primary key
     */
    private Long id;
    /**
     * Config key
     */
    private String key;
    /*<AUTOGEN--END>*/
    public ShopConfigBaseBo toShopConfigBase(){
        return this.toShopConfigBase(this);
    }
}

Compatibility Guarantees

Ensured API request/response signatures, default values, and field types remain identical between .NET and Java services. For example, C# int fields were mapped to Java Integer (nullable) and null values were omitted during serialization.

Data Synchronization

Used Alibaba open‑source middleware DataX for full‑load and Yugong for incremental sync between MySQL and SQL Server. Custom interceptors handled millisecond truncation, default column values, composite primary keys, and URL case‑insensitivity.

Testing and Validation

Parallel .NET and Java service calls compared input/output parameters via Python scripts.

SQL scripts compared row‑level data between source and target databases.

Automated scripts run_yugong_import.sh and run_only_check.sh performed full sync and validation respectively.

Deployment and Rollback

During the cut‑over, a one‑hour database downtime was allocated. Steps included:

Full sync of orders with IDs ≥ 12001 from SQL Server to MySQL using DataX.

Adjust MySQL auto‑increment to 13000.

Switch API Gateway to Java services, start MySQL, then resume incremental sync with Yugong.

Rollback involved stopping MySQL writes, running Yugong to sync back to SQL Server, adjusting SQL Server auto‑increment, and switching the gateway back to .NET.

Conclusion

The migration, dubbed “去Windows化”, was completed in 2.5 hours (well under the planned 6.5 hours) with no major bugs or rollbacks, demonstrating a successful large‑scale backend transformation.

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.

MigrationSystem ArchitectureData Synchronization
Hujiang Technology
Written by

Hujiang Technology

We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.

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.