Vì sao versioning là bài toán về niềm tin
Khi một dev đưa API của bạn lên production, họ đặt cược sự ổn định của hệ thống họ vào tay bạn. Một breaking change bất ngờ có thể làm sập ứng dụng của họ lúc 3 giờ sáng. Vì thế versioning và deprecation không chỉ là vấn đề kỹ thuật — chúng là quản trị niềm tin. DX PM giỏi biết rằng một lần phá vỡ backward compatibility cẩu thả có thể mất khách hàng vĩnh viễn, dù tính năng mới có hay đến đâu.
Phân biệt: thay đổi phá vỡ và không phá vỡ
Non-breaking (an toàn, thêm được bất cứ lúc nào):
- Thêm endpoint mới.
- Thêm trường optional vào request.
- Thêm trường mới vào response (dev cũ bỏ qua được).
- Thêm giá trị enum mới nếu dev đã được cảnh báo phải xử lý giá trị lạ.
- Xóa hoặc đổi tên trường/endpoint.
- Đổi kiểu dữ liệu hoặc ý nghĩa của trường.
- Biến trường optional thành bắt buộc.
- Thay đổi hành vi mặc định, taxonomy lỗi, hoặc format.
Đặc thù AI: khi "mô hình" là một dạng version ẩn
AI tooling có một loại breaking change đặc biệt nguy hiểm: thay đổi mô hình bên dưới. Cùng endpoint, cùng schema, nhưng nâng cấp mô hình có thể làm output đổi tính chất — prompt cũ cho kết quả khác, độ dài khác, giọng văn khác. Với dev đã tinh chỉnh prompt cẩn thận, đây là breaking change dù schema không đổi. Cách xử lý:
- Pin phiên bản mô hình: cho phép dev chỉ định
model: "gpt-x-2026-06"thay vì alias động, để họ chủ động chọn thời điểm nâng cấp. - Có alias "latest" tùy chọn cho ai muốn luôn mới nhất, nhưng mặc định nên là bản pin ổn định.
- Thông báo rõ khi model sunset, kèm hướng dẫn migrate và thời gian chuyển tiếp.
Chiến lược versioning
Có vài cách phổ biến; chọn cách và nhất quán:
- URL versioning (
/v1/,/v2/): dễ hiểu, rõ ràng, phổ biến nhất. - Header versioning (
API-Version: 2026-06-01): linh hoạt, kiểu date-based cho phép nâng cấp mượt. - Dù chọn gì, giữ version cũ chạy song song đủ lâu; đừng ép migrate ngay.
Quy trình deprecation nhân văn
Một deprecation làm đúng gồm các bước:
- Thông báo sớm và rõ: qua changelog, email, dashboard, và header
Deprecation/Sunsetngay trong response để dev thấy trong log. - Đưa ra timeline cụ thể (ví dụ tối thiểu 6-12 tháng cho breaking change lớn) — càng nhiều khách production, timeline càng dài.
- Cung cấp migration guide với ví dụ code trước/sau, và nếu được, công cụ tự động phát hiện chỗ dùng cũ.
- Cảnh báo tăng dần: log warning → email nhắc → (đôi khi) brownout ngắn có kế hoạch trước khi tắt hẳn.
- Tắt chỉ sau khi đã theo dõi lượng dùng còn lại gần bằng 0 và đã liên hệ trực tiếp khách lớn còn sót.
Ví dụ cụ thể
Một team cần đổi format của một trường timestamp. Thay vì sửa tại chỗ (breaking), họ thêm trường mới created_at_iso bên cạnh trường cũ, đánh dấu trường cũ là deprecated trong docs với header Sunset, và đợi 9 tháng theo dõi lượng dùng. Khi trường cũ gần như không ai gọi, họ mới gỡ. Không một khách nào bị sập — niềm tin được giữ nguyên.
Khung tư duy: "Đối xử với API cũ như lời hứa đã ký"
Mỗi endpoint public là một lời hứa. Bạn được phép thay đổi lời hứa, nhưng phải báo trước, cho thời gian, và giúp người ta chuyển. Tốc độ ship tính năng mới không bao giờ đáng đánh đổi bằng việc phản bội các tích hợp production đang chạy.
Checklist versioning & deprecation
- [ ] Thay đổi này thật sự breaking hay có thể làm additive?
- [ ] Với AI: dev có pin được phiên bản mô hình không?
- [ ] Có changelog công khai và header
Deprecation/Sunsetkhông? - [ ] Timeline deprecation có đủ dài cho khách production không?
- [ ] Có migration guide với ví dụ trước/sau không?
- [ ] Đã theo dõi lượng dùng còn lại trước khi tắt chưa?
Sai lầm thường gặp
- Ship breaking change im lặng, coi "chắc không ai để ý" — dev luôn để ý.
- Nâng cấp mô hình mặc định mà không cho pin, làm hỏng prompt đã tinh chỉnh của khách.
- Deprecation timeline quá ngắn, ép migrate gấp và gây bức xúc.
- Không có migration guide, để dev tự mò cách chuyển.
- Sửa tại chỗ thay vì thêm mới, biến một cải tiến nhỏ thành sự cố diện rộng.