Modular Monolith: Giải Pháp Giữa Microservice Và Monolith
Modular Monolith: Giải Pháp Giữa Microservice Và Monolith
Có một câu hỏi mình nhận được đều đặn mỗi khi ai đó chuẩn bị build sản phẩm mới: "Nên chọn Microservice hay Monolith?" Câu trả lời thật của mình sau 15 năm làm phần mềm, hơn 10 năm trong đó bảo trì các hệ thống .NET từ bản 1.0 lên tới 10.0, là: cả hai đều sai nếu chọn sai thời điểm.
Microservice quá cồng kềnh để bắt đầu. Monolith thì lại dễ trở thành cái bẫy khi sản phẩm bắt đầu có user thật. Vấn đề không nằm ở việc chọn phe nào, mà ở việc thiết kế sao để giai đoạn đầu chạy nhanh, còn giai đoạn sau vẫn tách được mà không phải viết lại từ đầu.
Vì sao Microservice quá nặng để bắt đầu một sản phẩm mới
Microservice hứa hẹn scale tốt, deploy độc lập, team nào lo phần đó. Nhưng cái giá phải trả ở ngày đầu tiên là rất thật: setup service discovery, cấu hình message queue, viết contract giao tiếp giữa các service, dựng CI/CD riêng cho từng service, rồi lo thêm việc đồng bộ dữ liệu khi một nghiệp vụ chạy qua 3-4 service khác nhau.
Với một sản phẩm còn chưa biết có ai dùng hay không, phần lớn thời gian tuần đầu tiên sẽ trôi vào việc dựng hạ tầng thay vì viết tính năng lõi. Đây chính là lý do nhiều dự án MVP chết yểu trước khi kịp có feedback đầu tiên từ user — không phải vì ý tưởng dở, mà vì mất quá nhiều thời gian mới chạm được vào phần tạo ra giá trị thật.
Monolith cũng có giới hạn riêng khi hệ thống lớn lên
Ngược lại, Monolith giúp bắt đầu cực nhanh — một project, một database, code chung một chỗ. Nhưng vấn đề xuất hiện không phải ở ngày đầu, mà ở giai đoạn logic nghiệp vụ bắt đầu phình to.
Khi module gửi email bỗng nhiên bị gọi tải cao gấp 10 lần các phần còn lại, hoặc module thanh toán cần tách riêng để đảm bảo uptime cao hơn phần còn lại của hệ thống, đó là lúc Monolith bộc lộ điểm yếu: code các module đã đan xen nhau qua nhiều tầng, share chung DB context, gọi thẳng class của nhau thay vì qua interface rõ ràng. Tách ra lúc này không còn là refactor, mà gần như viết lại.
Modular Monolith hướng Microservice: hướng hybrid cân bằng nhất
Cách mình thấy cân bằng nhất giữa hai thái cực trên là thiết kế Monolith nhưng tổ chức theo tư duy Microservice ngay từ đầu — gọi là Modular Monolith. Ý tưởng cốt lõi: giữ một codebase, một lần deploy, nhưng ranh giới giữa các phần nghiệp vụ phải rõ ràng như thể chúng là các service độc lập.
Bốn nguyên tắc thiết kế cụ thể:
Database tách sẵn Schema theo Bounded Context — mỗi nghiệp vụ (Identity, Billing, Tenancy...) có schema riêng, không JOIN chéo giữa các schema. Sau này cần tách DB riêng cho một module, việc migrate dữ liệu nhẹ nhàng hơn nhiều so với gỡ dữ liệu ra khỏi một database dùng chung.
Source code tách module theo Bounded Context — mỗi module có Clean Architecture riêng hoàn chỉnh (Domain, Application, Infrastructure, API), có endpoint riêng như một microservice thật sự, chỉ khác là đang chạy chung trong một process.
Giao tiếp nội bộ giữa các module qua Interface + Contract project chung, inject lúc runtime — không qua Queue, không qua HTTP call nội bộ. Khi cần tách một module ra thành service riêng, chỉ cần đổi phần implement của interface từ gọi trực tiếp sang gọi qua HTTP hoặc message broker, phần code nghiệp vụ bên trong module gần như không phải sửa.
Chỉ share phần thực sự dùng chung: Infrastructure (email, storage, caching, các integration bên thứ ba) và Shared Kernel (các value object, exception, base class dùng chung). Mọi thứ khác đều thuộc về module của nó, không lấn sang module khác.
Cách tổ chức này giữ được tốc độ phát triển của Monolith — một lần build, một lần deploy, không phải lo network latency giữa các service khi đang còn ít user. Nhưng khi cần tách, ranh giới đã có sẵn từ ngày đầu, việc tách chỉ là thay đổi implementation của một interface chứ không phải mổ xẻ lại toàn bộ kiến trúc.
TEDU áp dụng framework này vào TEDUOS như thế nào
Đây không phải lý thuyết suông. TEDU đúc rút cách tổ chức này thành framework nội bộ tên TEDUOS, dùng .NET 10 và React, sau khi trải qua cả hai thái cực Microservice lẫn Monolith trên nhiều dự án thực tế.
TEDUOS có sẵn ba module bắt buộc mà gần như sản phẩm SaaS nào cũng cần: Tenancy, Identity, Billing — mỗi module đóng gói trọn vẹn theo đúng bốn nguyên tắc ở trên. Khi cần thêm module nghiệp vụ mới, có sẵn script dựng khung module tự động, sinh kèm cả bộ test để đảm bảo module mới không phá vỡ ranh giới kiến trúc đã định — tức là không lo về sau code viết lệch chuẩn vì mỗi người một kiểu.
Với một sản phẩm mới, việc có sẵn walking skeleton dạng này giúp bỏ qua toàn bộ giai đoạn "dựng nền móng" — vốn thường chiếm vài tuần đầu tiên của bất kỳ dự án SaaS nào — để đi thẳng vào viết nghiệp vụ đặc thù của sản phẩm.
Kết luận
Câu hỏi đúng không phải là "Microservice hay Monolith", mà là "làm sao để hôm nay chạy nhanh, còn ngày mai vẫn tách được mà không phải đập đi xây lại". Modular Monolith hướng Microservice giải quyết đúng bài toán đó: một codebase để phát triển nhanh, nhưng ranh giới rõ ràng đủ để tách bất kỳ module nào thành service riêng khi hệ thống thực sự cần.
Bạn nào đang phân vân giữa Microservice và Monolith cho sản phẩm sắp build, cứ inbox mình để chia sẻ thêm chi tiết về cách tổ chức module, cách generate module mới, hoặc cách TEDUOS xử lý phần Tenancy và Billing.
Bài viết liên quan
Comprehensive Developer – Định nghĩa một thế hệ lập trình viên toàn diện
Comprehensive Developer (cDev) là một lập trình viên có khả năng làm việc xuyên suốt toàn bộ vòng đời của một sản phẩm phần mềm.
Đọc thêm
Các Kỹ Năng Quan Trọng Của Một Technical Leader Trong Dự Án IT
Technical Leader (Tech Lead) là người chịu trách nhiệm dẫn dắt đội ngũ kỹ thuật trong dự án IT, đảm bảo các quyết định công nghệ phù hợp với yêu cầu kinh doanh và khả năng triển khai của nhóm.
Đọc thêmTại sao một cái cây cao thường rễ sâu?
Một cái cây muốn mọc cao thường bộ rễ phải đâm sâu vào lòng đất. Một người làm nghề phải hiểu sâu trước khi hiểu rộng.
Đọc thêm
Nguyên nhân nào khiến bạn làm lập trình lâu rồi vẫn chưa giỏi?
Bạn đã có "thâm niên" trong nghề lập trình nhưng vẫn thấy mình chưa giỏi để có thu nhập cao hay đảm nhiệm những vị trí quan trọng?
Đọc thêm
Kế hoạch phát triển khóa học 2021
TEDU xin gửi tới các bạn bản kế hoạch phát triển khóa học năm 2021.
Đọc thêm
Làm sao để làm việc nhóm cho tốt?
Chia sẻ các vấn đề hay gặp và kinh nghiệm làm sao để làm việc nhóm cho tốt trong TEAM đặc biệt là team làm phần mềm trong lĩnh vực IT.
Đọc thêm
Định hướng nghề nghiệp cho các bạn muốn học CNTT
Một vài chia sẻ cho các bạn trẻ muốn hay có ý thích học ngành công nghệ thông tin đứng từ góc nhìn người đang làm nghề.
Đọc thêm
Kế hoạch phát triển TEDU năm 2020
TEDU xin gửi tới tất cả mọi người kế hoạch ra khóa học 2020 và các bổ sung cập nhật trên hệ thống TEDU để mọi người tiện theo dõi.
Đọc thêm
Senior khác Junior ở điểm gì? Và lộ trình để từ Junior lên Senior.
Làm sao để lên senior developer? Dựa vào hiểu biết và kinh nghiệm của mình sẽ chia ra một số quan điểm đúc kết lại trong bài viết để hy vọng giúp các bạn có thêm thông tin tham khảo giúp ích cho career path của mình.
Đọc thêm
Lộ trình trở thành một Java Web Developer
Và hiển nhiên trở thành một Java Developer cũng giúp bạn có rất nhiều lợi thế trong nghề nghiệp của mình.
Đọc thêm