3TP Cachly
Блог
Главная / Блог / Stale‑while‑revalidate

Stale‑while‑revalidate на пальцах: когда применять, а когда — стрелять в ногу

SWR — самый недооценённый инструмент кэширования. И самый опасный, если применить его к данным, которые должны быть точными. Разберём механизм, три реальных сценария и проверочный чек‑лист.

stale-while-revalidate · сценарии

Что такое SWR в одном абзаце

Stale‑while‑revalidate — это директива HTTP‑кэша, которая разрешает edge‑узлу отдать устаревший ответ пользователю и одновременно сходить за свежим в фоне. Пользователь получает 200‑ку с прошлой версией мгновенно, фон обновляет кэш, следующий запрос придёт уже к свежему. Описание в RFC 5861, поддерживают практически все современные CDN.

Заголовок ставится со стороны origin или прописывается правилом на edge:

Cache-Control: public, max-age=300, stale-while-revalidate=600

То есть: «храни 5 минут как свежий, ещё 10 минут — можешь отдавать как устаревший, пока обновляешь».

Сценарий 1: главная страница новостного сайта — идеально

Главная новостного — это пример, где SWR работает без оговорок. Контент меняется раз в несколько минут, точная синхронизация не нужна (пользователю всё равно — он увидит новость на 30 секунд позже). Зато трафик предсказуемо большой, и каждое обновление кэша в часы пик — это удар по origin.

Реальный кейс одного нашего клиента: на главной — 9 разных блоков с рекомендациями. Каждый блок ходил к отдельному микросервису. На пиках в момент инвалидации origin получал «шторм» в 1.5 тысячи RPS на пустом кэше. С max-age=120, stale-while-revalidate=300 origin теперь получает один запрос в две минуты от каждого edge‑узла (всего 32 запроса). Остальные — горячий кэш, в том числе устаревший.

Сценарий 2: цена в карточке товара — почти стрельба в ногу

Цена меняется по нескольким триггерам: акции, изменения у поставщика, динамическое ценообразование. Если использовать SWR на саму карточку — пользователь может увидеть старую цену, добавить товар в корзину, и в чекауте удивиться. Юридически — это публичная оферта.

Правильное решение: разделить рендер. Карточка кэшируется как статика (заголовок, описание, фото), а блок цены подгружается отдельным fetch‑запросом без SWR, с очень коротким TTL — 5–10 секунд. Тогда мгновенное TTFB остаётся, а критичные данные всегда свежие.

Эмпирическое правило: всё, что попадает в чекаут, корзину или контракт — без SWR. Всё, что является публичным контентом — с SWR.

Сценарий 3: API внутреннего dashboard — спорно

Дашборды аналитики — частый случай, где SWR кажется удобным: пользователь хочет, чтобы графики прогружались мгновенно, а небольшая задержка обновления допустима. Но есть нюанс: на дашбордах пользователи часто кликают «обновить» и ждут именно свежих чисел. SWR в этой ситуации ломает ментальную модель — «я нажал, но числа те же».

Что делаем мы:

Чек‑лист перед включением SWR

  1. Ресурс — публичный? Не зависит от пользователя?
  2. Если данные устарели на 30 секунд / 1 минуту / 5 минут — пользователь это заметит и пострадает?
  3. Есть ли альтернатива в виде разделения рендера на «статичную часть» и «динамическую»?
  4. Понимает ли команда, что инвалидация не делает кэш мгновенно свежим — только запускает фоновую перевыдачу?
  5. Есть ли мониторинг «возраста» ответа в логах CDN, чтобы детектить аномальный stale?

Если на все ответили «да» — включайте. SWR один из тех инструментов, которые экономят инфраструктуру на порядок. Только не на цене товара.

ДЮ
Дмитрий Юдин
Principal Engineer · 3TP Cachly