Bỏ qua menu, vào nội dung chính

Vì sao doanh nghiệp nhỏ không cần microservices: monolith đủ dùng tới đâu

Microservices giải bài toán của tổ chức có nhiều đội phát triển cần triển khai độc lập. Với doanh nghiệp nhỏ và vừa, kiến trúc này nhân chi phí vận hành, độ trễ và số điểm có thể hỏng. Bài so sánh monolith, modular monolith và microservices bằng số đo thật, kèm những thành phần ALODEV từng dựng sẵn rồi phải gỡ.

11 phút đọc

Doanh nghiệp nhỏ không cần microservices vì kiến trúc này giải một bài toán họ không có: nhiều đội phát triển lớn cần triển khai phần của mình mà không chờ nhau. Với phần mềm do một đội từ ba tới mười người làm, một chương trình duy nhất (monolith) chia module rõ ràng triển khai một lần, dùng một cơ sở dữ liệu, sao lưu một chỗ, và khi lỗi thì tìm ở một nơi. Microservices biến mỗi module thành một dịch vụ riêng: thêm máy chủ, thêm đường mạng, thêm chỗ giám sát, thêm cách hỏng.

Bài này dành cho chủ doanh nghiệp đang đọc một bản đề xuất có chữ "kiến trúc microservices" và muốn biết đó là ưu điểm hay chi phí. Số đo và ví dụ lấy từ ALODEV AIO, hệ thống nội bộ của ALODEV viết bằng Go, chạy dưới dạng một chương trình duy nhất.

Monolith và microservices khác nhau ở ranh giới triển khai

Monolith là một chương trình chứa mọi chức năng: chấm công, lương, hợp đồng, thông báo. Các phần gọi nhau bằng lời gọi hàm trong bộ nhớ và cùng đọc ghi một cơ sở dữ liệu. Microservices tách mỗi chức năng thành một chương trình riêng, thường có cơ sở dữ liệu riêng, gọi nhau qua mạng bằng HTTP, gRPC hoặc hàng đợi tin nhắn. Kích thước mã không phải điểm phân biệt: một monolith có thể có hàng trăm nghìn dòng mà vẫn gọn gàng.

Ở giữa có modular monolith: vẫn một chương trình, nhưng mã được chia module với ranh giới rõ, module này chỉ gọi module kia qua một lối vào định sẵn. Khi thật sự cần tách một module ra thành dịch vụ riêng, ranh giới đã có sẵn.

Ba kiến trúc nhìn từ phía doanh nghiệp vận hành phần mềm.
Tiêu chíMonolithModular monolithMicroservices
Số chương trình phải triển khai11Một cho mỗi dịch vụ, thường 5-50
Cơ sở dữ liệu11, chia schema theo moduleThường một cho mỗi dịch vụ
Giao dịch nhiều bước (chấm công rồi tính lương)Một transactionMột transactionPhải thiết kế bù trừ khi một bước lỗi
Tìm lỗiMột nhật kýMột nhật kýCần truy vết xuyên dịch vụ
Sao lưuMột chỗMột chỗNhiều chỗ, phải khớp thời điểm
Đội phát triển phù hợp1-5 người3-30 ngườiNhiều đội độc lập
Mở rộng khi tải tăngNhân cả chương trìnhNhân cả chương trìnhNhân riêng phần nặng

Mỗi lần gọi qua mạng đắt gấp hàng trăm nghìn lần

Trong monolith, module lương hỏi module chấm công bằng một lời gọi hàm. Trong microservices, câu hỏi đó thành một yêu cầu mạng: đóng gói dữ liệu, gửi, chờ, giải mã. ALODEV đo cùng một phép tính lương nhỏ theo ba cách.

Biểu đồ thang logarit: gọi hàm 0,19 ns, gọi hàm có JSON 660 ns, gọi qua HTTP trên cùng máy 65.000 ns
Benchmark Go ngày 25/09/2026: gọi hàm trực tiếp gần như không tốn thời gian (0,19 ns, trình biên dịch tối ưu gần hết), thêm bước đóng gói JSON tốn khoảng 660 ns, gọi qua HTTP trên cùng một máy tốn khoảng 65.000 ns. Chưa tính mạng thật giữa hai máy chủ.

