Сценарій: оптимізуємо не фреймворк, а повторення
У команди є серверно відтворені сторінки: каталог, документація, маркетингові сторінки, публічні профілі або статті. Частина відповідей однакова для тисяч користувачів, але застосунок усе одно запускає код на кожен запит: читає дані, збирає HTML, виконує шаблони, віддає відповідь. Затримка росте, CPU витрачається, а команда починає думати про повну статичну збірку.
Інколи кращий перший крок простіший: поставити кеш перед кодом. Якщо готова публічна відповідь уже є і безпечна для повторного використання, її можна віддати з кешу. Якщо її немає, запит доходить до початкового сервера, код виконується один раз, а результат зберігається для наступних запитів.
Свіжий приклад такої моделі — Workers Cache від Cloudflare, де кеш може стояти перед Worker, який сам є початковим сервером для застосунку із серверним відтворенням. Але головний урок не в конкретному продукті. Урок у підході: кеш має стояти перед дорогим виконанням коду, а не тільки перед статичними файлами.
Крок 1. Інвентаризація маршрутів перед будь-якими заголовками
Не починайте з Cache-Control. Почніть із таблиці маршрутів. Для кожного маршруту запишіть, хто бачить відповідь, від чого вона залежить і як швидко має оновлюватися.
Практичний поділ:
- публічна: сторінка однакова для всіх, наприклад документація або публічна стаття;
- умовно публічна: відповідь залежить від мови, країни, валюти або типу пристрою;
- приватна: відповідь залежить від користувача, авторизації, файлів cookie, ролі або сесії.
Приватні відповіді не повинні потрапляти в спільний кеш. Якщо сторінка містить ім’я користувача, особисті замовлення, стан підписки або інші персональні дані, ставте Cache-Control: no-store і перевіряйте, що платформа не може закешувати таку відповідь через загальні правила.
Крок 2. Заголовки: Cache-Control і Vary як контракт
Для публічного маршруту заголовок може бути коротким і зрозумілим, наприклад Cache-Control: public, max-age=60, stale-while-revalidate=300. Це означає: відповідь можна зберігати, вона свіжа протягом 60 секунд, а після цього кеш ще може швидко віддати стару версію під час фонового оновлення.
Але Cache-Control — лише половина контракту. Друга половина — Vary. Якщо сторінка має різні мовні версії, кеш повинен знати, що Accept-Language впливає на відповідь. Якщо відповідь стиснена по-різному, часто враховується Accept-Encoding. Якщо ви раптом хочете варіювати відповідь за Cookie, це сигнал зупинитися: можливо, маршрут насправді приватний і не має бути у спільному кеші.
Окремо перевірте Set-Cookie. Відповідь, яка встановлює файл cookie, часто не повинна кешуватися як публічна. Типова помилка — публічна сторінка додає аналітичний або сесійний cookie, після чого команда намагається кешувати її без перегляду заголовків.
Крок 3. stale-while-revalidate: швидкість із межами
stale-while-revalidate корисний для сторінок, де невелика затримка оновлення прийнятна. Наприклад, документація, блог, довідкові сторінки або каталог без критичних залишків можуть витримати кілька хвилин несвіжості. Користувач отримує швидку відповідь, а кеш оновлюється у фоні.
Це поганий вибір для даних, де застаріла відповідь шкодить: ціна під час оплати, статус доступу, баланс, персональні повідомлення, правові обмеження. Для таких маршрутів або не використовуйте кеш, або робіть дуже вузькі правила з явним очищенням кешу після зміни даних.
Домовтеся про допустимий час несвіжості: скільки секунд або хвилин сторінка може бути застарілою без інциденту. Якщо команда не може відповісти, значення stale-while-revalidate поки не готове.
Крок 4. Очищення кешу: не кнопка паніки, а мапа контенту
Кеш без стратегії очищення швидко стає джерелом страху. Потрібна мапа: яка зміна контенту очищує які відповіді.
Приклади:
- публікація статті очищує її шлях і список статей;
- зміна товару очищує сторінку товару, категорію і пошукові фрагменти;
- оновлення навігації очищує всі сторінки з цим меню або відповідний Cache-Tag;
- зміна перекладу очищує тільки мовну версію, а не весь сайт.
Cloudflare у своєму матеріалі згадує Cache-Tag і програмне очищення кешу як частину моделі Workers Cache. У будь-якій платформі думайте так само: очищення за тегом або префіксом має бути достатньо точним. Антипатерн — очищувати весь кеш після кожної маленької зміни. Це повертає навантаження на початковий сервер і маскує проблеми в мапі залежностей.
Крок 5. Короткі перевірки у тестовому середовищі
Перед впровадженням у робочому середовищі зробіть короткий набір перевірок.
- Відкрийте публічний маршрут двічі. Перший запит має показати промах кешу, другий — влучання кешу.
- Перевірте журнали або метрику CPU: під час влучання кешу код застосунку не має виконувати повну генерацію відповіді.
- Повторіть тест для різних мов або інших значень Vary. Версії не повинні змішуватися.
- Перевірте заголовки відповіді: немає
Set-Cookie, немає приватних даних, немає залежності від Authorization. - Оновіть контент, виконайте очищення кешу за шляхом або тегом, переконайтеся, що наступний запит бачить нову версію.
- Тимчасово вимкніть кеш або правило маршруту й перевірте, що запити коректно йдуть до початкового сервера.
Антипатерни, які варто зловити до релізу
Перший антипатерн — кешувати все, що повільне. Повільність не робить відповідь безпечною для повторного використання.
Другий — ігнорувати Vary. Якщо сторінка залежить від мови, але кеш цього не знає, користувачі отримають чужу мовну версію.
Третій — використовувати довгий max-age без очищення кешу. Це створює швидкий сайт, якому ніхто не довіряє.
Четвертий — тестувати тільки швидкість. Для серверно відтворених відповідей обов’язково тестуйте приватність, свіжість і те, чи справді влучання кешу не запускає дорогий код.
Обережне впровадження
Почніть з одного публічного маршруту з низьким ризиком: документація, довідкова сторінка або стаття. Додайте заголовки, Vary, очищення кешу та короткі перевірки. Потім розширюйте покриття на групи маршрутів з однаковими правилами.
Мета не в тому, щоб перетворити весь застосунок на статичний сайт. Мета — прибрати зайве повторення там, де відповідь уже готова, публічна і контрольовано оновлюється.
Джерела
- Cloudflare Blog: Workers Cache — https://blog.cloudflare.com/workers-cache/
- RFC 9111: HTTP Caching — https://www.rfc-editor.org/rfc/rfc9111.html
- MDN Web Docs: Cache-Control — https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control
- MDN Web Docs: Vary — https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Vary
Короткий чеклист
- складіть список маршрутів і позначте публічні, приватні та умовно публічні відповіді
- забороніть кешування для відповідей з авторизацією, персональними даними або Set-Cookie
- задайте Cache-Control і Vary для кожного маршруту, який можна кешувати
- визначте, де доречний stale-while-revalidate і яка допустима несвіжість
- підготуйте очищення кешу за шляхом, префіксом або тегом для подій оновлення контенту
- перевірте у тестовому середовищі влучання, промах, свіжість і відсутність приватних даних
Скласти безпечний план кешування серверних маршрутів
Ти допомагаєш підготувати обережне впровадження кешу перед серверно відтвореним застосунком. Постав уточнювальні питання, якщо бракує даних. Попроси такі вхідні дані: - список маршрутів і приклади відповідей; - які маршрути залежать від авторизації, файлів cookie, мови, країни або пристрою; - допустиму затримку оновлення контенту для кожного типу сторінки; - як контент оновлюється у CMS, базі даних або адмінці; - які сигнали влучання та промаху кешу доступні у платформі; - як команда може очищувати кеш за шляхом, префіксом або тегом; - обмеження тестового й робочого середовищ. Поверни результат у такому форматі: 1. Матриця маршрутів: маршрут, публічність, можливість кешування, причина, ризик. 2. Рекомендовані заголовки: Cache-Control, Vary та правила Set-Cookie. 3. План stale-while-revalidate: значення, коли доречно, коли заборонено. 4. Мапа очищення кешу: подія зміни контенту, шлях або тег, очікуваний ефект. 5. Короткі перевірки: команди або кроки для влучання, промаху, свіжості та приватності. 6. План відкату: як вимкнути кеш і перевірити повернення до початкового сервера. Не пропонуй кешувати відповіді з персональними даними, авторизацією або Set-Cookie без окремого обґрунтування.