Возьмём справочник категорий интернет-магазина.
Он меняется от силы раз в месяц, но запрашивается при каждом открытии каталога сотнями тысяч пользователей:
GET /api/v1/categories
Если не описать кэширование, Backend будет снова и снова возвращать один и тот же JSON.
❗️ Даже когда категории не изменились.
На масштабе это превращается в тысячи лишних запросов, повторные обращения к БД и передачу одинаковых данных по сети.
Это незаметная деградация производительности и кража ресурсов от более важных API-запросов.
👉 Как оптимизировать такой метод через требования, а не через «давайте добавим серверов»?
✅ Заголовки (headers): Cache-Control, ETag, If-None-Match
1️⃣ Backend возвращает данные и правила кэширования
В ответ на запрос списка категорий приходит:
HTTP 200 OK
Content-Type: application/json
Cache-Control: public, max-age=3600
ETag: "categories-v42"
{
"categories": [...]
}
Что здесь происходит:
▫️
max-age=3600 — ответ считается актуальным в течение 3600 секунд (1 час)▫️
public — ответ разрешено хранить не только клиенту, но и промежуточным кэшам▫️
ETag — идентификатор текущей версии представления справочникаКэш сохранён на сервере. Например в Redis.
👉 Клиент должен сохранить список категорий локально — в своём кэше.
2️⃣ Пока кэш свежий, новый запрос на Backend не нужен
В течение часа клиент использует ранее сохранённый ответ.
Backend, API Gateway и БД в обработке такого обращения не участвуют.
Именно
Cache-Control позволяет не отправлять повторный запрос вообще.3️⃣ После истечения `max-age` клиент проверяет актуальность данных
GET /api/v1/categories
If-None-Match: "categories-v42"
Клиент передаёт ранее полученный ETag в заголовке
If-None-Match.4️⃣ Если справочник не изменился, Backend возвращает:
HTTP 304 Not Modified
Cache-Control: public, max-age=3600
ETag: "categories-v42"
Тело ответа не передаётся.
Клиент продолжает использовать сохранённый JSON, а срок его свежести обновляется.
5️⃣ Если справочник изменился, Backend возвращает новый ответ:
HTTP 200 OK
Content-Type: application/json
Cache-Control: public, max-age=3600
ETag: "categories-v43"
{
"categories": [...]
}
Клиент сохраняет новые данные и новый ETag в локальном кэше.
📌 Что системному аналитику описать в требованиях:
▫️ допускается ли кэширование ответа
▫️ срок актуальности кэша —
max-age▫️ где разрешено хранить ответ —
public или private▫️ как формируется и обновляется ETag
▫️ поддержку заголовка
If-None-Match▫️ ответы
200 OK и 304 Not Modified▫️ сохранение клиентом тела ответа и ETag
▫️ правила инвалидации кэша при изменении данных
⚠️ Важно
Необязательно каждый раз собирать полный JSON и рассчитывать от него хэш.
Иначе Backend может сначала выполнить тяжёлый запрос к БД, сформировать весь ответ и только потом понять, что данные не изменились.
Для справочников эффективнее хранить отдельную версию данных и обновлять её при изменениях.
📌 Правило
Часто вызываемый GET-метод с редко изменяемым и пригодным для кэширования ответом — кандидат на связку:
Cache-Control + ETag + If-None-Match
✅ Cache-Control сокращает количество запросов к Backend.
✅ ETag сокращает повторную передачу неизменившихся данных после истечения срока свежести.
И это уже не одна «волшебная строчка», а полноценная политика кэширования, которую аналитик должен спроектировать в требованиях к API.
#RestApiGA