65 micro giây nghe nhỏ. Vấn đề là nó nhân lên. Một màn hình phần mềm doanh nghiệp thường gọi 10-20 API, mỗi API ở kiến trúc microservices có thể kéo theo vài lời gọi nội bộ giữa các dịch vụ, và mỗi lời gọi là một chỗ có thể chậm hoặc hỏng. Khi đường đi qua mạng thật, con số lớn hơn nhiều: ALODEV đo ngày 15/09/2026, backend AIO trả lời trong 0,8 ms nhưng mỗi lời gọi đi qua đường hầm Cloudflare mất 0,4 đến 4,6 giây. Người dùng cảm nhận độ trễ của cả chuỗi, không riêng khâu nhanh nhất.

Mỗi dịch vụ thêm là một thứ phải nuôi

Chi phí lớn nhất của microservices không nằm ở độ trễ mà ở vận hành. Mỗi dịch vụ cần được triển khai, giám sát, sao lưu, nâng phiên bản và có người hiểu nó. ALODEV có bằng chứng từ chính hệ thống của mình, dù AIO chưa từng là microservices: chỉ riêng các thành phần hạ tầng dựng sẵn "cho sau này" đã thành chi phí.

  • ClickHouse, cơ sở dữ liệu phân tích, được dựng và chạy suốt, được giám sát và sao lưu. Kiểm ngày 26/08/2026: không một dòng mã nào kết nối tới nó, bảng rỗng. Nhật ký sao lưu cho thấy thư mục dữ liệu của chính dịch vụ này nằm trong phần bị nén mỗi đêm, đúng đợt bản sao lưu phình từ 4 GB lên 49 GB và làm đầy đĩa ngày 11/09/2026.
  • Máy chủ gRPC nhận dữ liệu từ phần mềm theo dõi máy tính: phần mềm đó bị huỷ ngày 26/08/2026. Đo trước khi gỡ, cổng vẫn mở nhưng không có một kết nối nào, bốn bảng nó ghi vào đều rỗng. Mã bị xoá hẳn ngày 08/09/2026.
  • Nhiều tác vụ nền đọc dữ liệu từ nguồn đã chết vẫn chạy đều đặn mỗi giờ hoặc mỗi năm phút, không lỗi, không ra kết quả. Đợt dọn ngày 06-08/09/2026 xoá ít nhất năm tác vụ như vậy.

Trong một chương trình duy nhất, những thứ thừa này còn tìm ra được bằng cách đọc mã. Khi mỗi thứ là một dịch vụ riêng trên máy riêng, chúng dễ sống mãi vì không ai dám tắt thứ mình không hiểu.

Một chương trình vẫn làm được nhiều việc song song

Lý do hay được nêu để tách dịch vụ là "tác vụ nền không được làm chậm API". Với ngôn ngữ có xử lý đồng thời tốt như Go, điều đó không cần tách chương trình. Backend AIO chạy bảy tác vụ nền (nhắc việc chờ duyệt quá hạn, kiểm toàn vẹn dữ liệu, lặp lịch họp, dọn nhật ký...) cùng máy chủ API trong một tiến trình.

Mã main.go của ALODEV AIO khởi động các tác vụ nền bằng goroutine và máy chủ REST trong cùng tiến trình
Cuối hàm main của backend ALODEV AIO: vòng for khởi động từng tác vụ nền thành một goroutine, rồi chạy máy chủ API. Khi nhận lệnh dừng, chương trình cho các yêu cầu đang xử lý 10 giây để hoàn tất. Toàn bộ là một tệp chạy khoảng 19 MB.

Một chương trình và một cơ sở dữ liệu còn giữ được tính nhất quán dễ dàng. Trong AIO, dữ liệu chấm công thiếu ngày đi thẳng vào phép tính lương thành khoản trừ thật, vì hai module đọc cùng một cơ sở dữ liệu. Ở kiến trúc microservices với dịch vụ chấm công và dịch vụ lương riêng, cùng luồng đó cần thiết kế cho trường hợp một bên cập nhật xong, bên kia lỗi giữa chừng.

Monolith có rủi ro riêng: mã dồn vào một chỗ nếu không giữ kỷ luật. AIO là ví dụ trung thực.

