skipLink.label

Monolith Splitter

Monolith Splitter

hard 30-45 minutes

🎯 Learning Objectives

  • ✅ How to analyze a monolithic codebase and identify natural microservice boundaries
  • ✅ Why modules with shared dependencies should be grouped together, not split apart
  • ✅ How to determine domain-driven service groupings from dependency graphs
  • ✅ Why splitting by domain (business capability) is better than splitting by layer

📖 Concept: Monolith to Microservices

Monolith splitting คือการแบ่ง application ขนาดใหญ่ออกเป็น services เล็กๆ — เหมือนการแบ่งโรงยิมขนาดใหญ่ออกเป็นหลายห้อง训练 แต่ การ split ต้องทำอย่างถูกที่ — ถ้า split ผิดจุด คุณจะสร้าง distributed monolith ที่แย่กว่าเดิม

หลักการสำคัญ: SPLIT BY DOMAIN, NOT BY LAYER — services ควร ownership business capability (เช่น users, orders, inventory) ไม่ใช่แค่ technical layer (เช่น “database layer”, “API layer”). AI tools มักจะ split ทุก module เป็น service แยกกัน ซึ่งผิด — modules ที่ share dependencies ควรอยู่ด้วยกัน

Think of it like separating a multi-discipline martial arts school into specialized dojos — you group by fighting style (boxing, grappling, striking), not by equipment type (gloves room, mat room).

⚙️ How It Works

The Analysis Workflow

  1. Parse modules — extract name, dependencies, and routes
  2. Group by shared dependencies — modules with same dependencies = same service
  3. Assign domain reasons — each service needs a clear business justification
  4. Verify coverage — all modules must be accounted for

Dependency-Based Grouping

const modules = [
{ name: 'auth', dependencies: ['users-db'], routes: ['/login'] },
{ name: 'users', dependencies: ['users-db'], routes: ['/users'] },
{ name: 'orders', dependencies: ['orders-db', 'inventory-db'], routes: ['/orders'] },
{ name: 'inventory', dependencies: ['inventory-db'], routes: ['/inventory'] },
];
// Analysis:
// - auth + users both depend on users-db → same service
// - orders depends on orders-db + inventory-db → separate service
// - inventory depends on inventory-db → separate service
// Result:
[
{ service: 'service-1', modules: ['auth', 'users'], reason: 'User domain — shares user database' },
{ service: 'service-2', modules: ['orders'], reason: 'Order domain — shares order database' },
{ service: 'service-3', modules: ['inventory'], reason: 'Inventory domain — shares inventory database' }
]

The Critical Rule: Don’t Split Everything

// ❌ Naive AI: every module becomes its own service
[
{ service: 'service-1', modules: ['auth'] },
{ service: 'service-2', modules: ['users'] }, // WRONG! Shares users-db with auth
{ service: 'service-3', modules: ['orders'] },
{ service: 'service-4', modules: ['inventory'] }
]
// ✅ Correct: group by shared dependencies
[
{ service: 'service-1', modules: ['auth', 'users'] }, // CORRECT
{ service: 'service-2', modules: ['orders'] },
{ service: 'service-3', modules: ['inventory'] }
]

💡 Example: Walkthrough

const modules = [
{ name: 'auth', dependencies: ['users-db'], routes: ['/login'] },
{ name: 'users', dependencies: ['users-db'], routes: ['/users'] }
];
// Analysis:
// - Both modules depend on users-db
// - Same dependency → same service
// - Domain reason: "User domain — shares user database"
// Output:
[
{ service: 'service-1', modules: ['auth', 'users'], reason: 'User domain — shares user database' }
]

⚠️ Common Mistakes

Mistake 1: Splitting every module into its own service

“ทุก module = 1 service” → Modules ที่ share dependencies ต้องอยู่ด้วยกัน — มิฉะนั้นจะเกิด distributed monolith

Mistake 2: Not providing domain reasons

“Split แล้วแต่ไม่บอกว่าทำไม” → ทุก service ต้องมี reason ที่ชัดเจน — “User domain”, “Order domain”, ฯลฯ

Mistake 3: Missing modules in output

“บาง module หายไป” → ตรวจสอบว่า ทุก module ถูก account for ใน output

Mistake 4: Empty input crashes

“ไม่ได้ handle modules ว่าง” → Empty modules → return empty array

📝 Knowledge Check

📝 Knowledge Check

Q1:Modules that share the same database dependency should be:

Q2:What is the better approach for splitting a monolith?

Q3:Why must every service in the output have a `reason` field?

🏋️ Quest: Monolith Splitter

Now it’s time to practice! Identify microservice boundaries in a monolith.

  1. Download ไฟล์เริ่มต้นของ quest:

    Terminal window
    npx bluebeltdojo download quest-101-monolith-splitter
    cd quest-101-monolith-splitter
  2. เปิด problem.js ใน editor ของคุณพร้อมความช่วยเหลือของ AI

  3. Implement solution ตาม instructions ใน problem.js

  4. ตรวจสอบ solution ของคุณ:

    Terminal window
    node test.js
  5. ส่งคำตอบ:

    Terminal window
    npx bluebeltdojo submit

💡 Tip: ทดสอบ edge case — ตรวจสอบว่า modules ที่ share dependencies ถูก group เข้าด้วยกัน

คำใบ้

  • analyzeMonolith(modules) รับ array ของ modules และ return array ของ services
  • Modules ที่ share dependencies ต้องอยู่ใน service เดียวกัน
  • ทุก service ต้องมี service, modules, และ reason fields
  • ตรวจสอบว่าทุก module ถูก account for
  • ถ้าติดขัด ดู _solution/solution.js