Thiết kế API cho pin di động: giảm tần suất yêu cầu
Thiết kế API cho pin di động: học cách gộp yêu cầu, dùng header cache và thu gọn payload để giảm các wakeup radio, tăng tốc màn hình và giảm hao pin.

Tại sao API “nhiều cuộc gọi” làm hao pin trên di động
Một API “chatty” khiến app gửi nhiều yêu cầu nhỏ để dựng lên một màn hình. Mỗi yêu cầu trên giấy có vẻ rẻ, nhưng trên điện thoại chúng cộng lại rất nhanh.
Tác động pin lớn nhất thường đến từ radio mạng. Chip Cellular và Wi‑Fi chuyển sang trạng thái công suất cao để gửi và nhận dữ liệu. Khi một app gửi nhiều yêu cầu gần nhau, radio liên tục thức dậy và giữ hoạt động lâu hơn. Dù mỗi phản hồi nhỏ, các lần thức dậy lặp lại tiêu tốn năng lượng thực sự.
CPU cũng phải làm việc. Mỗi yêu cầu nghĩa là xây header, thực hiện TLS, parse JSON, cập nhật cache và chạy mã app để hợp nhất kết quả. Nếu kết nối rớt, công việc khởi tạo phải lặp lại.
Tính chatty còn làm giao diện cảm thấy chậm hơn. Thay vì một lần tải dự đoán được, màn hình chờ một chuỗi các gọi. Bạn sẽ thấy spinner lâu hơn, render từng phần nhảy chỗ, và nhiều timeout hơn khi mạng yếu. Làm mới nền cũng tệ đi theo cùng cách: nhiều retry hơn, nhiều wakeup hơn, nhiều hao pin hơn.
Một cách thực tế để nghĩ về thiết kế API cho pin di động rất đơn giản: hiển thị cùng UI với ít vòng đi lại hơn, ít byte hơn, và ít công việc nền hơn.
Bạn có thể theo dõi thành công bằng vài thay đổi cụ thể:
- Ít cuộc gọi API hơn cho một lần tải màn hình
- Ít byte tải xuống hơn cho một màn hình
- Thời gian tới tương tác trung vị và trường hợp xấu hơn trên mạng di động tốt hơn
- Ít lần lấy nền và retry hơn để đạt kết quả tương đương
Khi những chỉ số đó cải thiện, độ phản hồi và thời lượng pin thường cải thiện cùng nhau.
Cần đo gì trước khi thay đổi
Trước khi gộp yêu cầu hay tinh chỉnh cache, hãy có hình ảnh rõ ràng về app hiện tại. Những chiến thắng nhanh thường đến từ sửa vài thủ phạm lặp lại, nhưng bạn chỉ tìm ra chúng nếu đo màn hình và luồng thực (không chỉ một lần chạy đường truyền hiển nhiên).
Với vài màn hình có lưu lượng cao, ghi log cơ bản: có bao nhiêu yêu cầu mỗi lần tải, các endpoint nào được gọi, byte gửi và nhận (headers cộng body), tỉ lệ retry và timeout, và mất bao lâu để UI cảm thấy có thể dùng được. Nếu được, tách tỉ lệ lỗi theo loại mạng (Wi‑Fi vs cellular). Các tách này thường tiết lộ vấn đề trên kết nối không ổn định.
Tách traffic foreground và background. Một màn hình có thể trông yên tĩnh, nhưng điện thoại có thể bận với làm mới nền, đồng bộ kích hoạt bởi push, tải analytics, hoặc các cuộc gọi prefetch “phòng khi cần”. Theo dõi riêng để bạn không tối ưu sai thứ.
Các điểm nóng thường tụ quanh vài khoảnh khắc: khởi động app, màn hình chính/feed, màn hình chi tiết đẩy ra nhiều gọi, và pull-to-refresh. Chọn một trong những màn này và đo end-to-end.
Đặt một ngân sách baseline để đội ngũ đồng thuận thế nào là “tốt”. Ví dụ: “Một lần tải lạnh của màn hình theo dõi đơn hàng không nên phát sinh quá 6 yêu cầu và tải không quá 250 KB trước khi hiển thị trạng thái.”
Nếu muốn một cặp KPI đơn giản để bắt đầu, dùng (1) số yêu cầu cho mỗi lần tải màn hình và (2) tỉ lệ retry. Cắt giảm retry thường tiết kiệm pin nhiều hơn mong đợi, vì retry lặp lại giữ radio hoạt động lâu hơn.
Từng bước: giảm yêu cầu bằng batching
API chatty dễ tạo ra một cách vô ý. Mỗi widget tải “dữ liệu của nó”, và một màn hình kích hoạt hàng chục cuộc gọi. Khắc phục thường không phức tạp: xác định những gì luôn tải cùng nhau và trả về trong ít cuộc gọi hơn.
Bắt đầu bằng việc lập sơ đồ một màn hình có lưu lượng cao (home, inbox, danh sách đơn hàng). Ghi lại những gì xuất hiện above the fold, rồi truy nguồn từng phần tử UI tới yêu cầu cung cấp nó. Bạn thường thấy trùng lặp (cùng profile người dùng bị fetch hai lần) và các gọi luôn đi cùng nhau (profile + permissions + unread count).
Tiếp theo, nhóm các gọi luôn xảy ra cùng nhau. Thông thường bạn có hai lựa chọn:
- Tạo một endpoint phục vụ mục đích riêng cho màn hình đó (thường ổn định nhất)
- Thêm một endpoint batch chấp nhận danh sách nhỏ, có thể dự đoán của các tài nguyên
Giữ các batch theo màn hình và có giới hạn để dễ cache, giám sát và debug.
Một vài quy tắc giúp batching không biến thành mớ hỗn độn. Trả về chỉ những gì màn hình cần ngay bây giờ, không phải toàn bộ đối tượng “phòng khi”. Nếu có phần tùy chọn, làm rõ để UI có thể render phần quan trọng nhanh. Thiết kế phản hồi để thất bại từng phần không bắt retry toàn bộ. Rẻ hơn nhiều khi chỉ retry phần lỗi hơn là gửi lại toàn bộ batch.
Header cache thông minh giúp tiết kiệm pin (không chỉ băng thông)
Caching là một tính năng tiết kiệm pin. Mỗi yêu cầu thức dậy radio, giữ CPU bận và kích hoạt parse cùng logic app. Header cache tốt biến nhiều lần làm mới thành các kiểm tra nhẹ.
Chiến thắng lớn nhất là các yêu cầu điều kiện. Thay vì tải lại cùng dữ liệu, app hỏi “Cái này có thay đổi không?” Nếu không, server trả 304 Not Modified rất nhỏ.
Dùng ETag trên phản hồi biểu diễn phiên bản tài nguyên, và cho client gửi If-None-Match ở lần fetch tiếp theo. Nếu tạo ETag khó, Last-Modified với If-Modified-Since vẫn hoạt động tốt cho các tài nguyên kiểu “updated at”.
Với dữ liệu hiếm khi thay đổi, hãy quyết định cache rõ ràng. Cache-Control nên phản ánh thực tế. Một max-age ngắn cho profile người dùng có thể ổn, trong khi cấu hình app, danh sách tham chiếu và feature flag thường được để lâu hơn.
Ở phía app, xử lý 304 như đường dẫn nhanh. Đừng parse JSON (vì không có), đừng rebuild model, và đừng làm UI nhấp nháy. Giữ những gì đã hiển thị và chỉ cập nhật chỉ báo.
Ví dụ: màn hình theo dõi đơn hàng poll trạng thái mỗi 15 giây. Nếu phản hồi bao gồm ETag, hầu hết kiểm tra có thể trả 304. App giữ trạng thái cuối cùng và chỉ làm việc thực sự khi trạng thái thay đổi (ví dụ “Đã đóng gói” sang “Đã gửi”).
Cân nhắc cẩn thận với dữ liệu nhạy cảm. Caching không tự động nguy hiểm, nhưng cần quy tắc rõ ràng. Tránh cache phản hồi có thông tin cá nhân hoặc token trừ khi yêu cầu sản phẩm cho phép. Dùng thời lượng ngắn cho dữ liệu người dùng cụ thể, và ngăn cache chia sẻ lưu trữ phản hồi riêng tư (dùng Cache-Control: private khi cần).
Payload thông minh hơn: gửi ít hơn, parse ít hơn
Mỗi byte thừa tiêu tốn nhiều hơn băng thông trên di động. Nó giữ radio thức dậy lâu hơn và khiến app tốn CPU giải nén JSON và cập nhật model. Nếu mục tiêu là giảm tần suất yêu cầu, cắt payload thường là chiến thắng nhanh nhất.
Bắt đầu bằng audit payload theo màn hình. Chọn một màn hình (ví dụ home feed), ghi lại kích thước phản hồi và xem từng trường: client có render trường này không, hay chỉ dùng để quyết định hiển thị? Nếu không, loại bỏ khỏi endpoint đó.
Với danh sách, một dạng “tóm tắt” nhỏ thường đủ. Một hàng danh sách thường cần id, tiêu đề, trạng thái và timestamp. Không cần mô tả đầy đủ, ghi chú dài, hoặc các object lồng sâu. Lấy chi tiết chỉ khi người dùng mở item.
Một vài thay đổi thường cắt payload nhanh:
- Ưu tiên id hoặc mã enum ngắn thay vì chuỗi dài lặp lại
- Đừng gửi lại giá trị mặc định hiển nhiên mà client có thể suy ra
- Tránh lặp cùng một object lồng trong mọi item danh sách
- Giữ tên trường và kiểu ổn định để client ít phải phân nhánh và parse lại
Nén dữ liệu có thể hữu ích, nhất là trên mạng chậm, nhưng kiểm tra chi phí CPU trên thiết bị thật. Gzip hoặc Brotli thường giảm nhiều kích thước truyền, nhưng điện thoại cũ có thể tốn thời gian giải nén phản hồi rất lớn. Chiến thắng tốt nhất vẫn là gửi ít dữ liệu ngay từ đầu.
Đối xử với cấu trúc phản hồi như một hợp đồng. Khi tên trường và kiểu ổn định, app cần ít fallback và ít code phòng thủ hơn, giúp UI mượt và tiết kiệm pin.
Thiết kế cho mạng kém và ít retry hơn
App di động không chỉ hao pin khi gửi yêu cầu. Nó còn hao pin khi thất bại, retry, thức dậy radio lần nữa và lặp lại công việc. Nếu API giả định Wi‑Fi hoàn hảo, người dùng thật trên 4G chập chờn sẽ trả giá.
Làm cho việc yêu cầu ít dữ liệu hơn trở nên dễ dàng. Ưu tiên lọc phía server và phân trang thay vì “tải mọi thứ rồi lọc trên điện thoại”. Nếu màn hình cần 20 sự kiện gần nhất cho một user, hỗ trợ truy vấn đó để app không fetch hàng trăm dòng chỉ để vứt bỏ phần lớn.
Hỗ trợ delta sync để app có thể hỏi “cái gì thay đổi kể từ lần cuối tôi kiểm tra?” Điều này đơn giản như trả về timestamp hoặc số phiên bản tăng dần, rồi cho phép client yêu cầu chỉ cập nhật và xóa kể từ điểm đó.
Retry là không tránh khỏi, nên làm cho các cập nhật idempotent. Một retry không nên tính phí hai lần, gửi hai lần, hay tạo trùng. Khóa idempotency cho thao tác tạo và semantics cập nhật đặt trạng thái (thay vì “tăng thêm 1”) rất hữu ích.
Khi retry xảy ra, tránh retry storm. Dùng exponential backoff với jitter để hàng ngàn thiết bị không đổ tới server cùng lúc, và để điện thoại không thức dậy mỗi giây.
Trả mã lỗi rõ ràng để app biết hành động. 401 nên kích hoạt re-auth, 404 thường dừng retry, 409 có thể cần refresh state, và 429 hoặc 503 nên kích hoạt backoff.
Hành vi client khiến chi phí API phình to
Ngay cả với API thiết kế tốt, client vẫn có thể nhân lên công việc mạng. Trên di động, các wakeup và thời gian radio thường tiêu tốn pin nhiều hơn các byte.
Cache dữ liệu hiếm khi thay đổi. Ảnh profile, feature flag và dữ liệu tham chiếu (quốc gia, trạng thái, danh mục) không nên fetch mỗi lần vào màn hình. Cho chúng vòng đời hợp lý, lưu trên đĩa và chỉ làm mới khi cần. Nếu API hỗ trợ xác thực (ETag hoặc Last-Modified), một recheck nhanh thường rẻ hơn nhiều so với tải lại.
Vấn đề phổ biến khác là duplicate in-flight requests. Hai phần của app cùng hỏi một tài nguyên tại cùng thời điểm (ví dụ header và màn hình cài đặt đều yêu cầu profile). Nếu không gộp, bạn gửi hai cuộc gọi, parse hai phản hồi và cập nhật state hai lần. Xử lý một cuộc gọi mạng như nguồn chân thực duy nhất và cho nhiều consumer chờ trên nó.
Làm mới nền cần có chủ đích. Nếu nó không thay đổi những gì người dùng thấy sớm, hoặc không kích hoạt thông báo, thường nên chờ. Tránh chạy logic làm mới mỗi khi app resume. Thêm cooldown ngắn và kiểm tra lần cập nhật cuối.
Nếu bạn xây backend với AppMaster, sẽ dễ hỗ trợ các hành vi client này bằng cách tạo các endpoint theo màn hình, giữ schema phản hồi nhất quán và thêm header cache có kiểm soát để client có thể im lặng phần lớn thời gian.
Sai lầm phổ biến với batching, caching và payload
Mục tiêu là ít wakeup radio hơn, ít công việc CPU hơn, và ít retry hơn. Một vài mẫu sai có thể huỷ bỏ lợi ích và thậm chí làm màn hình cảm thấy chậm hơn.
Khi batching làm mọi thứ tệ hơn
Batch hữu ích cho đến khi nó biến thành “gửi cho tôi mọi thứ”. Nếu server phải join nhiều bảng, chạy nhiều kiểm tra quyền, và xây một phản hồi khổng lồ, thì request đơn đó có thể chậm hơn vài request nhỏ. Trên di động, một request chậm giữ app chờ, giữ mạng hoạt động và tăng rủi ro timeout.
Một batch lành mạnh nên có hình dạng màn hình: chỉ những gì một view cần, với giới hạn rõ ràng. Nếu bạn không thể mô tả phản hồi trong một câu, endpoint có lẽ quá rộng.
Caching gây ra màn hình lỗi thời
Caching mà không có invalidation rõ ràng dẫn đến vòng lặp xấu: người dùng thấy dữ liệu cũ, họ pull-to-refresh, và app lại tải lại toàn bộ. Dùng header cache kèm kế hoạch những gì cập nhật dữ liệu (thao tác tạo/cập nhật, sự kiện server, hoặc cửa sổ tươi ngắn) để client có thể tin tưởng các phản hồi cache.
Polling là bẫy pin khác. Timer 5 giây chặt giữ thiết bị bận ngay cả khi không có gì thay đổi. Ưu tiên cập nhật do server đẩy khi có thể, hoặc giảm dần tần suất (khoảng lâu hơn sau các poll trống, tạm dừng ở background).
Payload quá lớn là chi phí thầm lặng. Trả về các object lồng khổng lồ “cho tiện” có nghĩa là nhiều byte hơn, nhiều parse JSON hơn và churn bộ nhớ hơn. Gửi chỉ những gì màn hình cần và lấy chi tiết khi cần.
Cuối cùng, đừng bỏ qua thất bại từng phần trong batch. Nếu một sub-result lỗi và bạn retry toàn bộ batch, bạn nhân đôi traffic. Thiết kế phản hồi để client chỉ retry phần lỗi.
Checklist nhanh trong đầu: giữ batch có giới hạn, định nghĩa độ tươi cache trước, tránh polling chặt, cắt payload và hỗ trợ partial success.
Checklist ngắn trước khi phát hành
Trước khi ship, làm một lượt chỉ tập trung vào hành vi mạng. Phần lớn lợi ích về pin đến từ loại bỏ bất ngờ: ít wakeup hơn, ít parse hơn, và ít retry nền hơn.
Chạy điều này trên ba màn hình hàng đầu của bạn:
- Tải lạnh hoàn thành trong số yêu cầu nhỏ, dự đoán được (theo dõi các gọi ẩn như lookup per-item).
- Phản hồi bao gồm quy tắc cache rõ ràng (
ETaghoặcLast-Modifiedkhi phù hợp) và trả304 Not Modifiedkhi không có gì thay đổi. - Endpoint danh sách có giới hạn: sắp xếp ổn định, phân trang và không có trường thừa theo mặc định.
- Logic retry dùng backoff với jitter và dừng ở các lỗi không tự khắc phục; tổng thời gian retry được giới hạn.
- Cập nhật nền có lý do; tránh polling liên tục trừ khi nó thực sự thay đổi thứ người dùng thấy.
Kiểm tra thực tế đơn giản: tải một màn hình, bật chế độ máy bay, rồi mở lại. Nếu nó vẫn hiển thị thứ hữu ích (nội dung cache, trạng thái biết lần cuối, placeholder thân thiện), bạn có lẽ đã giảm các cuộc gọi không cần thiết và cải thiện tốc độ cảm nhận.
Ví dụ: làm cho màn hình theo dõi đơn hàng nhẹ hơn
Một khách hàng mở app theo dõi đơn trên dữ liệu di động với 20% pin còn lại. Họ chỉ cần biết: “Gói hàng của tôi đang ở đâu ngay bây giờ?” Màn hình trông đơn giản, nhưng traffic API phía sau có thể tốn kém đáng ngạc nhiên.
Trước đây, app tải màn hình với một loạt yêu cầu. UI chờ trong khi radio thức dậy nhiều lần, và vài cuộc gọi timeout trên kết nối yếu.
Mẫu “trước” điển hình:
GET /orders/{id}cho tóm tắt đơn hàngGET /orders/{id}/itemscho các dòng hàngGET /orders/{id}/historycho sự kiện trạng tháiGET /mecho profile và preferences người dùngGET /settingscho quy tắc hiển thị (tiền tệ, định dạng ngày)
Bây giờ áp dụng ba thay đổi không làm khác UI.
Thứ nhất, thêm một endpoint màn hình duy nhất trả đúng những gì view cần trong một lần đi: tóm tắt đơn, trạng thái mới nhất, lịch sử gần nhất và tiêu đề các item. Thứ hai, cache profile: GET /me trả ETag và Cache-Control: private, max-age=86400, nên hầu hết lần mở trở thành 304 nhanh (hoặc không cần request nếu bản cache vẫn còn tươi). Thứ ba, thu nhỏ payload: danh sách items gửi id, name, qty, và thumbnail_url thôi, không gửi mô tả sản phẩm đầy đủ hay metadata không dùng.
Kết quả là ít vòng đi lại hơn, ít byte hơn, và ít retry hơn khi mạng chập chờn. Radio của điện thoại ngủ nhiều hơn, và đó là nơi tiết kiệm pin thực sự xảy ra.
Với người dùng, không có gì “mới” xuất hiện. Màn hình giống trước, nhưng tải nhanh hơn, cảm thấy phản hồi hơn và vẫn hoạt động khi kết nối kém.
Bước tiếp theo: kế hoạch triển khai thực tế (và chỗ AppMaster hỗ trợ)
Nếu muốn thắng nhanh, bắt đầu nhỏ và chứng minh tác động. Tiết kiệm pin thường đến từ ít wakeup radio hơn và ít parse hơn, không phải từ một bản rewrite lớn.
Ba thay đổi an toàn, dễ đo và dễ quay lui:
- Đo end-to-end một màn hình (số yêu cầu, tổng byte, thời gian tới tương tác, tỉ lệ lỗi và retry)
- Gộp các yêu cầu của màn hình đó thành một hoặc hai cuộc gọi (giữ các endpoint cũ để tương thích)
- Thêm support
ETagtrên các GET có lưu lượng cao để client dùngIf-None-Matchvà nhận304 Not Modified
Chọn tính năng có usage ổn định, như danh sách đơn hàng hoặc inbox. Triển khai sau flag server-side nếu có thể, rồi so sánh KPI đường cũ và đường mới trong vài ngày. Tìm ít yêu cầu hơn mỗi phiên, ít retry hơn, và ít byte tải xuống hơn mỗi người dùng hoạt động.
Phối hợp phát hành API và app để client cũ không bị hỏng. Nguyên tắc thực tế: thêm hành vi mới trước, chuyển client sau, xóa hành vi cũ cuối cùng. Nếu thay đổi hành vi caching, cẩn thận với dữ liệu cá nhân hoá và đảm bảo cache chia sẻ không trộn người dùng.
Nếu muốn prototype và phát hành backend nhanh hơn, AppMaster (appmaster.io) có thể giúp bạn mô hình dữ liệu trực quan, xây logic nghiệp vụ bằng trình kéo-thả, và tái tạo mã nguồn sẵn sàng production khi yêu cầu thay đổi.
Thử một endpoint batch cộng ETag trên một màn hình lưu lượng cao trước. Nếu số liệu cải thiện, bạn sẽ biết chính xác nơi đầu tư thêm thời gian kỹ sư.
Câu hỏi thường gặp
Một mốc tốt là đặt ngân sách cho từng màn hình rồi đo trên các phiên thực tế. Nhiều nhóm bắt đầu với khoảng 4–8 yêu cầu cho một lần tải lạnh trên mạng di động, rồi siết chặt dần sau khi sửa các tác nhân gây tệ nhất. Con số đúng là con số giúp bạn đạt mục tiêu thời gian tới tương tác mà không gây retry hay làm radio hoạt động lâu.
Batch thường hữu ích khi nhiều cuộc gọi luôn xảy ra cùng nhau, nhưng nó có thể phản tác dụng nếu batch trở nên chậm hoặc quá lớn. Giữ phản hồi của batch “theo hình dạng màn hình” và có giới hạn để một request không trở thành điểm thất bại duy nhất. Nếu endpoint batch thường xuyên timeout hoặc trả về nhiều dữ liệu không dùng, hãy tách lại thành vài gọi tập trung.
Bắt đầu với ETag và các yêu cầu điều kiện dùng If-None-Match, vì nó có thể biến nhiều lần làm mới thành các phản hồi 304 Not Modified rất nhỏ. Thêm Cache-Control phù hợp với tần suất thực tế dữ liệu thay đổi để client tránh làm việc mạng không cần thiết. Nếu ETag khó triển khai, Last-Modified với If-Modified-Since là giải pháp thay thế ổn định cho các tài nguyên kiểu “cập nhật tại”.
Dùng ETag khi bạn cần kiểm tra “phiên bản” tài nguyên chính xác, đặc biệt khi nội dung thay đổi không khớp gọn với một dấu thời gian. Dùng Last-Modified khi server có thời điểm cập nhật rõ ràng và bạn chấp nhận độ chính xác theo timestamp. Nếu chỉ có thể triển khai một cái, ETag thường chính xác hơn để tránh tải lại vô ích.
Theo dõi theo màn hình và phiên, không chỉ theo endpoint. Ghi nhận số yêu cầu, byte (headers cộng body), retry, timeout và thời gian tới tương tác; tách biệt traffic foreground và background để bạn không tối ưu sai thứ. Thường thì vài màn hình hoặc luồng chính tạo ra phần lớn các wakeup lặp lại.
Thiết kế phản hồi batch sao cho mỗi kết quả con có thể thành công hoặc thất bại độc lập, và bao gồm đủ chi tiết lỗi để client chỉ retry phần bị lỗi. Tránh bắt client phải yêu cầu lại toàn bộ batch vì chỉ một phần bị hỏng. Điều này giảm traffic trùng lặp và tránh các wakeup radio thừa khi kết nối không ổn định.
Cắt gọn phản hồi chỉ còn những gì màn hình hiển thị ngay lập tức, và dùng dạng tóm tắt cho danh sách. Di chuyển các trường nặng hoặc ít dùng sang endpoint chi tiết load khi người dùng mở item. Cách này giảm byte truyền, giảm parse JSON và cập nhật model — đều là chi phí CPU và pin có ý nghĩa trên điện thoại.
Dùng exponential backoff kèm jitter và giới hạn tổng thời gian retry để điện thoại không liên tục thức dậy mỗi vài giây. Làm cho các thao tác ghi có tính idempotent để retry không tạo bản sao hay hành động kép. Đồng thời trả mã lỗi rõ ràng để client dừng retry khi lỗi không tự khắc phục được.
Các interval polling ngắn giữ radio và CPU hoạt động ngay cả khi không có gì thay đổi. Nếu phải poll, tăng khoảng cách khi phản hồi không thay đổi và tạm dừng polling ở background. Khi có thể, chuyển sang cập nhật theo sự kiện để app chỉ thức dậy khi có dữ liệu mới.
Trong AppMaster, bạn có thể tạo các endpoint hướng màn hình và giữ schema phản hồi nhất quán, giúp batching và định hình payload dễ quản lý hơn. Bạn cũng có thể thêm logic versioning và trả header hỗ trợ các yêu cầu điều kiện để client nhận các phản hồi “không thay đổi” nhanh. Cách thực tế: bắt đầu với một màn hình lưu lượng cao, phát hành một endpoint batch và thêm ETag cho các GET chính, rồi đo giảm request và retry.


