Why and How to Split Monolithic Applications: A Practical Guide

This article explains why monolithic applications need to be split, outlines the preparatory steps for understanding business complexity and defining service boundaries, and provides detailed practical guidance on database vertical and horizontal splitting, global ID generation, migration, cut‑over strategies, consistency, and post‑split stability.

ITFLY8 Architecture Home
ITFLY8 Architecture Home
ITFLY8 Architecture Home
Why and How to Split Monolithic Applications: A Practical Guide

Why Split?

Applications become tightly coupled over time, with the same functionality duplicated across many services, making any change require modifications in every application. Business extensibility suffers because data models support only a single business type, leading to delays when new types appear. Legacy code accumulates scattered if‑else logic, creating maintenance nightmares. System scalability degrades as both applications and databases struggle to handle rapid growth, and the accumulation of technical debt eventually threatens system viability.

Preparation Before Splitting

Understanding Business Complexity : Assess the relationship between the system and its business domains. Treat the system like a heart‑pacemaker: the more business it supports, the tighter the coupling, and reckless changes can damage the core.

Gather technical insights through discussions with product managers and developers to learn each application's domain model, strengths, and weaknesses. Complement this with hands‑on practice—requirements, refactoring, and optimization—to grasp code and architecture details.

Defining Service Boundaries : Aim for high cohesion, low coupling, and single responsibility. Use the “Hulu brothers” analogy—each service should have independent capabilities yet be able to combine into a unified platform.

Determine the granularity of boundaries by balancing business scenarios, goals, and timelines; start with broader boundaries and refine as the system evolves.

Setting Post‑Split Goals : Clearly state what each split service should achieve (e.g., separating DB and application in phase 1, redesigning the data model in phase 2) to avoid endless deepening of the split.

Assessing Current Architecture : Evaluate the existing architecture, codebase, and dependencies, and anticipate possible failure modes before starting the work.

Practical DB Splitting

Vertical vs. Horizontal Splitting : Vertical splitting moves tables into separate databases based on functional domains (e.g., messages vs. organization). Horizontal splitting shards large tables (e.g., a message table with millions of rows) across multiple databases.

Global ID Generation : Replace auto‑increment primary keys with a globally unique ID generator (e.g., Snowflake, a dedicated MySQL table, or Alibaba’s tddl‑sequence) to avoid key collisions during migration and rollback.

Global ID generation
Global ID generation

Migration Steps :

Create new tables with utf8mb4 charset and proper indexes.

Perform full data sync during low‑traffic windows, then use binlog‑based incremental sync tools (e.g., Alibaba Canal or Otter).

Ensure binlog positions are captured before the full sync to avoid data loss.

SQL Refactoring for Cross‑Database Joins : Since cross‑database joins are unsupported, refactor join queries by reducing coupling, using global tables, adding redundant fields, or performing in‑memory joins via RPC or local caches.

Cut‑Over Strategies

Stop‑Write (DB‑downtime) Approach : Quickly switch traffic by stopping writes, but carries high rollback risk and limited verification points.

Dual‑Write Approach : Write to both old and new tables for a short period, then disable binlog sync. This reduces risk and allows easier rollback, though it adds latency and operational steps.

Ensuring Consistency After Split

Distributed transactions are generally avoided due to performance. Instead, use message‑based compensation, scheduled compensation jobs, or a combination to achieve eventual consistency.

Maintaining Stability Post‑Split

Defensive Programming : Implement fallback strategies, set timeouts, and convert strong dependencies to weak ones.

Interface Design : Expose minimal, well‑designed APIs to prevent misuse; apply rate limiting and capacity controls per service.

Operational SOPs : Prepare clear rollback plans, monitor resource usage (CPU, memory, DB, cache), and automate cleanup of legacy technical debt.

Conclusion

Successful application splitting requires thorough preparation, incremental and testable steps, robust migration tooling, and disciplined post‑split operations. Anticipate Murphy’s Law, create SOPs, and treat each large‑scale refactor as an opportunity to strengthen the 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.

BackendmigrationMicroservicesConsistencyID generationdatabase-splittingoperational-stability
ITFLY8 Architecture Home
Written by

ITFLY8 Architecture Home

ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.

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.