Kiến trúc phần mềm là gì? 5 quyết định ảnh hưởng chi phí dài hạn
Năm quyết định kiến trúc quyết định chi phí ba năm của một hệ thống: ranh giới mô-đun, quyền sở hữu dữ liệu, đồng bộ hay bất đồng bộ, mô hình đa khách thuê, và môi trường chạy.

Mục lục bài viết
Trả lời nhanh
Kiến trúc phần mềm là tập hợp quyết định khó đảo ngược về ranh giới, dữ liệu và vận hành. Năm quyết định và chi phí ba năm của từng lựa chọn.
Kiến trúc phần mềm là tập hợp những quyết định khó đảo ngược về ranh giới thành phần, quyền sở hữu dữ liệu, cách các phần trao đổi và cách hệ thống chạy. Năm quyết định dưới đây quyết định phần lớn chi phí vận hành và chi phí thay đổi trong ba năm đầu.
Tóm tắt nhanh
- Kiến trúc không phải sơ đồ thành phần. Kiến trúc là những quyết định mà sửa sau sẽ tốn kém hơn nhiều so với làm đúng ngay từ đầu.
- Chi phí kiến trúc không hiện ra ở hoá đơn xây dựng. Nó hiện ra ở chi phí vận hành, ở thời gian thêm một chức năng, và ở số người cần có để giữ hệ thống chạy.
- Năm quyết định quan trọng nhất là: ranh giới mô-đun, quyền sở hữu dữ liệu, đồng bộ hay bất đồng bộ, mô hình đa khách thuê, và môi trường chạy kèm khả năng quan sát.
- Với phần lớn doanh nghiệp vừa, lựa chọn rẻ nhất trong ba năm là monolith mô-đun hoá, một cơ sở dữ liệu, và một môi trường chạy đơn giản. Không phải vì nó hiện đại, mà vì nó ít thứ phải vận hành.
Kiến trúc phần mềm là gì và không là gì
Kiến trúc phần mềm là cách chia một hệ thống thành các phần, cách các phần đó trao đổi, và cách dữ liệu được sở hữu. Ba câu đó nghe đơn giản nhưng chúng quyết định gần như toàn bộ chi phí dài hạn.
Kiến trúc không phải danh sách công nghệ. Một tài liệu ghi "dùng framework A, cơ sở dữ liệu B, hàng đợi C" không phải tài liệu kiến trúc. Nó là danh sách công cụ. Kiến trúc nói vì sao chia như vậy, phần nào sở hữu dữ liệu nào, và điều gì xảy ra khi một phần ngừng hoạt động.
Kiến trúc không phải sơ đồ để trình bày. Sơ đồ hữu ích, nhưng một sơ đồ không kèm lý do và không kèm ràng buộc sẽ bị hiểu sai theo nhiều cách khác nhau. Giá trị nằm ở phần chữ: quyết định nào đã chốt, quyết định nào còn mở, và giả định nào đang được dựa vào.
Kiến trúc không phải thứ làm một lần. Nó là một tập quyết định được ghi lại, và mỗi quyết định có ngày, có người quyết, và có điều kiện để xem lại. Một quyết định không có điều kiện xem lại là một quyết định sẽ bị giữ quá lâu.
Tiêu chí thực dụng để phân biệt: nếu một quyết định có thể đảo ngược trong một ngày làm việc, đó là quyết định triển khai, không phải quyết định kiến trúc. Nếu đảo ngược nó cần một quý và ảnh hưởng tới dữ liệu đã có, đó là quyết định kiến trúc.
Vì sao quyết định kiến trúc là quyết định chi phí
Chi phí của một hệ thống có bốn phần: chi phí xây dựng ban đầu, chi phí thêm chức năng, chi phí vận hành, và chi phí sửa khi hỏng. Kiến trúc ảnh hưởng mạnh nhất tới ba phần sau.
Chi phí thêm chức năng phụ thuộc vào việc một thay đổi phải chạm vào bao nhiêu phần. Nếu thêm một trường vào đơn hàng đòi sửa bốn dịch vụ và hai hàng đợi, chi phí mỗi thay đổi tăng lên và tốc độ giao hàng giảm. Đây là chi phí lớn nhất trong đời sống của một hệ thống, và nó gần như hoàn toàn do ranh giới mô-đun quyết định.
Chi phí vận hành phụ thuộc vào số thứ phải chạy và số thứ phải giám sát. Mỗi thành phần tách riêng là một tiến trình, một cấu hình, một bộ log, một cách triển khai và một chỗ có thể hỏng độc lập. Với một đội nhỏ, chi phí này tăng nhanh hơn lợi ích của việc tách.
Chi phí sửa khi hỏng phụ thuộc vào khả năng quan sát. Nếu một yêu cầu đi qua sáu thành phần và không có mã theo dõi xuyên suốt, việc tìm nguyên nhân mất nhiều giờ thay vì nhiều phút. Chi phí này không hiện ra trong kế hoạch, nhưng nó là chi phí thật của mỗi sự cố.
Ba chi phí này cộng lại thường lớn hơn chi phí xây dựng ban đầu trong vòng hai đến ba năm. Vì vậy một quyết định kiến trúc tiết kiệm hai tuần lúc đầu có thể tốn nhiều tháng về sau.
Năm quyết định ảnh hưởng chi phí dài hạn
Quyết định 1 — Ranh giới mô-đun: monolith hay nhiều dịch vụ
Đây là quyết định bị tranh luận nhiều nhất và cũng bị hiểu sai nhiều nhất. Câu hỏi không phải "monolith hay microservices", mà là "ranh giới nghiệp vụ nằm ở đâu".
Một monolith mô-đun hoá là một ứng dụng duy nhất, nhưng bên trong chia thành các mô-đun có ranh giới rõ, mỗi mô-đun sở hữu dữ liệu của mình và chỉ trao đổi qua giao diện hàm. Một hệ nhiều dịch vụ là nhiều ứng dụng chạy riêng, trao đổi qua mạng.
Về chi phí, monolith mô-đun hoá rẻ hơn ở ba điểm: chỉ một thứ để triển khai, không có lỗi mạng giữa các phần, và giao dịch dữ liệu vẫn là giao dịch của một cơ sở dữ liệu. Nhiều dịch vụ đắt hơn ở đúng ba điểm đó, và chỉ có lợi khi các phần cần mở rộng độc lập hoặc do các đội khác nhau sở hữu.
Lựa chọn đúng cho phần lớn dự án vừa là monolith mô-đun hoá với ranh giới viết ra rõ ràng. Ranh giới rõ cho phép tách sau này nếu cần; ranh giới mờ thì không, dù hệ thống chạy một tiến trình hay mười tiến trình.
Cách so sánh chi tiết giữa các kiểu kiến trúc được trình bày trong các kiến trúc phần mềm phổ biến. Lý do monolith vẫn thắng nhiều dự án được phân tích riêng trong kiến trúc phần mềm monolithic.
Quyết định 2 — Quyền sở hữu dữ liệu
Câu hỏi: mỗi loại dữ liệu có đúng một nơi sở hữu, hay nhiều phần cùng đọc và ghi?
Khi một loại dữ liệu có nhiều nơi cùng ghi, ba vấn đề xuất hiện. Thứ nhất, không ai biết giá trị đúng là gì khi hai nơi ghi khác nhau. Thứ hai, mọi thay đổi quy tắc phải sửa ở nhiều nơi và dễ bỏ sót. Thứ ba, không thể trả lời câu hỏi "vì sao giá trị này lại như vậy" vì không có nơi nào giữ lịch sử đầy đủ.
Chi phí của việc sở hữu mờ thường không hiện ra ngay. Nó hiện ra sau sáu tháng, dưới dạng báo cáo không khớp, dưới dạng hai màn hình hiển thị hai con số khác nhau cho cùng một đơn hàng, và dưới dạng thời gian họp để xác định "số nào đúng".
Cách xử lý rẻ nhất là vẽ bảng sở hữu dữ liệu trước khi viết mã: mỗi thực thể, một chủ sở hữu, các phần khác chỉ đọc qua giao diện của chủ sở hữu đó.
Quyết định 3 — Đồng bộ hay bất đồng bộ
Câu hỏi: khi hai phần cần trao đổi, bên gọi có chờ bên kia trả lời không?
Đồng bộ nghĩa là bên gọi chờ. Đơn giản, dễ hiểu, dễ tìm lỗi: nếu có lỗi, nó hiện ra ngay trong yêu cầu. Nhược điểm là bên gọi phụ thuộc vào thời gian phản hồi và tình trạng của bên kia.
Bất đồng bộ nghĩa là bên gọi đẩy việc vào hàng đợi và đi tiếp. Chịu được khi bên kia chậm hoặc tạm ngừng, nhưng đắt hơn ở ba điểm: cần một hàng đợi để vận hành, cần xử lý trường hợp một việc được xử lý hai lần, và cần một cách để biết một việc đã hoàn tất hay chưa.
Lựa chọn đúng là mặc định đồng bộ, và chỉ dùng bất đồng bộ khi có lý do cụ thể: một việc chạy lâu không nên giữ người dùng chờ, hoặc một sự kiện cần nhiều bên cùng xử lý độc lập.
Sai lầm phổ biến là dùng bất đồng bộ ở mọi nơi vì "hiện đại hơn". Kết quả là một hệ thống khó tìm lỗi: khi một đơn hàng không được xử lý, không ai biết nó đang nằm ở hàng đợi nào.
Quyết định 4 — Mô hình đa khách thuê
Nếu hệ thống phục vụ nhiều tổ chức khách hàng, có ba cách tách dữ liệu: một cơ sở dữ liệu dùng chung với cột phân biệt, một lược đồ riêng cho mỗi khách thuê, hoặc một cơ sở dữ liệu riêng cho mỗi khách thuê.
Chi phí thay đổi theo hướng ngược với mức tách. Dùng chung rẻ nhất để xây và vận hành, nhưng đòi kỷ luật tuyệt đối: mọi truy vấn phải lọc theo khách thuê, và một chỗ quên lọc là một lỗ hổng dữ liệu. Tách hoàn toàn an toàn hơn về ranh giới nhưng đắt hơn ở mỗi lần nâng cấp và mỗi lần chạy báo cáo tổng hợp.
Với phần lớn hệ thống doanh nghiệp vừa, mô hình dùng chung kèm một lớp bắt buộc lọc ở tầng truy cập dữ liệu là lựa chọn hợp lý. Điều kiện là lớp đó phải nằm ở một chỗ duy nhất, không phải ở từng câu truy vấn.
Quyết định 5 — Môi trường chạy và khả năng quan sát
Câu hỏi: hệ thống chạy ở đâu, và khi có sự cố thì ai biết, biết trong bao lâu, và biết được gì?
Ba thứ cần có, và cả ba đều rẻ nếu làm từ đầu: một mã theo dõi xuyên suốt mỗi yêu cầu, log có cấu trúc kèm mã đó, và một bảng theo dõi các chỉ số quan trọng nhất như thời gian phản hồi và tỷ lệ lỗi.
Chi phí của việc thiếu ba thứ này không hiện ra cho tới sự cố đầu tiên. Khi đó, mỗi giờ tìm nguyên nhân là một giờ hệ thống không phục vụ được, và đội phải đọc log rời rạc để đoán.
Một quy tắc thực dụng: nếu bạn không trả lời được câu "yêu cầu này đi qua những bước nào và mất bao lâu ở mỗi bước" trong vòng năm phút, hệ thống chưa có khả năng quan sát đủ.
Chi phí ba năm của từng lựa chọn
Bảng dưới đây so sánh hai cấu hình điển hình. Không có con số tiền, vì chi phí thật phụ thuộc quy mô đội và khối lượng giao dịch; cột so sánh là mức tương đối.
| Khía cạnh | Monolith mô-đun hoá | Nhiều dịch vụ |
|---|---|---|
| Số thứ phải triển khai | Một | Nhiều, mỗi dịch vụ một quy trình |
| Chi phí thêm một chức năng đơn giản | Thấp | Trung bình đến cao, tuỳ số dịch vụ phải sửa |
| Chi phí thêm một chức năng xuyên nhiều phần | Trung bình | Cao, cần phối hợp hợp đồng giữa các dịch vụ |
| Giao dịch dữ liệu | Một giao dịch của cơ sở dữ liệu | Cần xử lý bù trừ khi một bước thất bại |
| Chi phí hạ tầng | Thấp | Cao hơn, cần thêm hàng đợi, cân bằng tải, giám sát |
| Chi phí tìm lỗi | Thấp nếu có mã theo dõi | Cao nếu thiếu mã theo dõi xuyên dịch vụ |
| Khả năng mở rộng độc lập | Hạn chế, thường mở rộng cả ứng dụng | Cao, mở rộng từng dịch vụ |
| Số người cần để vận hành | Ít | Nhiều hơn, cần người trực và công cụ |
| Phù hợp khi | Một đội, nghiệp vụ còn thay đổi | Nhiều đội, tải rất khác nhau giữa các phần |
Cách đọc bảng này: hai cấu hình không phải hai mức chất lượng. Chúng là hai mức đánh đổi. Với một đội nhỏ và nghiệp vụ còn thay đổi, cột trái rẻ hơn ở hầu hết dòng. Với nhiều đội và tải rất lệch giữa các phần, cột phải bắt đầu có lợi.
Năm kiểu hỏng thường gặp và triệu chứng
Kiến trúc hỏng không hỏng đột ngột. Nó hỏng dần, và có triệu chứng sớm.
| Kiểu hỏng | Triệu chứng sớm | Hậu quả nếu để lâu | Cách phòng |
|---|---|---|---|
| Ranh giới mờ | Một thay đổi nhỏ phải sửa nhiều mô-đun | Mỗi thay đổi chậm dần, chi phí tăng | Viết ranh giới và quy tắc phụ thuộc trước khi viết mã |
| Sở hữu dữ liệu chồng chéo | Hai màn hình hiển thị hai con số khác nhau | Báo cáo không được tin, phải đối chiếu tay | Bảng sở hữu dữ liệu, một chủ cho mỗi thực thể |
| Bất đồng bộ tràn lan | Không ai biết một việc đã chạy xong chưa | Sự cố khó tìm nguyên nhân, dữ liệu lệch | Mặc định đồng bộ, chỉ bất đồng bộ khi có lý do |
| Thiếu khả năng quan sát | Sự cố đầu tiên mất nhiều giờ để tìm | Mỗi sự cố tốn thời gian không tương xứng | Mã theo dõi và log có cấu trúc từ đầu |
| Cấu hình rải rác | Mỗi môi trường có một bộ giá trị riêng | Triển khai sai môi trường, khó tái lập | Một nguồn cấu hình, có kiểm tra khi khởi động |
Kiểu hỏng đầu tiên là kiểu tốn kém nhất và cũng khó sửa nhất. Ranh giới mờ không sửa được bằng cách thêm công cụ; nó chỉ sửa được bằng cách chia lại mô-đun, và việc chia lại thường đòi di chuyển dữ liệu.
Câu hỏi nên hỏi nhà cung cấp về kiến trúc
Sáu câu dưới đây kiểm tra được năng lực thiết kế mà không cần bạn là kỹ sư.
| Câu hỏi | Câu trả lời đáng tin | Dấu hiệu cảnh báo |
|---|---|---|
| "Ranh giới mô-đun dựa trên cái gì?" | Dựa trên nghiệp vụ và quyền sở hữu dữ liệu, có ví dụ cụ thể | Dựa trên công nghệ hoặc theo thói quen |
| "Dữ liệu nào thuộc phần nào?" | Có bảng sở hữu dữ liệu, mỗi thực thể một chủ | "Các phần dùng chung cơ sở dữ liệu" mà không nói ai ghi |
| "Khi một phần ngừng hoạt động thì sao?" | Nêu hành vi cụ thể: phần nào vẫn chạy, phần nào báo lỗi | "Hệ thống vẫn chạy bình thường" |
| "Làm sao tìm nguyên nhân một yêu cầu chậm?" | Có mã theo dõi và log theo bước | "Xem log của từng phần" |
| "Thêm một chức năng xuyên nhiều phần cần sửa gì?" | Liệt kê được các điểm chạm | "Chỉ cần thêm một màn hình" |
| "Quyết định nào ở đây khó đảo ngược nhất?" | Nêu được một quyết định và điều kiện xem lại | "Không có, đều linh hoạt" |
Câu cuối là câu quan trọng nhất. Một đội trả lời "đều linh hoạt" là đội chưa phân biệt được quyết định khó đảo ngược với quyết định dễ đảo ngược, và điều đó có nghĩa là họ sẽ đưa ra quyết định khó đảo ngược mà không biết.
Kiến trúc không phải tài liệu vẽ một lần
Một tài liệu kiến trúc có giá trị khi nó sống cùng dự án. Ba thực hành giữ nó sống:
Ghi lại quyết định kèm bối cảnh. Mỗi quyết định nên có một đoạn ngắn: vấn đề, các phương án đã cân nhắc, phương án chọn, lý do, và điều kiện để xem lại. Đoạn này ngắn hơn nhiều so với việc viết lại tài liệu, và nó là thứ duy nhất giúp người mới hiểu vì sao hệ thống có hình dạng hiện tại.
Định kỳ kiểm tra ranh giới. Mỗi quý, kiểm tra xem có mô-đun nào đang gọi trực tiếp vào dữ liệu của mô-đun khác không. Ranh giới bị xuyên qua một lần sẽ bị xuyên qua nhiều lần, và sau một năm không ai còn biết ranh giới ở đâu.
Đặt điều kiện tách trước khi cần tách. Nếu đang dùng monolith mô-đun hoá, ghi rõ điều kiện nào sẽ khiến một mô-đun được tách thành dịch vụ riêng, ví dụ tải của mô-đun đó vượt một ngưỡng hoặc một đội khác tiếp nhận. Điều kiện viết trước ngăn cả hai lỗi: tách quá sớm vì áp lực trình diễn, và không bao giờ tách vì không ai quyết.
Với các hệ thống có giao diện web truyền thống, cách tổ chức ba lớp theo mô hình MVC và giới hạn của nó được trình bày trong kiến trúc phần mềm MVC. Và khi đội dùng công cụ AI để viết mã, các quyết định kiến trúc càng cần được viết ra trước, vì công cụ sẽ làm theo cấu trúc hiện có — kể cả cấu trúc sai — với tốc độ cao hơn: xem AI coding là gì.
Mẫu ghi lại một quyết định kiến trúc
Một quyết định kiến trúc chỉ có giá trị khi người khác đọc lại được. Mẫu dưới đây gói trong một trang và đủ để trả lời câu hỏi "vì sao hệ thống lại như thế này" sau hai năm.
| Trường | Nội dung cần ghi | Ví dụ |
|---|---|---|
| Mã quyết định | Số thứ tự và ngày | ADR-004, 10/2026 |
| Vấn đề | Câu hỏi cần quyết, viết thành một câu | Có tách phần báo cáo thành dịch vụ riêng không? |
| Phương án đã cân nhắc | Ít nhất hai, kèm phương án không làm gì | Tách riêng; giữ trong ứng dụng; không làm báo cáo |
| Phương án chọn | Một phương án, không phải danh sách | Giữ trong ứng dụng, tách phần tính toán nặng thành tiến trình riêng |
| Lý do | Ràng buộc nào quyết định, không phải sở thích | Một đội vận hành, tải báo cáo theo lô đêm, không cần mở rộng độc lập |
| Điều kiện xem lại | Ngưỡng hoặc sự kiện khiến quyết định này hết đúng | Xem lại khi báo cáo chạy quá 30 phút hoặc khi có đội thứ hai nhận phần báo cáo |
| Hệ quả | Điều gì trở nên dễ hơn, điều gì trở nên khó hơn | Dễ triển khai; khó mở rộng riêng phần báo cáo nếu tải tăng |
Ba trường hay bị bỏ nhất là "phương án đã cân nhắc", "điều kiện xem lại" và "hệ quả". Bỏ trường thứ nhất, người đọc sau không biết đã có lựa chọn nào khác. Bỏ trường thứ hai, quyết định sống mãi kể cả khi lý do đã hết. Bỏ trường thứ ba, người đọc không biết mình đang phải trả giá ở đâu.
Một quy tắc nhỏ có tác dụng lớn: ghi quyết định trong cùng kho mã nguồn, cạnh phần mã liên quan. Tài liệu kiến trúc để trong một thư mục riêng thường không được cập nhật; tài liệu nằm cạnh mã thì người sửa mã nhìn thấy.
Câu hỏi thường gặp
Kiến trúc phần mềm khác thiết kế phần mềm ở chỗ nào?
Thiết kế nói về cách một thành phần hoạt động bên trong: các lớp, các hàm, cách xử lý một yêu cầu. Kiến trúc nói về cách chia hệ thống thành các phần và cách chúng trao đổi. Một cách phân biệt thực dụng: thiết kế thay đổi được trong vài ngày, kiến trúc thì không. Nếu đổi nó đòi di chuyển dữ liệu hoặc chia lại đội, đó là kiến trúc.
Dự án nhỏ có cần kiến trúc không?
Có, nhưng ở mức gọn hơn: một bảng sở hữu dữ liệu, một quy tắc ranh giới mô-đun, và một quyết định về cách triển khai. Ba trang là đủ cho một dự án nhỏ. Điều không nên bỏ là bảng sở hữu dữ liệu, vì đó là thứ đắt nhất để sửa sau khi đã có dữ liệu thật.
Có nên chọn microservices ngay từ đầu?
Thường không, trừ khi có ít nhất hai đội cùng làm và tải giữa các phần rất khác nhau. Với một đội, chi phí vận hành nhiều dịch vụ thường lớn hơn lợi ích. Cách an toàn hơn là monolith mô-đun hoá với ranh giới rõ, và tách khi có điều kiện cụ thể đã viết trước.
Làm sao biết kiến trúc hiện tại có vấn đề?
Ba dấu hiệu dễ quan sát: một thay đổi nhỏ phải sửa nhiều mô-đun, hai màn hình hiển thị hai con số khác nhau cho cùng một dữ liệu, và khi có sự cố không ai trả lời được yêu cầu đã đi qua những bước nào. Cả ba đều là triệu chứng của ranh giới mờ hoặc thiếu khả năng quan sát, và cả ba đều sửa được nếu xử lý sớm.
Cập nhật và kiểm chứng
Cập nhật tháng 10/2026. Nội dung phản ánh quy trình bốn chặng WinSell áp dụng — Khám phá, Đặc tả, Xây dựng, Bàn giao và đo lường — và được rà soát theo thông lệ thiết kế hệ thống đang áp dụng. Bài viết không mô tả hạ tầng nội bộ của WinSell, không nêu giá dịch vụ và không sử dụng số liệu khách hàng của bất kỳ bên nào.
Nếu bạn cần một bên viết ra các quyết định kiến trúc kèm lý do và điều kiện xem lại trước khi viết mã, xem dịch vụ xây dựng phần mềm theo yêu cầu của WinSell. Báo giá sau khi chốt phạm vi.
Cần một hệ thống chạy được, không chỉ một bài viết?
WinSell xây phần mềm theo yêu cầu và làm SEO/GEO cho chính sản phẩm đó. Phạm vi và báo giá được chốt sau bước khám phá.


