Кеширование на сервере: браузер, CDN, прокси и приложение
Кеш на каждом уровне может сократить задержку и разгрузить сервер, но ошибка в одном заголовке способна закрепить старую страницу у пользователей. Разбираем, что кешировать на каждом слое, как они взаимодействуют и где проверять результат.

Четыре кеша — четыре разных риска
Браузер, CDN, обратный прокси и приложение могут хранить одну и ту же страницу, но управляют этим по-разному. Если вы включите кеширование «на максимум» сразу везде, можно получить не только быстрые ответы, но и устаревшие данные, чужую персональную страницу в общем кеше или трудноуловимый баг, который исчезает при прямом запросе к серверу.
Рабочее правило: сначала определите, кто именно может повторно использовать ответ, как долго и при каких условиях его нужно считать устаревшим. Ниже — практическая схема для HTTP-сервисов; синтаксис конкретных настроек зависит от CDN и прокси. Примеры поведения относятся к HTTP caching, описанному в RFC 9111; документацию своей платформы и версию конфигурации сверяйте отдельно.
Что нужно решить до настройки
Разделите ответы хотя бы на три класса: публичная неизменяемая статика, публичные страницы с допустимой задержкой обновления и персональные или чувствительные данные. Для каждого класса ответьте на три вопроса:
- Можно ли отдать этот ответ другому посетителю?
- Сколько времени допустимо показывать его без обращения к источнику?
- Как быстро система должна заметить изменение и обновить кеш?
Ключ кеша — это набор признаков запроса, по которым кеш решает, что два запроса могут получить один ответ. Если в ответе есть персонализация, а ключ учитывает только URL, общий кеш может перепутать пользователей. Если ключ включает каждый случайный параметр, кеш дробится на множество почти одинаковых записей и перестаёт экономить запросы.
Распределите работу между уровнями
Браузер: повторные визиты одного пользователя
Браузерный кеш подходит для файлов и ответов, которые можно безопасно хранить на устройстве посетителя. Для версионированной статики — например, файла с хешем в имени — обычно выбирают длительное хранение: при изменении содержимого меняется URL. Для HTML, который должен обновляться быстрее, срок хранения делают короче или требуют проверки актуальности у сервера.
Заголовок Cache-Control задаёт правила хранения и повторного использования. Директива private запрещает общим кешам хранить ответ, но сама по себе не делает содержимое безопасным и не заменяет контроль доступа. Для данных, которые нельзя сохранять в кеше, используют no-store. Не путайте его с no-cache: последнее допускает хранение, но требует проверки перед повторным использованием.
CDN: кеш ближе к посетителю
CDN особенно полезна для публичных файлов и страниц, которые запрашивают из разных регионов. Она уменьшает путь до ответа и количество запросов к origin — серверу-источнику. Но CDN может применять собственные правила поверх заголовков origin. Проверьте, какие директивы платформа уважает, есть ли отдельный TTL и какие условия обходят кеш: cookie, query-параметры, заголовки или метод запроса.
Не включайте кеширование HTML на CDN, пока не определили ключ кеша и поведение для авторизованных запросов. Страница с одним URL может выглядеть по-разному для гостя, вошедшего пользователя и клиента из другого региона. Учитывать все cookies в ключе — не универсальное решение: оно может резко снизить долю попаданий в кеш.
Обратный прокси: защита origin и повторное использование ответов
Прокси перед приложением, например Nginx, может хранить ответы и отдавать их без повторного вызова приложения. Это полезно для публичных страниц с повторяющимися запросами. Здесь важно не только время жизни записи, но и поведение при промахе: сколько запросов одновременно пойдут за одним и тем же объектом к origin, и что увидят посетители, если origin временно недоступен.
Не копируйте конфигурацию для другого сервера вслепую. Проверяйте документацию именно вашей версии прокси и то, как она обрабатывает cookies, query-параметры, статус ответа и заголовки кеширования. Если CDN и прокси оба хранят HTML, задайте ясную политику: какой слой считается источником срока жизни и как выполняется очистка.
Приложение: кеширование результатов работы
Кеш приложения ускоряет дорогие операции: повторные вычисления, выборки из базы или сборку ответа из нескольких источников. Но здесь ключ зависит уже от логики продукта. В него могут входить идентификатор пользователя, язык, права доступа, версия данных или параметры запроса. Если пропустить значимый признак, можно отдать корректный с точки зрения кеша, но неправильный для пользователя результат.
Для такого кеша заранее определите срок жизни и способ инвалидации — удаления или обновления записи после изменения исходных данных. TTL ограничивает время устаревания, но не гарантирует немедленную свежесть. Инвалидация может обновлять данные быстрее, зато требует связать изменение записи с удалением всех зависимых результатов.
| Уровень | Что обычно кешировать | Главный риск | Что проверять |
|---|---|---|---|
| Браузер | Версионированную статику, допустимые для локального хранения ответы | Устаревший файл или сохранение чувствительных данных | Cache-Control, изменение URL при выпуске новой версии |
| CDN | Публичные файлы и проверенные публичные страницы | Выдача чужого или устаревшего варианта | Ключ, обход кеша, TTL, очистку |
| Обратный прокси | Повторяющиеся публичные ответы перед приложением | Всплеск запросов к origin при промахе | Промахи, ошибки origin, правила заголовков |
| Приложение | Дорогие вычисления и повторно используемые результаты | Неверный ключ или запоздалая инвалидация | Попадания, промахи, возраст записи, согласованность |
Как сочетать уровни, не запутавшись
Практически удобно двигаться снаружи внутрь. Сначала задайте правила браузеру и CDN для публичной статики; затем отдельно решите, можно ли кешировать HTML на CDN или прокси; в конце добавляйте кеш приложения для дорогой логики. После каждого изменения проверяйте ответ через реальную цепочку, а не только напрямую у origin.
- Разделите публичные и персональные ответы. Проверьте авторизацию, cookies и содержимое ответа. Успех: персональный ответ не попадает в общий кеш, а публичный не обходится без причины.
- Зафиксируйте ключ кеша. Перечислите параметры, влияющие на содержимое: язык, регион, тип устройства, состояние пользователя. Успех: запросы с разным содержимым не получают один вариант, а незначимые параметры не плодят копии.
- Установите допустимое время устаревания. Сопоставьте его с тем, как часто меняются данные и какой ущерб принесёт старая версия. Успех: срок можно объяснить владельцу продукта, а не только значением в конфиге.
- Проверьте обновление и очистку. Измените тестовый материал и проследите, когда новая версия появляется в браузере, CDN и прокси. Успех: известен путь обновления и его наблюдаемая задержка.
- Посмотрите на метрики под нагрузкой. Сравните долю попаданий и промахов, задержку ответа, число запросов к приложению и ошибки origin до и после. Успех: улучшилась не только средняя задержка, но и нагрузка на нижние уровни.
Заголовок Age, если его отдаёт промежуточный кеш, помогает увидеть, сколько времени объект находится в кеше. Заголовки ETag и Last-Modified могут позволить проверить актуальность без повторной передачи всего тела ответа. Наличие этих заголовков не доказывает, что каждый слой ведёт себя одинаково: смотрите на фактический ответ и логи.
Кеш безопасен не тогда, когда он хранит меньше, а когда система точно знает, кому можно отдать сохранённый ответ и когда он перестаёт быть верным.
Что ломается и когда подход не подходит
- Старая страница остаётся после публикации. Проверьте, какой слой отдал ответ, его возраст и способ очистки. Очистка CDN не удалит копию в браузере пользователя.
- Один посетитель видит данные другого. Немедленно отключите общий кеш для затронутого ответа и проверьте ключ, cookies и авторизационные правила на каждом уровне.
- Кеш почти всегда промахивается. Изучите ключ: случайные параметры, cookies или слишком дробное разделение вариантов могут создавать отдельную запись для каждого запроса.
- После истечения TTL приложение перегружено. Проверьте одновременные промахи, частоту запросов и поведение при недоступном origin. План восстановления должен учитывать всплеск, а не только обычную нагрузку.
Многоуровневый кеш не всегда оправдан. Если данные должны быть актуальны сразу после изменения, цена устаревшего ответа высока или число повторов мало, сложность очистки и диагностики может перевесить выигрыш. Начните с одного слоя, измерьте эффект и добавляйте следующий только под конкретную проблему.
Термин: инвалидация кеша — удаление или пометка устаревшими сохранённых данных после изменения источника, чтобы следующий запрос получил актуальную версию.
Что делать дальше
Выберите один публичный ответ и пройдите весь путь от приложения до браузера: запишите его ключ, заголовки, срок хранения и механизм обновления на каждом уровне. Затем проверьте три сценария — обычный повторный запрос, изменение данных и запрос с другой авторизацией. В проде наблюдайте за попаданиями, промахами, возрастом кеша, задержкой и нагрузкой на origin. Следующий шаг после настройки — не увеличить TTL, а убедиться, что очистка и обход кеша работают именно так, как ожидает продукт.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: RFC 9111: HTTP Caching, Документация NGINX: ngx_http_proxy_module
Частые вопросы
Можно ли включить кеширование для всех страниц сайта?
Чем no-cache отличается от no-store?
Если я очищу кеш CDN, пользователь сразу увидит новую страницу?
Как понять, какой именно кеш отдал ответ?
Нужно ли кешировать HTML на CDN, если статика уже кешируется?
Какой TTL выбрать для приложения и CDN?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.