Кеширование
SWR: сгладить пилу ревалидации
Читать про пилу p99 — не то же, что заставить её исчезнуть с реального графика задержек. Подними кэш перед медленным origin, загони его в пик на каждой границе TTL, затем примени stale-while-revalidate, stale-if-error и single-flight, пока хвост не станет плоским — с доказательствами на каждом шаге.
Преврати ментальную модель юнита в воспроизводимый цикл: измерь пик синхронной ревалидации, раздели свежесть и задержку окном SWR, защитись от аварии origin через stale-if-error, скоалесцируй фоновое обновление и подтверди плоский хвост числами до/после.
Поставь кэш (CDN edge, обратный прокси вроде Varnish/nginx/Fastly или маленький in-process кэш, который напишешь сам) перед намеренно медленным origin, воспроизведи пилу p99 на каждой границе TTL, затем сгладь её через stale-while-revalidate и stale-if-error плюс single-flight — доказывая каждое изменение измерениями под одинаковой нагрузкой.
- Сравнение до/после под одинаковой нагрузкой: p99 во времени для только-max-age против max-age+SWR, с видимо исчезнувшей пилой на графике «после» — измеренное, не оценённое.
- Панель rps к origin, показывающая фоновые обновления, скоалесцированные примерно до одного на ключ за истечение после single-flight, против стада до него.
- Демонстрация, что во время форсированного 5xx origin кэш отдаёт stale (stale-if-error) и что за пределами настроенного окна он перестаёт отдавать stale и выносит сбой наружу — доказывая, что устаревание ограничено.
- Абзац-вывод: максимальное устаревание, допускаемое твоей итоговой политикой, почему эта граница приемлема для этих данных, и тот единственный эндпоинт, который ты намеренно исключил из SWR, и почему.
- Воспроизведи тот же паттерн на клиенте библиотекой SWR (или React Query): отрендери компонент stale-first, покажи, как dedupingInterval коалесцирует два параллельных вызова в один запрос, и как revalidateOnFocus обновляет устаревшую вкладку.
- Добавь on-call runbook: как читать пилу на дашборде, три окна заголовка и что каждое защищает, ручки single-flight и джиттера, и чек-лист ограниченного устаревания.
- Добавь линт политики свежести в CI, который валит билд, если любой эндпоинт auth, прав или feature-флага отгружает директиву stale-while-revalidate или stale-if-error.
- Измерь распределение устаревания: проинструментируй, насколько старыми реально оказываются отданные ответы под устойчивой нагрузкой, и подтверди, что оно остаётся внутри настроенного окна — превратив «ограниченное устаревание» из утверждения в измеренный факт.
Это цикл, который ты прогонишь на каждом реальном инциденте свежести: сначала измерь пилу синхронной ревалидации, раздели свежесть и задержку через stale-while-revalidate, чтобы ни один человек не ждал обновления, скоалесцируй фоновое обновление single-flight плюс джиттером, чтобы горячий ключ не мог заштурмовать origin, защити аварию ограниченным полом stale-if-error и полностью вырежи auth из политики. Сделав это однажды против игрушечного origin, ты превращаешь production-версию — сглаживание реального графика p99 без поломки корректности — в мышечную память.