API versioning trong web/app: thay đổi sản phẩm mà không làm gãy client cũ

19 lượt xem · 1 trả lời

1. 05:25 06/08/2026
Khi một web/app còn nhỏ, API thường được sửa khá thoải mái: đổi tên field, thêm trạng thái mới, thay cấu trúc response… Nhưng khi đã có mobile app, web frontend, đối tác tích hợp hoặc các service nội bộ cùng dùng API, mỗi thay đổi đều có thể làm “gãy” client cũ. Đây là lúc cần nghĩ nghiêm túc về API versioning. API versioning không phải để làm hệ thống phức tạp hơn, mà để cho phép backend tiến lên trong khi client có thời gian cập nhật. Một ví dụ thực tế Giả sử API hiện tại trả về thông tin đơn hàng: GET /api/orders/123 Response có field: - id - total - status Ban đầu status chỉ có: pending, paid, cancelled. Sau này hệ thống thêm quy trình giao hàng, status có thêm shipping, delivered, returned. Nếu mobile app cũ chỉ biết 3 trạng thái ban đầu, app có thể hiển thị sai hoặc lỗi giao diện. Một thay đổi khác nguy hiểm hơn: đổi total từ số tiền đơn hàng sang object chi tiết: - Trước: "total": 250000 - Sau: "total": {"amount": 250000, "currency": "VND"} Với frontend mới thì hợp lý, nhưng client cũ có thể crash vì đang kỳ vọng total là number. Những kiểu thay đổi dễ làm gãy API Không phải thay đổi nào cũng cần version mới. Nên phân biệt: Thường an toàn: - Thêm field mới vào response. - Thêm endpoint mới. - Thêm query parameter không bắt buộc. - Sửa bug mà không đổi contract đã công bố. Có nguy cơ breaking change: - Xóa hoặc đổi tên field. - Đổi kiểu dữ liệu của field. - Đổi ý nghĩa của field. - Thay đổi format lỗi. - Bắt buộc thêm parameter mới. - Đổi logic phân quyền hoặc trạng thái theo cách client cũ không xử lý được. Các cách versioning phổ biến 1. Version trong URL Ví dụ: - /api/v1/orders/123 - /api/v2/orders/123 Cách này dễ hiểu, dễ debug, dễ cấu hình routing. Đây là lựa chọn thực dụng cho nhiều đội nhỏ và vừa. Nhược điểm là URL có thể bị “đóng dấu phiên bản” khá rõ, đôi khi v2 chỉ khác một phần nhỏ nhưng vẫn phải tách endpoint. 2. Version qua header Ví dụ client gửi: - Accept: application/vnd.myapp.v2+json Cách này gọn URL và phù hợp với một số API thiết kế chặt chẽ. Tuy nhiên khó thử nhanh trên trình duyệt, dễ bị bỏ sót khi debug, và cần tài liệu rõ ràng hơn. 3. Version theo từng field hoặc capability Thay vì tạo /v2, server có thể hỗ trợ thêm option: - GET /api/orders/123?include=payment_breakdown Hoặc client gửi capability mà mình hỗ trợ. Cách này linh hoạt, nhưng nếu không kiểm soát tốt sẽ biến API thành nhiều nhánh logic khó bảo trì. Lời khuyên thực dụng khi triển khai Đừng tạo version mới cho mọi thay đổi nhỏ. Nếu chỉ thêm field mới và client cũ có thể bỏ qua, thường không cần v2. Nhưng nếu đổi cấu trúc dữ liệu hoặc thay hành vi cũ, hãy cân nhắc version mới. Giữ contract rõ ràng. Với mỗi endpoint quan trọng, nên biết request gồm gì, response gồm gì, lỗi có format nào. Tài liệu không cần quá màu mè, nhưng phải đủ để frontend, mobile hoặc đối tác không đoán mò. Đừng xóa vội version cũ. Hãy có thời gian chuyển tiếp. Ví dụ: thông báo v1 sẽ ngừng sau một mốc cụ thể, thêm log để biết client nào còn gọi v1, rồi mới dọn dẹp. Theo dõi usage theo version. Nếu không biết còn ai dùng /v1/orders, bạn sẽ không dám xóa. Chỉ cần log version, endpoint, app version hoặc client id là đã giúp ra quyết định tốt hơn. Thiết kế response dễ mở rộng. Ví dụ thay vì để client phụ thuộc vào text hiển thị từ backend, có thể trả status code ổn định và để frontend map nhãn phù hợp. Với các danh sách trạng thái có khả năng tăng thêm, client nên có fallback như “Trạng thái khác” thay vì lỗi trắng màn hình. Kết luận API versioning là một dạng bảo hiểm kỹ thuật cho quá trình phát triển sản phẩm. Làm quá sớm và quá phức tạp sẽ tốn công, nhưng bỏ qua hoàn toàn thì đến lúc nhiều client cùng phụ thuộc, mỗi lần sửa API đều thành rủi ro. Cách tiếp cận hợp lý là: xác định rõ breaking change, chọn một kiểu versioning dễ vận hành, theo dõi client đang dùng phiên bản nào, và luôn cho hệ thống có thời gian chuyển tiếp trước khi loại bỏ API cũ.
0 Facebook
2. 12:29 13/10/2026
Trả lời Quản Trị Viên Khi một web/app còn nhỏ, API thường được sửa khá thoải mái: đổi tên field, thêm trạng thái mới, thay cấu trúc response… …
Bài viết rất thực tế, đặc biệt phần phân biệt "an toàn" và "breaking change" giúp team dễ quyết định có nên bump version hay không. Mình thấy cách để `total` là number rồi đổi sang object là ví dụ điển hình của breaking change lén lút – dễ bị bỏ qua khi review code vì test case thường chỉ kiểm tra happy path. Đội mình trước đây dùng version trong URL (v1, v2) cho đơn giản, nhưng sau này chuyển sang header `Accept` để URL gọn hơn cho SEO và client. Tuy nhiên debug trên Postman/Swagger thì hơi phiền vì dev hay quên set header. Có bác nào đã thử kết hợp cả hai: mặc định URL không version (trỏ về latest stable) nhưng cho phép override qua header khi cần test version cũ không? Cách này có giúp giảm cognitive load cho client mới không?
0
Vui lòng đăng nhập để tham gia trả lời chủ đề này.
Điều hướng nhanh

Bạn muốn khám phá điều gì?

Tìm chủ đề, bài viết hoặc đi thẳng đến một khu vực của cộng đồng.

Esc để đóng Ctrl K để mở lại