Biểu đồ số dòng mã theo package của backend ALODEV AIO, package rest chiếm 97.127 trên 103.785 dòng
Số dòng Go theo package của backend ALODEV AIO ngày 25/09/2026: package rest chứa 97.127 trên 103.785 dòng (93,6%). Các module nghiệp vụ tách theo tệp bên trong package này. Chia thành các package nhỏ hơn là việc nên làm trước khi tính tới tách dịch vụ.

Điều này cho thấy thứ tự đúng: khi monolith khó bảo trì, bước đầu tiên là chia module rõ hơn bên trong chương trình. Chỉ khi một module có lý do cụ thể để chạy riêng thì mới tách nó ra.

Các công ty lớn cũng quay về

Martin Fowler, một trong những người phổ biến khái niệm microservices, viết bài MonolithFirst năm 2015 với nhận xét rằng gần như mọi câu chuyện microservices thành công đều bắt đầu từ một monolith quá lớn rồi được tách ra, còn hệ thống xây microservices ngay từ đầu thường gặp rắc rối nghiêm trọng. Năm 2023, đội kỹ thuật Prime Video công bố đã chuyển dịch vụ giám sát chất lượng video từ kiến trúc phân tán sang chạy trong một tiến trình, giảm chi phí hạ tầng của dịch vụ đó 90%. Hai nguồn tra ngày 25/09/2026.

Cần đọc đúng trường hợp Prime Video: đó là một dịch vụ cụ thể, phần còn lại của Amazon vẫn dùng dịch vụ tách rời. Bài học là tách hay gộp phải dựa trên đo đạc chi phí thật, không theo xu hướng.

Khi nào microservices đáng giá

  • Có nhiều đội phát triển, mỗi đội phụ trách một mảng và cần phát hành độc lập mà không chờ nhau.
  • Một phần hệ thống có tải khác hẳn phần còn lại: xử lý video, nhận diện khuôn mặt, chạy mô hình AI. Tách riêng phần đó để nhân lên hoặc chạy trên máy có GPU.
  • Một phần phải viết bằng ngôn ngữ khác vì thư viện: ví dụ phần học máy bằng Python đặt cạnh backend Go.
  • Có yêu cầu cô lập về bảo mật hoặc pháp lý: dữ liệu thanh toán, dữ liệu sinh trắc học phải nằm ở hệ thống riêng với quyền truy cập riêng.

Để ý rằng các trường hợp trên thường chỉ cần tách một hoặc hai dịch vụ ra khỏi monolith, không cần chuyển cả hệ thống sang microservices.

Khi nào KHÔNG nên dùng microservices

  • Đội phát triển dưới khoảng mười người, hoặc một đơn vị thuê ngoài làm toàn bộ.
  • Sản phẩm đang tìm hướng, nghiệp vụ còn đổi hằng tháng: ranh giới dịch vụ vẽ sớm thường vẽ sai, và dời ranh giới giữa hai dịch vụ tốn hơn nhiều so với dời mã giữa hai module.
  • Không có người vận hành hạ tầng: mỗi dịch vụ là một thứ phải triển khai, giám sát, nâng cấp.
  • Ngân sách hạ tầng cần dự đoán được: nhiều dịch vụ nghĩa là nhiều máy, nhiều đường truyền và hoá đơn khó đoán hơn.
  • Lý do duy nhất là "để sau này mở rộng": một monolith viết đúng trên máy chủ tốt phục vụ được lượng người dùng lớn hơn nhiều so với nhu cầu của doanh nghiệp vừa.

Hỏi gì khi bản đề xuất ghi "kiến trúc microservices"

  1. Hệ thống gồm bao nhiêu dịch vụ, mỗi dịch vụ chạy ở đâu, và ai giám sát từng cái sau khi bàn giao?
  2. Khi một dịch vụ dừng, những màn hình nào ngừng hoạt động?
  3. Sao lưu các cơ sở dữ liệu của từng dịch vụ thế nào để phục hồi về cùng một thời điểm?
  4. Chi phí hạ tầng hằng tháng khác bao nhiêu so với phương án một chương trình?
  5. Vì sao phương án modular monolith không đủ cho quy mô của chúng tôi?

