---
title: "Thiết kế nền tảng multi-tenant - control plane, tenant isolation và quota"
description: "Khóa học nền tảng về thiết kế app SaaS phục vụ nhiều doanh nghiệp trên cùng hệ thống, tập trung vào bài toán kiểm soát ranh giới dữ liệu và tài nguyên giữa các tenant. Bạn sẽ chọn đúng mô hình lưu trữ, ngăn rò rỉ dữ liệu bằng RLS, thiết lập quota bám sát chi phí và điều phối tài nguyên công bằng qua control plane."
canonical: "https://200lab.io/courses/thiet-ke-nen-tang-multi-tenant-control-plane-tenant-isolation-va-quota"
type: "course"
course_type: "course"
learning_type: "free_form"
published: "2026-10-13T08:03:31Z"
students: 32
---

## Khóa học này mang lại gì cho bạn

Ứng dụng SaaS do bạn phát triển phục vụ nhiều doanh nghiệp cùng lúc trên một hệ thống Postgres dùng chung. Mỗi doanh nghiệp là một tenant, nắm giữ dữ liệu, người dùng và thiết lập cấu hình riêng. Khi lượng khách hàng tăng lên, dữ liệu có thể lọt sang file xuất của công ty khác, một tenant nhập dữ liệu lớn làm chậm mọi người dùng còn lại, và chi phí gọi AI lệch xa số liệu ghi nhận. Khóa học giúp bạn nắm vững ranh giới kỹ thuật để vận hành nền tảng multi-tenant ổn định và an toàn.

- **Quyết định mô hình lưu trữ** Bạn phân biệt ưu nhược điểm giữa shared, dedicated và hybrid để chọn cách đặt dữ liệu dựa trên tỷ trọng tải của tenant lớn nhất và yêu cầu khôi phục độc lập.
- **Bảo vệ ranh giới dữ liệu bằng RLS** Bạn thiết lập Row Level Security trên Postgres với đầy đủ bốn điều kiện về bảng, role và transaction để database tự lọc dòng theo tenant của transaction dù truy vấn thiếu điều kiện tenant.
- **Quản lý gói dịch vụ và quota bằng dữ liệu** Bạn chuyển entitlement và giới hạn riêng của từng tenant thành các dòng dữ liệu trong bảng, tách biệt giá trị giới hạn nằm trong dữ liệu với logic kiểm tra giới hạn vẫn nằm trong app.
- **Thiết kế metering ghi nhận usage chuẩn xác** Bạn ghi nhận mức tiêu thụ tài nguyên ngay tại tiến trình gọi provider bên ngoài, đối chiếu định kỳ, áp dụng pacing để giảm mức vượt khi số liệu báo về trễ và tính cả phần đang chạy được giữ trước nếu muốn chặn đúng ngân sách.
- **Điều phối hàng chờ worker công bằng** Bạn phân chia lane và cap cho từng tenant trên bảng job dùng chung, đảm bảo việc nền nặng của khách lớn không chiếm hết tài nguyên xử lý của khách nhỏ.
- **Vận hành vòng đời tenant bằng control plane** Bạn duy trì reconcile loop để kéo cấu hình thực tế về khớp với cấu hình mong muốn, đồng thời giữ cho data plane chạy tiếp khi control plane gặp sự cố.

Khóa học sử dụng Postgres làm nền tảng minh họa thực nghiệm, độc lập với các framework SaaS hay thư viện phân quyền chuyên biệt.

## Khóa học cung cấp những nền tảng nào

