Hiện đại hoá Legacy: Strangler Fig trong thực tế
Cách hiện đại hoá hệ legacy mà không cần rewrite big-bang. Pattern Strangler Fig, migration theo từng route, và bậc thang từ cũ sang mới qua 6-12 tháng.
Mục lục
- Khi nào hiện đại hoá thật sự trả lại giá trị?
- Cái giá khi để legacy ở lại là gì?
- Migration Strangler Fig trông thế nào?
- Timeline migration 12 tháng điển hình?
- Artifact theo dõi migration trông thế nào?
- Scale lên đa team ra sao?
- Hiện đại hoá có thể tự tạo ra những lỗi nào?
- Khi nào hiện đại hoá là câu trả lời sai?
- Đi tiếp từ đây như thế nào?
Một hệ chạy production mười năm xứng đáng được nghỉ hưu, không phải bị một dự án rewrite 6 tháng thất bại. Case study này cho thấy cách migration Strangler Fig ship giá trị mỗi quý, các artifact giúp giữ migration trung thực, và những bẫy có thể làm trật một dự án hiện đại hoá.
Khi nào hiện đại hoá thật sự trả lại giá trị?
Có ba tín hiệu chính.
Chi phí bảo trì đang tăng. Sửa bug lâu hơn; nhân viên mới ramp lâu hơn; tooling quanh legacy đã cũ (framework cũ, version ngôn ngữ cũ, vendor đã deprecate).
Tính năng mới bị chặn. "Không thêm được cái này nếu không refactor foundation X" - khi câu này được nói lần thứ ba, legacy không chỉ chậm bảo trì - nó đang chủ động ngăn các outcome nghiệp vụ.
Khó tuyển người. Engineer không muốn làm trên COBOL/PHP cũ/stack legacy. Tỉ lệ nghỉ tăng; thay người khó. Chi phí của legacy bao gồm cả chi phí không thể staff được.
Nếu bảo trì vẫn ổn, tuyển vẫn ổn, tính năng mới vẫn ship được, hiện đại hoá có thể chỉ là dự án khoe khoang. Hãy chạy lại bằng số.
Cái giá khi để legacy ở lại là gì?
Có ba kiểu lỗi cháy chậm.
Chi phí tăng dần. Mỗi năm legacy lại khó đổi hơn năm trước. Đến năm thứ 5 của câu "chúng ta sẽ hiện đại hoá năm sau", chi phí đã gấp đôi.
Chảy máu nhân tài. Engineer đáng lẽ lead hiện đại hoá thì rời đi vì không ai chịu làm. Đến giờ legacy có ít chuyên gia hơn và càng khó migrate hơn.
Lỗ hổng chiến lược. Đối thủ với stack hiện đại ship tính năng nhanh hơn. Legacy từng là lợi thế cạnh tranh giờ thành cái hào ngăn chính bạn cạnh tranh.
Migration Strangler Fig trông thế nào?
flowchart TB
Client[Client] --> Proxy[Tầng routing]
Proxy -->|Route A| New[Hệ mới<br/>xây song song]
Proxy -->|Route B và còn lại| Old[Hệ legacy<br/>vẫn phục vụ]
New --> NewDB[(Database mới)]
Old --> OldDB[(Database legacy)]
NewDB -.sync từ.- OldDB
Tầng routing (reverse proxy, feature flag, hoặc API gateway) gửi một vài route đến code mới và phần còn lại vẫn về legacy. Mỗi quý, thêm một số route được chuyển. Cuối cùng legacy không còn phục vụ gì nữa và được retire.
Timeline migration 12 tháng điển hình?
gantt
title Plan Strangler Fig 12 tháng
dateFormat YYYY-MM-DD
section Q1 Nền tảng
Tầng routing + observability :a1, 2026-07-01, 30d
Route đầu tiên migrate :a2, after a1, 30d
section Q2 Path đọc
Route nặng đọc (rủi ro thấp) :b1, 2026-10-01, 60d
Read replica từ DB legacy :b2, 2026-10-01, 30d
section Q3 Path ghi
Path ghi với dual-write :c1, 2027-01-01, 60d
Validate nhất quán :c2, after c1, 30d
section Q4 Retire
Route cuối migrate :d1, 2027-04-01, 60d
Decommission legacy :d2, after d1, 30d
Post-mortem + handover :d3, after d2, 30d
Quý 1 dùng để xây hạ tầng migration (routing, observability, data store song song). Quý 2 migrate các route nặng đọc (rủi ro thấp). Quý 3 migrate path ghi với dual-write để an toàn. Quý 4 retire legacy.
Artifact theo dõi migration trông thế nào?
# Tracker Hiện đại hoá — {{ Tên hệ }}
## Mục tiêu
Thay legacy {{ X }} bằng hệ mới {{ Y }} trước 2027-06-30.
## Tiến độ migration
| Route | Traffic cũ | Traffic mới | Trạng thái | Note |
|-------|------------|-------------|------------|------|
| GET /products | 0% | 100% | Đã migrate | Ổn từ Q2 |
| GET /products/:id | 0% | 100% | Đã migrate | Ổn từ Q2 |
| POST /orders | 90% | 10% | Đang làm | 10% canary; mở rộng Q3 |
| GET /reports | 100% | 0% | Chưa | Target Q4 |
| ... | | | | |
## KPI
- Traffic trên hệ mới: 35% (target cuối Q3: 60%)
- Tỉ lệ sự cố trên legacy: 0.3/tháng (cũ 0.4)
- Time-to-ship tính năng mới: 2 tuần (cũ 4 tuần cho team legacy)
## Rủi ro vận hành (RAID)
- R1: Edge case nhất quán dual-write phát hiện trong Q2
- R2: Một report legacy không có tài liệu schema
## Checklist decommission
- [ ] Mọi route ở 0% traffic legacy
- [ ] DB legacy last-modified > 30 ngày
- [ ] Code legacy archive sang repo read-only
- [ ] Rotation on-call bỏ legacy
- [ ] Server tắt
- [ ] Báo phần tiết kiệm chi phí cho sponsor
Tracker này được đính kèm status report cho buổi review của sponsor. Tiến độ quý nhìn thấy được là cách duy nhất để hiện đại hoá sống sót qua những lần đổi lãnh đạo.
Scale lên đa team ra sao?
flowchart TB
Mod[Team hiện đại hoá<br/>sở hữu routing + hệ mới] --> Team1[Team sản phẩm A<br/>dùng hệ mới]
Mod --> Team2[Team sản phẩm B<br/>migrate route của mình]
Mod --> Team3[Team sản phẩm C<br/>đóng góp domain]
Mod --> Sponsor[Review sponsor quý]
Một team hiện đại hoá riêng sở hữu migration; các team sản phẩm đóng góp chuyên môn domain. RACI cho team hiện đại hoá là Accountable cho migration, còn các team sản phẩm là Consulted.
Hiện đại hoá có thể tự tạo ra những lỗi nào?
- Migration mãi mãi. Dự án bước sang năm thứ 3 mà mới chạm 60% trên hệ mới. Cách phòng: có deadline decommission rõ; nếu không kịp tiến độ, cắt scope (route nào sẽ không migrate) và retire phần legacy đó đúng lịch.
- Hai hệ tồn tại mãi. Legacy cứ chạy vì có khách phụ thuộc; hệ mới không bao giờ thấy hoàn tất. Cách phòng: báo khách sớm; thông báo deprecation trước khi migration xong; sẵn lòng mất một vài khách legacy.
- Regression hiệu năng. Hệ mới chậm hơn legacy ở vài route. Cách phòng: có budget latency theo route trong observability; giữ khả năng rollback theo từng route.
- Mất kiến thức. Engineer biết legacy chi tiết rời đi trước khi migration xong. Cách phòng: pair họ với team migration; ghi lại kiến thức bộ lạc thành ADR (chương 19).
Khi nào hiện đại hoá là câu trả lời sai?
Có hai trường hợp.
Legacy thật sự đang ổn. Một hệ tẻ nhạt nhưng chạy tốt, chi phí bảo trì thấp, support ưu tiên nghiệp vụ - không cần hiện đại hoá. "Format lại file CSS mỗi năm một lần" không phải lý do đủ.
Không có team sẵn. Nếu không thể dành team riêng, đừng bắt đầu hiện đại hoá. Hiện đại hoá làm bằng nửa team sẽ kéo dài mãi và không giao gì.
Migration đáng 12-18 tháng khi legacy đang chủ động tốn tiền cho doanh nghiệp. Dưới ngưỡng đó, hãy để yên.
Đi tiếp từ đây như thế nào?
Case study cuối: dự án quản vendor - case khi phần lớn việc nằm ngoài team. Sau đó, các chương đóng meta (checklist, kết luận) sẽ khép lại series.