Stale-If-Error
Chỉ thị Cache-Control cho phép sử dụng phiên bản cũ nếu yêu cầu mới gặp lỗi mạng hoặc máy chủ không phản hồi.
Stale-If-Error là gì?
Stale-If-Error là một chỉ thị mở rộng của tiêu đề Cache-Control trong giao thức HTTP. Nó cho phép trình duyệt hoặc proxy (như CDN) tiếp tục phục vụ phiên bản cũ (stale) của tài nguyên — dù đã hết hạn cache — khi yêu cầu làm mới gặp lỗi mạng, timeout, hoặc máy chủ trả về phản hồi lỗi (ví dụ: 500, 502, 503, 504). Đây không phải tiêu chuẩn bắt buộc trong RFC 7234, mà là một đề xuất được đưa ra trong RFC 5861, và hiện được hỗ trợ rộng rãi bởi các trình duyệt hiện đại (Chrome, Firefox, Edge từ phiên bản 76+, Safari từ iOS 15.4 / macOS Monterey trở lên) và hầu hết CDN phổ biến (Cloudflare, Fastly, Cloud CDN).
Tại sao quan trọng trong SEO?
Khi trang web gặp sự cố kỹ thuật tạm thời, Googlebot và các bot tìm kiếm khác vẫn cần truy cập để duy trì khả năng lập chỉ mục và đánh giá trải nghiệm người dùng. Nếu không có stale-if-error, một lỗi 503 hoặc timeout có thể khiến bot nhận được lỗi thay vì nội dung — dẫn đến:
- Giảm tần suất thu thập (crawl rate) do bot tạm ngừng truy cập;
- Mất chỉ mục tạm thời nếu lỗi kéo dài;
- Ảnh hưởng đến điểm Core Web Vitals (đặc biệt là Largest Contentful Paint – LCP) do tải chậm hoặc thất bại;
- Tỷ lệ thoát tăng ở người dùng thật khi trang không mở được.
Ngược lại, với stale-if-error=3600, bot và người dùng vẫn thấy phiên bản cũ còn cache trong vòng 1 giờ — đủ để hệ thống phục hồi mà không làm gián đoạn trải nghiệm. Đây là yếu tố gián tiếp nhưng rõ ràng giúp giữ ổn định thứ hạng và độ tin cậy của trang.
Cách hoạt động
Chỉ thị stale-if-error chỉ kích hoạt khi đồng thời thỏa mãn ba điều kiện:
- Tài nguyên đã hết hạn (tức là
max-agehoặcexpiresđã qua); - Trình duyệt/CDN đang cố gắng làm mới tài nguyên (revalidation request);
- Yêu cầu làm mới thất bại do lỗi mạng (ERR_CONNECTION_TIMED_OUT), lỗi DNS, hoặc máy chủ trả về trạng thái HTTP lỗi thuộc nhóm 5xx (500–599) hoặc 408 (Request Timeout).
Khi đó, trình duyệt hoặc proxy sẽ bỏ qua lỗi và phục vụ phiên bản cũ — miễn là thời gian “lỗi được chấp nhận” chưa vượt quá giá trị đã khai báo (ví dụ: stale-if-error=86400 = 24 giờ kể từ lúc hết hạn).
Hướng dẫn thực hiện
Để áp dụng stale-if-error, bạn cần cấu hình tiêu đề HTTP Cache-Control tại tầng web server hoặc CDN. Dưới đây là các bước cụ thể:
- Xác định tài nguyên phù hợp: Ưu tiên áp dụng cho nội dung tĩnh ít thay đổi (CSS, JS, ảnh, font) và trang HTML có tính ổn định cao (trang danh mục, bài blog cũ, trang giới thiệu). Tránh dùng cho trang thanh toán, dashboard cá nhân hoặc nội dung thời sự.
- Chọn giá trị thời gian hợp lý: Giá trị thường nằm trong khoảng 300–86400 giây (5 phút – 24 giờ). Với trang HTML, khuyến nghị 3600–7200 giây (1–2 giờ); với tài nguyên tĩnh, có thể lên đến 86400 giây.
- Cấu hình trên các nền tảng phổ biến:
| Nền tảng | Cách cấu hình |
|---|---|
| Apache (.htaccess) | Header set Cache-Control "public, max-age=3600, stale-if-error=7200" |
| Nginx | add_header Cache-Control "public, max-age=3600, stale-if-error=7200"; |
| Cloudflare Workers | response.headers.set('Cache-Control', 'public, max-age=3600, stale-if-error=7200'); |
| Vercel / Next.js | Dùng headers trong next.config.js hoặc getStaticProps với revalidate + custom header. |
Lưu ý: Chỉ thị này không thay thế max-age hay stale-while-revalidate. Nó chỉ bổ sung hành vi xử lý lỗi — nên kết hợp với cả hai để tối ưu hiệu quả.
Lỗi thường gặp
Không thấy hiệu lực dù đã cấu hình
Nguyên nhân thường do: (1) Trình duyệt chưa hỗ trợ (kiểm tra qua caniuse.com); (2) CDN chặn hoặc ghi đè tiêu đề; (3) Có nhiều Cache-Control mâu thuẫn trong chuỗi phản hồi. Cách khắc phục: kiểm tra tiêu đề thực tế bằng DevTools → Network → Response Headers; đảm bảo chỉ có một giá trị Cache-Control hợp lệ.
Hiển thị nội dung lỗi thay vì phiên bản cũ
Có thể do giá trị stale-if-error quá nhỏ so với thời gian hết hạn, hoặc tài nguyên chưa từng được cache trước đó (vì chỉ áp dụng khi đã có bản stale tồn tại). Kiểm tra bằng cách xem Age và Expires trong response — nếu Age > max-age, bản stale mới tồn tại.
Sử dụng sai cho nội dung động
Ví dụ áp dụng stale-if-error cho trang giỏ hàng hiển thị số lượng sản phẩm — có thể khiến người dùng thấy thông tin lỗi thời. Khắc phục: phân tách cache theo loại nội dung; dùng no-cache hoặc private cho dữ liệu nhạy cảm.
Ví dụ thực tế
Một trang blog có URL https://example.com/bai-viet-ve-web-performance được cấu hình như sau:
Cache-Control: public, max-age=1800, stale-while-revalidate=300, stale-if-error=3600
→ Nội dung được cache 30 phút (max-age=1800).
→ Trong 5 phút sau hết hạn, trình duyệt có thể vừa hiển thị bản cũ vừa làm mới nền (stale-while-revalidate=300).
→ Nếu trong 1 giờ sau hết hạn, việc làm mới thất bại do máy chủ sập, trình duyệt vẫn phục vụ bản cũ (stale-if-error=3600).
Kết quả: Người dùng không thấy màn hình lỗi trắng, Googlebot vẫn thu thập được nội dung, và tỷ lệ tương tác không giảm đột ngột trong sự cố kỹ thuật ngắn hạn.
Câu hỏi thường gặp
Stale-If-Error có ảnh hưởng đến điểm PageSpeed Insights không?
Không trực tiếp — PageSpeed Insights không kiểm tra hành vi cache khi có lỗi. Tuy nhiên, nó gián tiếp cải thiện điểm LCP và CLS bằng cách tránh tình huống tải lại thất bại gây render trống hoặc nhảy layout. Kết quả kiểm thử thực tế cho thấy trang có stale-if-error duy trì điểm ổn định hơn trong điều kiện mạng kém hoặc server overload.
Googlebot có tuân thủ stale-if-error không?
Có. Googlebot sử dụng thư viện mạng tương tự Chromium, nên hỗ trợ đầy đủ stale-if-error từ đầu năm 2022. Tuy nhiên, Google không công bố chi tiết mức độ ưu tiên — vì vậy luôn kết hợp với max-age và last-modified để đảm bảo khả năng phục hồi tốt nhất.
Có cần kiểm tra tương thích với tất cả trình duyệt không?
Với người dùng desktop và iOS/Android hiện đại: có. Với trình duyệt cũ (IE, Android Browser trước 4.4, Safari dưới 15.4): không hỗ trợ — nhưng chúng sẽ bỏ qua chỉ thị này một cách an toàn (không gây lỗi). Vì vậy, việc triển khai là an toàn với mọi đối tượng, miễn là bạn không phụ thuộc hoàn toàn vào nó cho trải nghiệm cốt lõi.