---
title: "Thiết kế API giữa các service - error model, versioning và contract test"
description: "Khóa học trang bị tư duy thiết kế API giữa các service dựa trên ranh giới contract. Bạn sẽ làm chủ status code, error model Problem Details, phân trang keyset cursor, chiến lược versioning theo API key, contract test tự động, cùng kỹ thuật tối ưu với gRPC và GraphQL nhằm bảo đảm an toàn khi hệ thống tiến hóa."
canonical: "https://200lab.io/courses/thiet-ke-api-giua-cac-service-error-model-versioning-va-contract-test"
type: "course"
course_type: "course"
learning_type: "free_form"
published: "2026-10-05T02:56:08Z"
students: 74
---

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

API của một service sớm muộn cũng có những consumer mà team bạn không trực tiếp kiểm soát: service của team khác, app mobile trên thiết bị người dùng hay phần mềm của đối tác bên ngoài. Mỗi consumer đều viết code dựa trên status code, tên field, body báo lỗi và cơ chế phân trang của API, rồi deploy theo chu kỳ độc lập. Bảy năng lực thực chiến dưới đây giúp bạn làm chủ ranh giới contract để tự tin nâng cấp hệ thống mà không làm gãy code của consumer:

- **Thiết kế resource hướng tác vụ** — Bạn bọc dữ liệu theo nhu cầu hiển thị của màn hình thay vì sao chép cấu trúc từng bảng database, giúp app giảm từ **10 request** nối tiếp xuống còn **1 request** duy nhất. Các hành động nghiệp vụ như xác nhận, hủy đơn hoặc hoàn tiền được phân rã về POST trên resource con, bảo đảm GET chỉ hiển thị trang xác nhận, còn thao tác thay đổi trạng thái được thực hiện bằng POST khi khách bấm nút.
- **Quy chuẩn status code và error model** — Bạn phân loại kết quả bằng bảng status code nhất quán của nền tảng và dùng một hàm map duy nhất ở tầng ngoài cùng để chuyển đổi lỗi sang định dạng Problem Details. Code của consumer rẽ nhánh chính xác nhờ field `code` ổn định, trong khi chi tiết nhạy cảm và câu truy vấn SQL được giữ lại an toàn trong log.
- **Kiểm soát payload bằng schema** — Bạn chặn đứng dữ liệu sai định dạng ngay tại tầng handler bằng schema JSON chặt chẽ thay vì để server tự ý ép kiểu ngầm. Toàn bộ lỗi sai kiểu hoặc thiếu field được gom trả về trong một response 400 duy nhất, tách biệt rõ ràng với các vi phạm nghiệp vụ trả về mã 422 từ use case.
- **Phân trang an toàn và xử lý tác vụ dài** — Bạn áp dụng keyset cursor trên cặp khóa sắp xếp duy nhất để danh sách không bị nhảy trang hay đọc lặp khi dữ liệu biến động liên tục. Với tác vụ xử lý tốn nhiều thời gian, bạn trả mã 202 Accepted kèm status resource để consumer chủ động theo dõi tiến độ và nhận kết quả mà không làm nghẽn gateway.
- **Tiến hóa API và kiểm thử tương thích** — Bạn lưu trữ contract trong file OpenAPI được review song song với code và nhận diện chính xác các dạng breaking change từ góc nhìn consumer. Bạn vận hành song song hai version qua lớp chuyển đổi ở tầng ngoài cùng, theo dõi lưu lượng v1 theo từng API key trước khi tắt, và chặn đứng rủi ro deploy bằng consumer-driven contract test tự động trong CI.
- **Truyền định danh và thiết kế webhook** — Bạn trích xuất principal cùng tenant context từ token đã xác thực rồi truyền qua các tầng nội bộ bằng header tin cậy. Bạn gắn correlation ID theo chuẩn W3C Trace Context để gom trọn vẹn trace của request qua nhiều service, đồng thời thiết kế contract webhook có ID ổn định, chữ ký HMAC và lịch retry rõ ràng.
- **Làm chủ contract gRPC và GraphQL** — Bạn duy trì tính tương thích trên file `.proto`, thiết lập deadline để chặn sự cố treo dây chuyền và phân phối tải HTTP/2 qua proxy tầng 7. Bạn kiểm soát rủi ro null propagation trên schema GraphQL, triệt tiêu bài toán N+1 bằng cơ chế gom lượt đọc theo tick và giới hạn chi phí query trước khi thực thi.

