AllianceProject Handbook
← Knowledge

Phát hành

Backward compatibility giữa app và backend

User không update app ngay. Mọi thay đổi backend phải sống chung với các app version cũ còn ngoài thị trường, hoặc phải có cách buộc update.

Cập nhật 12/09/2026releaseapitương thích

Vấn đề riêng của mobile

Trên web, deploy xong là mọi user dùng bản mới trong vài phút. Trên mobile thì không: sau khi release, thị trường có nhiều app version chạy song song trong nhiều tháng. Một phần user không bao giờ update cho tới khi buộc phải làm.

Hệ quả: backend không phục vụ một client. Nó phục vụ tất cả app version còn sống. Một thay đổi backend tưởng như vô hại có thể giết chết các bản cũ ngay lập tức, và những user đó thậm chí không biết vì sao app đột nhiên hỏng.

Version matrix

Dự án giữ bảng này và cập nhật mỗi release:

App versionAPI versionTrạng tháiGhi chú
1.0 – 1.2v1DeprecatedHết hỗ trợ từ ngày công bố
1.3 – 1.5v1Minimum supportedCòn phục vụ, hiện banner mời update
1.6v1, v2RecommendedBản đa số user đang dùng
1.7v2LatestBản mới nhất trên store

Ba mốc phải luôn trả lời được, và backend phải đọc được chúng từ cấu hình, không phải từ trí nhớ của một người:

  • Minimum supported version — dưới mức này app bị chặn, buộc update.
  • Recommended version — dưới mức này hiện thông báo mời update, không chặn.
  • Latest version — bản đang có trên store.

Luật thay đổi API

Trong cùng một API version, chỉ được phép thay đổi theo hướng cộng thêm:

Được phépKhông được phép
Thêm field mới vào responseĐổi tên field đang có
Thêm endpoint mớiXoá field đang có
Thêm giá trị mới vào enum, nếu client đã xử lý giá trị lạĐổi kiểu dữ liệu của field
Nới lỏng validation đầu vàoSiết chặt validation đầu vào
Đổi ý nghĩa của một field mà giữ nguyên tên

Ví dụ kinh điển: backend đổi userName thành username. Với backend đó là một dòng diff. Với các app version cũ đang parse userName, đó là màn hình trắng hoặc crash cho toàn bộ user chưa update.

Cần thay đổi phá vỡ tương thích thì mở API version mới, giữ version cũ chạy song song cho tới khi số user ở các app version cũ rơi xuống dưới ngưỡng đã công bố.

Contract test

Luật ở trên chỉ có giá trị nếu có cơ chế chặn tự động. Cơ chế đó là contract test: schema của mỗi response được publish và version hoá; CI của backend chạy kiểm tra schema mới so với schema các version còn được hỗ trợ, và fail build khi phát hiện thay đổi phá vỡ tương thích.

Không có contract test thì luật này chỉ tồn tại trên giấy, và nó sẽ bị vi phạm bởi một người không biết luật, vào một chiều thứ sáu.

Force upgrade

Backend trả về cho client biết version tối thiểu; app so sánh và chặn nếu thấp hơn.

Force upgrade là phương án cuối, không phải công cụ tiện tay. Nó đẩy toàn bộ chi phí sang user: họ đang giữa việc thì bị chặn, phải tải một bản cập nhật có thể nặng, có thể đang ở mạng di động. Chỉ dùng khi:

  • Có lỗ hổng bảo mật ở bản cũ, hoặc
  • Bản cũ tạo ra dữ liệu sai mà không sửa được từ phía server, hoặc
  • API version cũ đã được thông báo deprecated đủ lâu và số user còn lại rất nhỏ.

Không dùng force upgrade chỉ vì backend muốn dọn code cho gọn.

Màn hình chặn phải nói rõ vì sao và có nút mở thẳng store. Chặn mà không giải thích là cách nhanh nhất để nhận đánh giá một sao.

Feature flag và remote config

Trên mobile không rollback được binary đã cài. Vì vậy khả năng tắt một tính năng từ xa là thứ thay thế cho rollback — xem Quy trình release và rollback.

Nên điều khiển từ xaKhông nên
Bật/tắt một tính năng mớiToàn bộ business logic
Tỷ lệ user được mở tính năngCông thức tính tiền, thuế, chiết khấu
Timeout, số lần retryQuy tắc phân quyền
Minimum supported versionNội dung màn hình phức tạp
Chế độ bảo trì, URL hỗ trợ

Hai luật đi kèm:

  1. Mỗi flag có chủ và có hạn. Flag sống quá hai release mà không được dọn thì trở thành nợ: số nhánh code nhân đôi mỗi lần thêm một flag, và không ai còn dám xoá.
  2. App phải chạy đúng khi không lấy được remote config. Luôn có giá trị mặc định biên dịch sẵn trong app. Config server chết mà app chết theo là đã tự tạo thêm một điểm gãy.

Giới hạn

  • Backward compatibility tốn chi phí thật: backend phải giữ code cũ, test phải chạy trên nhiều version. Vì vậy phải có chính sách deprecate rõ ràng, nếu không số version phải hỗ trợ sẽ tăng mãi.
  • Version matrix chỉ hữu ích khi được cập nhật. Bảng cũ sáu tháng còn nguy hiểm hơn không có bảng, vì người ta vẫn tin vào nó.