Một đơn vị có lý do thật sẽ trả lời được câu cuối bằng con số hoặc bằng một yêu cầu cụ thể của doanh nghiệp. Câu trả lời chung chung về "khả năng mở rộng" là dấu hiệu nên hỏi thêm.

Câu hỏi thường gặp

Monolith là gì?

Monolith là kiến trúc trong đó toàn bộ chức năng của phần mềm nằm trong một chương trình, triển khai một lần và thường dùng một cơ sở dữ liệu. Đây là kiến trúc mặc định hợp lý cho phần lớn phần mềm doanh nghiệp nhỏ và vừa.

Monolith có mở rộng được khi công ty lớn lên không?

Có. Monolith mở rộng bằng cách chạy nhiều bản sao phía sau bộ cân bằng tải và nâng cấp cơ sở dữ liệu. Khi một phần có tải đặc biệt, tách riêng phần đó; không cần tách cả hệ thống.

Microservices có an toàn hơn monolith không?

Không tự nhiên an toàn hơn. Nhiều dịch vụ nghĩa là nhiều cổng mạng, nhiều thông tin xác thực giữa các dịch vụ và nhiều chỗ phải vá. Cô lập chỉ có lợi khi được thiết kế cho một loại dữ liệu nhạy cảm cụ thể.

Modular monolith khác monolith thường ở điểm nào?

Modular monolith chia mã thành các module có ranh giới rõ, module chỉ gọi nhau qua lối vào định sẵn. Nhờ vậy mã dễ bảo trì hơn và khi cần, một module có thể tách thành dịch vụ riêng mà không phải viết lại.

Đang dùng microservices mà thấy tốn kém thì có nên gộp lại không?

Nên đo trước: chi phí hạ tầng từng dịch vụ, số sự cố do lời gọi giữa dịch vụ, thời gian đội dành cho vận hành. Gộp những dịch vụ luôn triển khai cùng nhau và gọi nhau liên tục thường mang lại lợi ích rõ nhất.

Bài viết liên quan

Ký sự lập trình
Ký sự lập trình11 phút đọc

Môi trường staging là gì, vì sao phần mềm doanh nghiệp phải có

Staging là bản sao chạy thử của phần mềm, giống hệ thống thật nhưng có dữ liệu riêng, để mọi thay đổi được đo trước khi chạm vào người dùng. Google SRE ghi khoảng 70% sự cố đến từ thay đổi trên hệ thống đang chạy. Bài giải thích staging khác bản xem thử ở đâu, bốn sự cố ALODEV gặp khi ranh giới staging và production bị lẫn, và những câu cần hỏi đơn vị làm phần mềm.

Ký sự lập trình11 phút đọc

Viết phần mềm theo yêu cầu: vì sao vẫn cần khi SaaS tràn ngập

Doanh nghiệp lớn trung bình dùng 305 ứng dụng SaaS và bỏ phí 36% giấy phép. Viết phần mềm theo yêu cầu vẫn cần cho phần quy trình làm nên khác biệt của công ty, phần mà gói có sẵn không diễn đạt được. Bài giải thích chỗ nào nên mua, chỗ nào nên may đo, cái giá thật của phần mềm riêng, và cách chia đôi hợp lý, kèm số đo từ phần mềm nội bộ của ALODEV.

Ký sự lập trình10 phút đọc

PHP và Laravel năm 2026: vì sao vẫn sống và khi nào doanh nghiệp nên chọn

PHP vẫn chạy khoảng 70% website có ngôn ngữ máy chủ nhận diện được, Laravel ra bản lớn mỗi năm và cam kết vá bảo mật hai năm cho từng bản. Bài giải thích vì sao PHP chưa chết, Laravel hợp với loại dự án nào, khi nào nên chọn ngôn ngữ khác, và những câu cần hỏi đơn vị làm phần mềm trước khi ký.

Nhận bài mới

Để lại email để nhận bài mới của series Ký sự lập trình, hoặc theo dõi bằng RSS.

RSS Ký sự lập trình

Email chỉ dùng để gửi bài mới, xem Chính sách bảo mật.

Trao đổi về dự án

Cần tư vấn?