Toàn bộ khóa học được xây dựng xoay quanh nguyên tắc xác định quyền sở hữu tài nguyên và thiết lập ranh giới cô lập giữa các tenant. Tùy thuộc vào quy mô, hệ thống sẽ phát triển theo từng nấc từ database dùng chung có cột `tenant_id` tới việc tách biệt control plane và cô lập phần cứng cho khách hàng lớn. Bạn có thể tham khảo [Tenancy Models for a Multitenant Solution](https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models) của Azure để so sánh các mô hình lưu trữ, tìm hiểu chiến lược chia sẻ tài nguyên trong [Fairness in multi-tenant systems](https://builder.aws.com/content/3Eupj3d2bo4fEvlzYbICMZNhQ3B/fairness-in-multi-tenant-systems) từ AWS, và nắm bắt cơ chế độc lập vận hành qua [Static stability](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/static-stability.html).

### 1. Dùng chung database, mỗi tenant một database riêng hay kết hợp cả hai
Khi app chạm mốc 400 tenant, việc tách mỗi khách hàng một database riêng trên cùng server khiến Postgres phải dự trù tối đa 8.000 connection và mất khoảng 4,4 giờ cho mỗi đợt chạy migration cấu trúc bảng. Mô hình dedicated không thể bảo vệ hệ thống nếu app định tuyến nhầm connection, đồng thời point-in-time recovery vẫn phải khôi phục trên toàn bộ server. Bạn sẽ nắm vững năm tiêu chí đo lường gồm noisy neighbor, blast radius, thời gian khôi phục, chi phí kết nối và thời gian deploy để giữ database dùng chung và cân nhắc chuyển sang hybrid khi tỷ trọng tải của tenant quá lớn, hoặc khi có yêu cầu khôi phục riêng và nguy cơ sự cố lan sang tenant khác.

### 2. Giữ cho dữ liệu của mỗi tenant không lọt sang tenant khác
Các hàm trong repository có thể lọc đúng `tenant_id`, nhưng những câu SQL viết tay từ script quản trị hay job báo cáo vẫn đi thẳng tới bảng và có nguy cơ đọc nhầm dữ liệu của tenant khác. Cơ chế Row Level Security (RLS) trên Postgres cung cấp lớp phòng vệ default-deny ở tầng lưu trữ để tự động lọc dòng theo tenant của transaction hiện tại. Lớp chặn này đòi hỏi bốn điều kiện kỹ thuật: bảng đã bật RLS, role của app không mang quyền bypass hay làm owner bảng, policy bao quát cả bốn lệnh đọc ghi, và tenant được gắn theo từng transaction thay vì giữ cố định trên connection pool.

### 3. Gói dịch vụ, quota và usage để tính tiền
Việc đưa trực tiếp tên gói và logic kiểm tra vào code khiến mỗi thỏa thuận riêng của sales đều buộc team phải sửa code và deploy lại. Control plane giải quyết vấn đề này bằng cách lưu gói dịch vụ, entitlement và giá trị ghi đè riêng của từng khách hàng vào bảng dữ liệu, giúp data plane chỉ cần tra cứu giới hạn đang áp dụng. Với tài nguyên AI, quota cần xác định rõ đơn vị đếm bám sát chi phí, phạm vi, cửa sổ thời gian và cơ chế chặn khi chạm trần. Để metering không bị lệch so với hóa đơn provider, app ghi nhận usage record kèm usage id riêng cho từng lần thử ngay tại thời điểm gọi, kết hợp pacing để giữ nhịp chi tiêu khi kết quả trả về trễ.

### 4. Chia worker và hạn mức của provider công bằng giữa các tenant
Hàng chờ xử lý tuần tự theo thời gian vào hàng sẽ khiến việc xuất báo cáo của khách nhỏ phải chờ hơn 4 giờ sau 40.000 job đồng bộ của khách lớn. Bằng cách bổ sung cột `lane` và dòng đếm số lượng slot đang chạy cho từng tenant, worker có thể luân phiên cấp lượt và giới hạn cap đồng thời cho từng khách hàng. Khi tenant lớn nhập hàng triệu dòng dữ liệu gây nghẽn disk hoặc vét cạn rate limit của provider LLM, hệ thống cần áp dụng quota tốc độ ghi và chia sẻ hạn mức token theo tỷ lệ công bằng thay vì chỉ tăng thêm worker.

### 5. Desired state, reconcile loop và giữ cho data plane chạy tiếp khi control plane sập
Trang quản trị có thể báo gói Pro nhưng khách hàng vẫn bị giới hạn ở mức cũ nếu nhiều thành phần cùng ghi đè trạng thái mà không lưu lại cấu hình thực tế đang áp dụng. Hệ thống cần phân định rõ desired state, observed state và status, gắn kèm số thế hệ generation để phát hiện các tác vụ chưa hoàn tất. Với các tài nguyên bên ngoài như tên miền riêng, controller vận hành reconcile loop định kỳ kiểm tra và thực hiện bước còn thiếu thay vì để job dừng hẳn ở trạng thái thất bại. Đồng thời, data plane lưu giữ bản cấu hình nhận gần nhất để tiếp tục phản hồi request và kiểm tra quota bình thường khi control plane gặp sự cố.

### 6. Tạm dừng, xóa, dời tenant lớn sang database riêng và tạo tenant mới
Vòng đời tenant cần chuyển biến tuần tự qua các trạng thái active, suspended, offboarding và deleted để ngăn chặn việc job nền tiếp tục chạy cho tài khoản đã hủy gói. Khi xóa dữ liệu lớn trên database dùng chung, tiến trình cần chia thành nhiều lô nhỏ và có khoảng nghỉ để không ảnh hưởng tới độ trễ p99 của các tenant khác. Đối với khách hàng lớn chiếm 30% dung lượng dữ liệu, việc chuyển đổi sang hybrid đòi hỏi một instance Postgres riêng sở hữu disk độc lập để thu hẹp blast radius về đúng một tenant. Quá trình tạo mới tenant cũng được controller xử lý bất đồng bộ qua mã phản hồi 202, sử dụng tên tài nguyên suy ra từ tenant ID để không sinh ra tài nguyên mồ côi khi thử lại.

## Vì sao 200Lab tạo ra khóa học này

Khi một app phục vụ nhiều doanh nghiệp vừa hình thành, việc thêm cột `tenant_id` và viết các API cơ bản thường diễn ra nhanh chóng. Hệ thống chạy êm ả trong giai đoạn vài chục tenant đầu tiên trên một server Postgres duy nhất. Khó khăn kỹ thuật chỉ bộc lộ khi quy mô đạt hàng trăm tenant với mức độ lệch tải lớn: một câu truy vấn viết tay bỏ quên điều kiện lọc làm lộ danh bạ khách hàng, hoặc một đợt đồng bộ dữ liệu đột biến làm tê liệt toàn bộ worker nền.

Trước những sự cố đó, phản xạ thường thấy là vội vã chia tách mỗi khách hàng một database riêng hoặc liên tục nâng cấp phần cứng. Cách làm này làm tăng đột biến chi phí duy trì kết nối, kéo dài thời gian deploy và tạo ra gánh nặng vận hành lớn mà không giải quyết được các lỗ hổng định tuyến ở tầng app. Trong khi đó, người trực tiếp vận hành hệ thống phải đối mặt với các báo cáo rò rỉ dữ liệu, giải trình chênh lệch hóa đơn từ service bên ngoài và xử lý khiếu nại tài khoản bị treo.

Lịch sử kỹ thuật đã ghi nhận nhiều sự cố tương tự ở quy mô lớn. Năm 2023, lỗi tái sử dụng connection pool trong thư viện client Redis đã khiến dữ liệu người dùng bị trả nhầm sang phiên truy cập khác. Năm 2025, nền tảng thương mại điện tử Norce ghi nhận một tenant duy nhất gây quá tải toàn bộ cụm database dùng chung, làm gián đoạn diện rộng các khách hàng multi-tenant. Cùng năm đó, sự cố gián đoạn tại thành phần Service Control của Google Cloud cho thấy rủi ro khi các khâu kiểm tra policy và quota nằm trực tiếp trên luồng xử lý request mà không có cơ chế độc lập vận hành.

Khóa học này được 200Lab xây dựng nhằm giúp bạn nhận diện chính xác nguyên nhân gốc rễ phía sau từng biểu hiện bất thường, từ việc rà soát các câu truy vấn không qua repository, chuẩn hóa đơn vị tính quota cho tới việc phân định ranh giới giữa control plane và data plane. Bạn sẽ có đầy đủ căn cứ kỹ thuật để duy trì một nền tảng database dùng chung ổn định, tiết kiệm chi phí và chỉ chuyển dịch mô hình khi các số đo vận hành thực tế yêu cầu.

## Những vấn đề thường gặp khi app phục vụ nhiều tenant

Khi hệ thống gặp lỗi rò rỉ dữ liệu hoặc suy giảm hiệu năng do tranh chấp tài nguyên, đội ngũ phát triển thường có xu hướng vá cục bộ tại điểm phát sinh lỗi, bổ sung thêm worker hoặc chuyển đổi hạ tầng vội vã. Những sự cố thực tế dưới đây chỉ ra rằng các biện pháp tình thế đó thường không xử lý đúng nguyên nhân gốc rễ:

- Bổ sung điều kiện `tenant_id` tại endpoint xuất file nhưng dữ liệu khách khác vẫn bị lộ — các truy vấn viết tay từ script quản trị và job báo cáo đi thẳng vào database mà không qua lớp lọc repository của app.
- Bảng dữ liệu đã kích hoạt RLS kèm policy theo tenant nhưng file xuất vẫn chứa hàng nghìn dòng dữ liệu của công ty khác — app đang kết nối bằng role sở hữu bảng nên Postgres tự động bỏ qua toàn bộ policy bảo vệ.
- Hai khách hàng cùng gói dịch vụ có số lượt gọi trợ lý AI như nhau nhưng số token tiêu thụ chênh lệch 40 lần — quota đang đếm theo lượt tương tác thay vì đo lường số lượng token mà provider tính tiền.
- Hóa đơn từ nhà cung cấp LLM ghi nhận lượng token cao hơn hẳn dữ liệu metering nội bộ — app chỉ ghi nhận usage khi lời gọi kết thúc trọn vẹn, bỏ sót các yêu cầu bị người dùng hủy giữa luồng stream hoặc timeout trước khi thử lại.
- Tác vụ xuất báo cáo nhỏ của khách hàng bị kẹt chờ hơn 4 giờ dù không phát sinh lỗi — hàng chờ worker lấy việc thuần túy theo thời gian gửi nên bị dồn ứ sau hàng chục nghìn job đồng bộ của khách hàng lớn.
- Hàng chờ xử lý việc nền vẫn thông suốt nhưng API của khách hàng nhỏ bị chậm tới 2,8 giây kèm lỗi 429 — tenant lớn đang làm bão hòa disk I/O của database và vét cạn hạn mức token mỗi phút của provider dùng chung.
- Màn hình quản trị hiển thị gói nâng cấp thành công nhưng app vẫn áp dụng hạn mức cũ cho khách hàng — cột trạng thái bị ghi đè bởi nhiều luồng bất đồng bộ và thiếu trường lưu trữ cấu hình thực tế được áp dụng.
- Số lượng bucket lưu trữ trên cloud vượt xa số tenant đang hoạt động và nhiều tài khoản bị treo khi đăng ký — quy trình tạo tenant thực hiện tuần tự trong một request khiến gateway bị timeout khi nhà cung cấp ngoài phản hồi trễ.

Những phân tích kỹ thuật trong từng bài học sẽ giúp bạn kết nối từng triệu chứng với ranh giới kiến trúc tương ứng và xác định đúng giải pháp xử lý.

## Bạn sẽ học theo cách nào

- **Xuất phát từ triệu chứng kỹ thuật thực tế** Bạn bắt đầu mỗi bài học từ các dấu hiệu đo đếm được trong nhật ký hệ thống, dòng log phân tích, hóa đơn dịch vụ hoặc báo cáo quá tải tài nguyên thay vì các giả định trừu tượng.
- **Quan sát qua sơ đồ luồng và trace dữ liệu** Bạn đối chiếu đường đi của request, ranh giới dữ liệu và các điểm tranh chấp tài nguyên qua sơ đồ trực quan trước khi đi sâu vào các đoạn mã cài đặt.
- **Dự đoán kết quả trước khi tiếp cận giải pháp** Bạn chủ động phân tích các tình huống kỹ thuật cụ thể, tự ước lượng độ trễ, số dòng dữ liệu ảnh hưởng hoặc hành vi của database trước khi xem kết luận từ hệ thống.
- **Đưa ra quyết định dựa trên số liệu đo lường** Bạn xác lập các ngưỡng kỹ thuật cụ thể về dung lượng, tỷ trọng tải, độ trễ p99 và chi phí tài nguyên để làm căn cứ điều chỉnh kiến trúc.

## Khóa học dành cho ai

1. **Kỹ sư phát triển phần mềm SaaS** Bạn đang xây dựng nền tảng phục vụ nhiều doanh nghiệp trên cùng một hệ thống và cần thiết lập ranh giới dữ liệu chuẩn xác, kiểm soát quota và xử lý triệt để tình trạng tranh chấp tài nguyên giữa các khách hàng.
2. **Kỹ sư tiếp nhận đề xuất tái cấu trúc hệ thống** Bạn cần các tiêu chí đo đạc cụ thể để đánh giá tính khả thi trước khi quyết định chuyển đổi mô hình database, kích hoạt RLS hay phân tách control plane thành service độc lập.
3. **Kỹ sư tích hợp các dịch vụ tính phí theo mức dùng** Bạn đang phát triển tính năng trợ lý AI hoặc các tiện ích phụ thuộc bên thứ ba và cần cơ chế metering chuẩn xác, phân bổ rate limit công bằng và kiểm soát ngân sách theo từng tenant.

## Những điều cần lưu ý

- Khóa học tập trung vào các ranh giới thiết kế kỹ thuật của nền tảng multi-tenant và không bao quát các thủ tục pháp lý hay quy định hợp đồng của dịch vụ SaaS; thay vào đó bạn nhận được các giải pháp kiến trúc có thể đo lường và triển khai trực tiếp trên hệ thống.
- Nội dung bài học sử dụng môi trường Postgres và TypeScript làm công cụ thực nghiệm chuẩn mực mà không phụ thuộc vào một framework SaaS hay nền tảng đám mây cụ thể; thay vào đó bạn nắm vững nguyên lý vận hành cốt lõi để áp dụng linh hoạt trên mọi ngăn xếp công nghệ.
- Hệ thống bài học không đi sâu vào việc cấu hình chi tiết các công cụ điều phối hạ tầng phức tạp; đổi lại bạn nắm rõ quy trình thiết kế reconcile loop, cơ chế chuyển đổi trạng thái và logic định tuyến dữ liệu ở mức app.
- Các số liệu trong bài tập tình huống được thiết lập nhằm mục đích minh họa và đối soát phương pháp tính toán; khi áp dụng vào thực tế, bạn sẽ sử dụng chính các số đo từ hệ thống của mình để đưa ra quyết định kiến trúc phù hợp.

## Bắt đầu từ đâu

Bài học mở đầu xuất phát từ bốn sự cố điển hình khi một hệ thống mở rộng từ 12 lên 400 tenant, đi kèm lời khuyên phổ biến về việc tách riêng database cho từng khách hàng. Bài học sẽ cùng bạn định vị control plane và data plane ngay trong cấu trúc app hiện tại, xác định vị trí của hệ thống trên bậc thang kiến trúc bốn nấc và đặt ra ba câu hỏi kỹ thuật trọng tâm trước khi quyết định thay đổi tầng lưu trữ.

## Chương trình

- Một app có nhiều doanh nghiệp cùng dùng thì cần thêm những gì? (miễn phí)

### Giữ cho dữ liệu của mỗi tenant không lọt sang tenant khác

- Mỗi khách hàng một database riêng có thật sự an toàn hơn không? (miễn phí)
- Người bán đọc được đơn hàng của người bán khác qua API nội bộ · quiz
- Vì sao code đã lọc theo tenant vẫn để lọt dữ liệu của khách khác? · quiz
- Tình huống: file xuất của khách chứa dữ liệu của công ty khác · kit cho agent

### Quota, metering và chia tài nguyên công bằng giữa các tenant

- Vì sao tăng giới hạn cho một khách mà phải sửa code và deploy? · quiz
- Cùng gói, cùng số lượt hỏi AI mà số token chênh nhau 40 lần · quiz
- Vì sao usage đã ghi thấp hơn số token trên hóa đơn của provider? · quiz · kit cho agent
- Ghi mỗi lượt chạy cron thành một dòng để không lượt nào bị lỡ hay chạy chồng · quiz · kit cho agent
- Job của khách nhỏ chờ hàng giờ sau 40.000 job của một khách lớn · quiz · kit cho agent
- Tình huống: tenant nhập 5 triệu dòng làm chậm mọi tenant khác · kit cho agent

### Tạo, đổi cấu hình, tạm dừng và xóa tenant bằng control plane

- Trang quản trị báo gói Pro nhưng khách vẫn bị giới hạn như gói cũ · quiz
- Job thêm tên miền riêng thất bại một lần rồi không được chạy lại · quiz
- Control plane sập làm request của mọi khách đều lỗi theo · quiz
- Khách đã hủy gói từ ba tháng trước mà dữ liệu vẫn còn khắp nơi · quiz
- Sự cố của một tenant lớn khiến mọi tenant không ghi được dữ liệu
- Tình huống: tạo tenant dở dang và để lại resource mồ côi · kit cho agent