Khóa học tập trung vào tư duy thiết kế kiến trúc và ranh giới giao tiếp giữa các service, giữ tính độc lập với mọi framework backend cụ thể.

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

Khóa học được xây dựng hoàn toàn xoay quanh khái niệm **contract**: toàn bộ những gì consumer quan sát được và đã viết code dựa vào, từ URL, method, status code, tên field, kiểu dữ liệu, error model cho đến cơ chế phân trang. Khi nắm vững ranh giới này, bạn có thể tái cấu trúc code bên trong use case hay database bất cứ lúc nào, trong khi mọi thay đổi ở tầng contract đều phải tôn trọng lịch phát hành của consumer. Kiến trúc tiến hóa của hệ thống dựa trên các hướng dẫn nền tảng từ [Stripe API versioning](https://stripe.com/blog/api-versioning), [Consumer-Driven Contracts](https://martinfowler.com/articles/consumerDrivenContracts.html) của Ian Robinson trên website của Martin Fowler và [Google Cloud API Design Guide](https://cloud.google.com/apis/design).

### 1. Resource, method, status code và error model

Chương này giải quyết câu hỏi: một endpoint cần giao tiếp kết quả và lỗi như thế nào để code của consumer đọc hiểu chính xác mà không phải phỏng đoán. Bạn sẽ nhận diện sự khác biệt giữa một resource hướng consumer và một dòng dữ liệu thô trong database, đưa màn hình chi tiết đơn từ **10 request** tuần tự với độ trễ p99 **3,1 giây** về **1 request** duy nhất trong khoảng **0,5 giây**. Bạn sẽ phân định rõ ranh giới ngữ nghĩa giữa safe method và idempotent method để bảo vệ hệ thống trước các công cụ quét link tự động. Bạn thiết lập một bảng status code tối thiểu cho toàn nền tảng, đưa mọi phản hồi lỗi về định dạng Problem Details chuẩn RFC 9457 với field `code` ổn định, và siết chặt validation bằng schema của contract để ngăn chặn triệt để tình trạng dữ liệu sai kiểu lọt vào database.

### 2. Cursor cho danh sách dài, trả 202 cho thao tác chạy lâu

Chương này cung cấp giải pháp xử lý khi kết quả không thể trả về trọn vẹn trong một response duy nhất mà consumer vẫn lấy đủ dữ liệu, không bị sót và không bị trùng lặp. Bạn sẽ phân tích nguyên nhân khiến phân trang offset bỏ sót **1.100 review** (**1,8%**) trong một phiên quét kiểm duyệt khi danh sách biến động, từ đó làm chủ kỹ thuật phân trang bằng keyset cursor opaque dựa trên cặp khóa xác định. Với các tác vụ tốn nhiều phút như sinh hàng loạt mã giảm giá hay xử lý file CSV dung lượng lớn, bạn sẽ thiết kế luồng phản hồi bất đồng bộ bằng mã 202 Accepted đi kèm status resource để consumer theo dõi tiến độ qua polling an toàn. Bài thực hành tình huống cuối chương đặt bạn vào bài toán nhập **300.000 sản phẩm** từ file CSV **180 MB**, kết hợp cơ chế ghi nhận checkpoint theo lô với báo cáo chi tiết từng dòng lỗi.

### 3. Đổi API mà không làm hỏng consumer đang gọi

Chương này trang bị quy trình kiểm soát rủi ro khi thay đổi API trong điều kiện các consumer chưa thể cập nhật code đồng thời. Bạn sẽ đưa contract vào file OpenAPI được quản lý version và review cùng code, đồng thời thiết lập drift test trong CI và runtime validator để phát hiện độ lệch giữa tài liệu và thực tế vận hành. Bạn sẽ phân tích vì sao một thay đổi tưởng như vô hại như thêm giá trị enum cũng có thể làm gián đoạn tiến trình đồng bộ của đối tác suốt **6 giờ**, qua đó xác định nghĩa vụ tolerant reader cho client. Bạn sẽ thực hành chạy song song hai version API bằng cách giữ một model nội bộ duy nhất kết hợp lớp chuyển đổi ở tầng ngoài cùng, theo dõi lượng gọi của từng API key để lên lịch tắt version cũ an toàn, và ngăn chặn lỗi phá vỡ tương thích ngay trong CI bằng consumer-driven contract test.

### 4. Request đi qua nhiều service và webhook gửi ra cho đối tác

Chương này mở rộng phạm vi ra toàn bộ chuỗi tương tác giữa các service nội bộ và kênh phát sự kiện ra bên ngoài. Bạn sẽ xây dựng cơ chế truyền tải tenant context và principal từ token xác thực xuống tận câu truy vấn database, loại bỏ nguy cơ rò rỉ dữ liệu giữa các người bán qua query parameter. Bạn sẽ gắn correlation ID chuẩn W3C Trace Context vào mọi điểm tiếp nhận request, truyền xuyên suốt qua header HTTP và message hàng đợi, đưa thời gian tra cứu sự cố trên log tập trung từ **3 giờ** xuống dưới **2 phút**. Chương học khép lại bằng thiết kế contract hoàn chỉnh cho webhook gửi tới đối tác, bảo đảm mỗi sự kiện duy trì một ID cố định qua các lần retry, xác thực nguồn gốc bằng chữ ký HMAC-SHA256 kèm khung thời gian hợp lệ **5 phút**, và công bố lịch retry minh bạch.

### 5. Contract gRPC, contract GraphQL và cách chọn giao thức

Chương này phân tích sâu cách quản lý contract, xử lý lỗi và kiểm soát breaking change trên hai giao thức hiệu năng cao là gRPC và GraphQL. Bạn sẽ nắm vững nguyên tắc định danh field bằng số trong file `.proto` để tránh sự cố tính sai tiền trên hàng nghìn hóa đơn, thiết lập deadline chặt chẽ cho lời gọi gRPC và phân phối tải HTTP/2 qua proxy tầng 7. Với GraphQL, bạn sẽ kiểm soát hiện tượng null lan truyền khi đổi kiểu trường dữ liệu, triệt tiêu bài toán N+1 bằng cơ chế batching theo tick và kiểm soát chi phí thực thi của query qua allowlist. Bài tình huống cuối chương hướng dẫn chuyển đổi một lời gọi nội bộ có tần suất **3.000 request/giây** từ JSON sang gRPC dựa trên phân tích profile CPU, giúp giảm **30%** lượng tiêu thụ tài nguyên tính toán mà không gây gián đoạn cho các service còn lại.

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

Trong thực tế phát triển phần mềm, một API hiếm khi chỉ phục vụ riêng một client do chính bạn kiểm soát. Khi hệ thống mở rộng, API của bạn nhanh chóng trở thành điểm tựa cho service của các team khác, app mobile tồn tại lâu dài trên máy khách hàng, hoặc hàng trăm đối tác kinh doanh bên ngoài. Từng service, app mobile hay đối tác đều xây dựng logic nghiệp vụ dựa trên từng chi tiết mà API trả về vào thời điểm tích hợp, và từ lúc đó, việc sửa một tên field hay thêm một trạng thái đơn hàng không còn là quyết định nội bộ của một team.

Rủi ro lớn nhất là các sự cố phá vỡ contract thường không hiển thị trên dashboard giám sát của chính server cung cấp API. Hệ thống gateway vẫn ghi nhận tỉ lệ response 2xx đạt mức lý tưởng, các bài unit test nội bộ vẫn xanh, nhưng tiến trình đồng bộ của đối tác đã dừng hoạt động vì parser gặp lỗi runtime. Kỹ sư trực ca phải mất hàng giờ ghép nối các dòng log rời rạc giữa các service để tìm nguyên nhân gốc rễ, đối mặt với các đợt đối soát sai lệch số liệu và buộc phải rollback khẩn cấp trong sự bị động.

Phần lớn kỹ thuật bảo vệ tương thích vốn không đòi hỏi những công cụ quá phức tạp: một mã lỗi ổn định trong Problem Details, một tham số định danh đối tác trong access log, một bước kiểm tra contract test trong pipeline CI/CD hay một header ngữ cảnh gắn liền với request. Điểm mấu chốt nằm ở tư duy nhận diện đâu là ranh giới contract, hiểu rõ tác động của từng thay đổi lên lịch deploy độc lập của consumer, và xác định chính xác thời điểm nào hệ thống cần áp dụng các giải pháp này.

200Lab xây dựng khóa học này nhằm giúp bạn làm chủ quy trình thiết kế và tiến hóa API một cách chuyên nghiệp. Sau khóa học, mỗi lần cập nhật API của bạn sẽ bắt đầu bằng việc đánh giá mức độ tương thích trên từng nhóm consumer, chủ động theo dõi số liệu vận hành thực tế và bảo vệ hệ thống vận hành bền bỉ qua từng đợt phát hành.

## Những vấn đề thường gặp khi thiết kế API giữa các service

Khi phát sinh sự cố tích hợp, phản xạ ban đầu của nhiều đội ngũ là chỉ kiểm tra các chỉ số tại chính service của mình như tỉ lệ response 2xx, tài nguyên CPU hay log cục bộ. Với hệ thống phân tán, nguyên nhân gốc rễ thường nằm ở sự lệch pha về contract, cách hiểu sai ngữ nghĩa giao thức hoặc thiếu cơ chế quan sát xuyên suốt giữa các service.

- Gateway ghi nhận **99,6%** response 2xx nhưng đối tác tạo ticket báo hàng nghìn đơn hàng bị thất lạc — Server trả mã 200 kèm body báo lỗi nghiệp vụ, khiến thư viện HTTP của client ngầm hiểu request thành công và không kích hoạt nhánh xử lý lỗi.
- Bản cập nhật biên dịch lại thông báo lỗi sang tiếng Việt khiến tỉ lệ bỏ dở đơn hàng của đối tác tăng vọt từ **3%** lên **11%** — Error model không cung cấp field `code` ổn định, buộc code tích hợp của đối tác phải so sánh trực tiếp chuỗi thông báo bằng tiếng Anh.
- Tỉ lệ hoàn hàng của nhóm đơn COD được xác nhận dưới 10 giây sau khi gửi email tăng đột biến lên **31%** chỉ vì thao tác kích hoạt nằm trên đường link mở bằng GET — Endpoint làm thay đổi trạng thái nghiệp vụ bị các bộ lọc email doanh nghiệp tự động truy cập để quét mã độc.
- Tiến trình đồng bộ dữ liệu chạy qua **120 request** thành công nhưng vẫn bỏ sót **1.100 bản ghi** — Cơ chế phân trang theo offset bị trôi vị trí khi các dòng dữ liệu phía trước liên tục thay đổi trạng thái trong quá trình đọc.
- Bổ sung một giá trị mới vào danh sách trạng thái đơn hàng làm tê liệt hệ thống ERP của đối tác suốt **6 giờ** — Contract không quy định nguyên tắc tolerant reader, khiến bộ parser phía client ném ngoại lệ khi gặp giá trị chưa từng khai báo.
- Toàn bộ test của hai service độc lập đều đạt kết quả tuyệt đối nhưng màn hình thanh toán tính sai tiền hàng loạt — Test phía consumer dựa trên dữ liệu mock cũ nên không phát hiện việc provider đã đổi tên field dữ liệu trong đợt refactor.
- Tắt version API cũ theo đúng thời hạn thông báo sáu tháng trước nhưng buộc phải khôi phục lại chỉ sau hơn **1 giờ** — Access log không định danh lưu lượng theo từng API key, khiến đội ngũ không nắm được còn đối tác quan trọng chưa hoàn tất chuyển đổi.
- Bổ sung replica cho service gRPC nhưng một node vẫn chịu tải **90%** CPU trong khi các node còn lại gần như không hoạt động — Load balancer tầng 4 chia tải theo connection TCP, ghim chặt các connection HTTP/2 tồn tại lâu vào một node duy nhất.

Mỗi tình huống trên đều được phân tích cặn kẽ từ tín hiệu vận hành thực tế trong khóa học, giúp bạn hiểu rõ bản chất vấn đề và áp dụng giải pháp tương ứng.

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

- **Phân tích từ triệu chứng kỹ thuật thực tế** — Mỗi bài học bắt đầu từ một tình huống kỹ thuật và dữ liệu minh họa dùng để phân tích cơ chế: một dòng log lỗi, tỉ lệ response bất thường, báo cáo đối soát chênh lệch hay tình trạng nghẽn tài nguyên, đi kèm câu hỏi định hướng giải quyết.
- **Minh họa trực quan bằng dữ liệu minh họa** — Mọi khái niệm contract được thể hiện qua các khối request và response hoàn chỉnh, đoạn trích file cấu hình, sơ đồ luồng dữ liệu và lược đồ trạng thái minh bạch.
- **Đánh giá giải pháp qua góc nhìn tradeoff** — Mỗi quyết định thiết kế từ việc chọn status code, cấu trúc error model, chiến lược versioning cho đến phân bổ replica đều được cân nhắc giữa lợi ích thu được và chi phí vận hành đi kèm.
- **Kiểm chứng qua các bài quiz tình huống** — Hệ thống câu hỏi tình huống giúp bạn tự dự đoán hành vi của hệ thống trước khi triển khai, củng cố phản xạ nhận diện các thay đổi có nguy cơ phá vỡ tương thích.
- **Thực hành qua các kịch bản mẫu** — Các bài học trọng tâm cung cấp hướng dẫn thiết lập hệ thống mẫu và kịch bản tạo tải để bạn trực tiếp quan sát sự cố, thực hiện tinh chỉnh và đo lường sự thay đổi của các chỉ số hiệu năng.

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

1. **Backend developer phụ trách API cho nhiều client** — Bạn phát triển các endpoint phục vụ đồng thời web, app mobile và các service nội bộ khác, cần tiến hóa tính năng an toàn mà không phải phụ thuộc vào lịch deploy của các team liên quan.
2. **Kỹ sư vận hành hệ thống tích hợp đối tác** — Bạn quản lý các cổng kết nối API và hạ tầng webhook công khai, cần kiểm soát lưu lượng, nắm bắt chính xác mức độ sử dụng của từng đối tác và lập kế hoạch ngừng hỗ trợ phiên bản cũ dựa trên số liệu.
3. **Developer xây dựng service phụ thuộc vào API bên ngoài** — Bạn cần thiết lập cơ chế khai báo nhu cầu dữ liệu và tích hợp contract test tự động vào pipeline CI/CD để ngăn chặn rủi ro gãy kết nối khi provider cập nhật hệ thống.
4. **Kỹ sư cân nhắc tối ưu giao thức truyền tải** — Bạn cần các tiêu chí định lượng dựa trên tần suất request và chi phí xử lý dữ liệu để đưa ra quyết định chuyển đổi giữa REST, gRPC và GraphQL cho từng tác vụ cụ thể.

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

- **Yêu cầu về kiến thức lập trình backend cơ bản** — Bạn cần nắm vững cấu trúc phân tầng bên trong một service giữa tầng handler tiếp nhận HTTP và tầng use case xử lý logic, hiểu rõ cấu trúc JSON và cách tương tác với database. Khóa học tập trung chuyên sâu vào ranh giới contract và sự tiến hóa của giao diện lập trình, không giảng giải lại cú pháp lập trình cơ bản.
- **Phạm vi nội dung được giới hạn rõ ràng** — Khóa học không bao gồm kỹ thuật cấu hình chi tiết cho từng loại API gateway phần cứng, các giao thức bảo mật phân quyền sâu như OAuth2 hay mTLS, quản trị message broker trong kiến trúc event-driven, và các giao thức thời gian thực hai chiều liên tục như WebSocket. Mục tiêu là giúp bạn làm chủ nguyên lý thiết kế và đưa ra quyết định kỹ thuật đúng đắn.
- **Số liệu minh họa phục vụ phân tích logic** — Mọi thông số về quy mô request, dung lượng dữ liệu hay tỉ lệ lỗi trong các bài học được xây dựng nhằm làm rõ phép tính kỹ thuật và mối liên hệ giữa các thành phần, làm khuôn mẫu để bạn đối chiếu và áp dụng vào số liệu thực tế trên hệ thống của mình.

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

Khóa học mở đầu bằng tình huống trực ca sáng thứ Hai: dashboard gateway hiển thị tỉ lệ response 2xx đạt **99,7%** nhưng số lượng ticket báo lỗi từ đối tác tăng gần **8 lần**. Bài học đầu tiên sẽ cùng bạn phân tích bốn sự cố ẩn sau số liệu đó, định nghĩa đầy đủ các thành phần cấu thành một contract API, và xác định vị trí hệ thống của bạn trên thang quy mô consumer. Những phân tích này sẽ giúp bạn nhận diện chính xác các cơ chế bảo vệ cần ưu tiên áp dụng ngay cho hệ thống hiện tại.

## Chương trình

- Vì sao đổi API lại khó hơn nhiều so với đổi code bên trong service? (miễn phí)

### Resource, method, status code và error model

- Một màn hình cần mười request vì API được dựng theo từng bảng (miễn phí)
- Chọn HTTP method để công cụ quét link không xác nhận đơn thay khách (miễn phí) · quiz
- API trả 200 cho cả request bị từ chối · quiz
- Sửa message lỗi làm code của đối tác không nhận ra lỗi hết hàng
- Kiểm tra payload theo schema để dữ liệu sai kiểu không lọt vào database · quiz

### Cursor cho danh sách dài, trả 202 cho thao tác chạy lâu

- Phân trang bằng offset bỏ sót bản ghi khi danh sách đang thay đổi · quiz
- Trả 202 kèm status resource để consumer biết thao tác chạy lâu đã xong chưa · quiz
- Thiết kế API nhập 300.000 sản phẩm từ một file CSV · kit cho agent

### Đổi API mà không làm hỏng consumer đang gọi

- Đưa contract của API vào một file được review cùng code
- Vì sao chỉ thêm một giá trị enum cũng có thể là breaking change · quiz
- Đổi kiểu dữ liệu của một field khi app bản cũ vẫn còn trên máy người dùng · quiz
- Tắt version API cũ dựa trên số request của từng API key
- Test của hai service đều xanh mà service checkout vẫn tính sai giá · quiz
- Đối tác đồng bộ đơn hàng qua API mà vẫn thiếu đơn · kit cho agent

### Request đi qua nhiều service và webhook gửi ra cho đối tác

- Người bán đọc được đơn hàng của người bán khác qua API nội bộ · quiz
- Dùng correlation ID để gom log của một request đi qua nhiều service · quiz
- Thiết kế contract cho webhook mà nền tảng gửi tới đối tác · kit cho agent

### Contract gRPC, contract GraphQL và cách chọn giao thức

- Đánh số lại field trong file .proto làm hóa đơn ghi sai tiền thuế · quiz
- Service đơn hàng treo theo service tồn kho vì lời gọi gRPC không có deadline · quiz
- Vì sao thêm replica mà mọi lời gọi gRPC vẫn dồn vào một replica · quiz
- Đổi một field GraphQL sang non-null làm cả object cha thành null · quiz
- Một query GraphQL gây ra hàng trăm truy vấn xuống database · quiz
- Chọn REST, gRPC hay GraphQL cho từng loại consumer
- Chuyển API của service gợi ý sản phẩm từ REST sang gRPC · kit cho agent
