CDN-кешування і TTL-оптимізація
Коротке резюме
CDN-кеш - це «прискорювач + щит» між користувачем і origin. Він працює добре, коли:1. Ключ кеша (cache key) стабільний і не містить «шуму».
2. TTL-політика під навантаження: `s-maxage`/`max-age` + `stale-while-revalidate/if-error`.
3. Інвалідація управляється: за тегами/префіксами + «м'які» purge.
4. Включені tiered-cache/origin-shield і negative-cache.
5. Є спостережуваність: hit-ratio по шарах, p95 TTFB, частка повернень 304.
Базові хедери і що вони означають
`Cache-Control`:- 'max-age =
'- TTL для браузера. - 's-maxage =
'- TTL для CDN/проксі (перекриває'max-age'). - 'stale-while-revalidate =
'- віддаємо застаріле, паралельно оновлюємо. - 'stale-if-error =
'- віддаємо застаріле при помилці origin. - «immutable» - ресурс не змінюється (підходить для версійованих асетів).
- 'ETag '/' Last-Modified'- умови для 304, економлять байти/CPU origin.
- 'Vary'- список заголовків, що впливають на ключ кешу (використовувати стримано!).
- 'Surrogate-Control'- «розширений» Cache-Control для CDN (якщо підтримується).
- «Expires» - застарілий, але все ще враховується клієнтами.
Cache-Control: public, max-age=31536000, immutable
Приклад (напів-динаміка з безпечним застаріванням):
Cache-Control: public, s-maxage=300, max-age=60, stale-while-revalidate=600, stale-if-error=86400
ETag: "a1c3..."
Ключ кешу: дизайн і нормалізація
Мета - щоб однакові по суті запити потрапляли в один і той же об'єкт.
Нормалізація URL: регістр, подвійні слеші, трейлінг-слеш, порядок query-параметрів.
Ігнор «шуму»: 'utm _','fbclid','gclid', довільні реф-теги.
Обмежений Vary: тільки реально значущі заголовки («Accept-Encoding», іноді «Accept», «Accept-Language» для локалі).
Device-class: якщо потрібно, використовуйте 2-3 класу (mobile/desktop/tablet), а не нескінченні user-agent гілки.
Auth-контекст: за замовчуванням не кешуйте приватне; використовуйте signed-URLs/cookies-bypass або поділ публічних/приватних шляхів.
Surrogate-Key: product:123 catalog
Cache-Control: public, s-maxage=300, stale-while-revalidate=600
Vary: Accept-Encoding
TTL-стратегії за типами контенту
Політики інвалідації
By URL/Prefix: «змести все під '/static/2025-11-05/'».
By Tag/Key: "зняти весь'catalog'і'product:123`».
Soft purge: позначити як застаріле, не прати об'єкт - швидше повторне наповнення.
Event-driven: CI/CD або адмін-подія викликає webhook «invalidate tags».
Рекомендація: об'єднуйте обидві тактики: версіонування шляхів для асетів + tag-purge для контенту/сторінок.
Tiered-cache, origin-shield и prewarm
Tiered-cache: регіональні шари CDN → менше запитів до origin.
Origin-shield: один «щитовий» POP до origin - покращує локальність і hit-ratio.
Prewarm (pre-fetch): прогрів гарячих URL/кешів перед івентом/релізом.
Negative-cache: короткочасно кешуйте 5xx/Timeout (30-120 с), щоб не завалити origin штормом ретраїв.
Кеш API: Коли можна
Тільки GET/HEAD і ідемпотентні.
Ключ: шлях + істотні query (наприклад,'? category =... & page =...').
Валідація: 'ETag '/' Last-Modified'і короткий's-maxage'.
Фільтри за користувачем: винесіть персоналізацію на клієнт/edge-функцію або використовуйте signed-requests + «публічну» відповідь.
Cache-Control: public, s-maxage=30, max-age=5, stale-while-revalidate=120, stale-if-error=600
ETag: "feed-v42"
Захист від отруєння кеша (cache poisoning)
Жорстка нормалізація URL/заголовків; білий список параметрів у ключі.
Обрізка підозрілих заголовків/дублікатів ('X-Forwarded-', розширені'Accept').
Обмеження'Vary'і контроль розміру/кол-ва заголовків.
Розділення доменів: приватне/адмін - на окремому імені без кешу.
Валідація відповідей: не кешуйте 4xx (крім 404 для статик), не кешуйте «користувацькі» сторінки без явної політики.
Стиснення та формати
Brotli для текстових (js/css/json), gzip - fallback; стислі асети допустимі.
Images: webp/avif там, де підтримка; використовуйте'Vary: Accept'+ похідні деривативи.
Range-requests для відео/аудіо: CDN кешує чанки.
Content-Negotiation: тримайте низький кардиналітет ключа (device-class замість сирих UA).
Спостережуваність і SLO
Ключові метрики
Hit-ratio (by bytes/requests) на edge/tier/shield.
p50/95/99 TTFB за регіонами і типами (статик/API).
Fill-rate/Origin egress - скільки йде до origin.
304 rate і середній розмір відповіді.
Error budget: частка'stale-if-error '/' SWR'видач; частота purge.
Приклади SLO
'p95 TTFB'статики регіонально ≤ 120-150 мс, API GET кешованих ≤ 200-250 мс.
Edge hit-ratio статики ≥ 90%, напів-динаміки ≥ 60%.
Частка відповідей з stale-гілки при помилках ≤ 0. 5% за 30 днів.
Конфіг-шпаргалки
Nginx (reverse-proxy перед CDN або в self-PoP)
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CDN:512m max_size=100g inactive=7d;
map $args $clean_args {
"~(^ &)(utm_ gclid fbclid) """; # default $ args simplified example;
}
server {
listen 443 ssl http2;
set $cache_key "$scheme$request_method$host$uri?$clean_args $http_accept $http_accept_encoding";
location /static/ {
proxy_cache CDN;
proxy_cache_key $cache_key;
proxy_ignore_headers Set-Cookie;
add_header Cache-Control "public, s-maxage=86400, max-age=3600, stale-while-revalidate=600" always;
proxy_pass https://origin_static;
}
location /api/public/ {
proxy_cache CDN;
proxy_cache_key $cache_key;
proxy_cache_valid 200 30s;
add_header Cache-Control "public, s-maxage=30, max-age=5, stale-while-revalidate=120, stale-if-error=600" always;
proxy_set_header If-None-Match $upstream_http_etag;
proxy_pass https://origin_api;
}
}
Envoy (SWR + negative-cache, концепт)
yaml http_filters:
- name: envoy. filters. http. cache typed_config:
"@type": type. googleapis. com/envoy. extensions. filters. http. cache. v3. CacheConfig typed_config:
"@type": type. googleapis. com/envoy. extensions. cache. simple_http_cache. v3. SimpleHttpCacheConfig
Cache-Control/Surrogate-Control Header Cache Policies
We cache 5xx errors briefly via route/retry policy + local_rate_limit
Хедери для «швидких» асетів
Cache-Control: public, max-age=31536000, immutable
ETag: "hash"
Content-Encoding: br
Хедери для напів-динаміки (каталоги)
Cache-Control: public, s-maxage=600, max-age=120, stale-while-revalidate=1800, stale-if-error=86400
Vary: Accept-Encoding, Accept
FinOps: як кеш економить гроші
Egress origin ↓, менше CPU/DB-навантаження → нижче інфраструктурні витрати.
Менше запитів до платних бекендів (search/index/images).
Цільова метрика: $/зниження p95 і $/зниження egress на 1 ГБ - відстежуйте післязапусковий ефект.
Специфіка для iGaming/фінтех
Каталоги провайдерів/асети: версіоновані шляхи + річний TTL.
Лендінги подій/турнірів: 1-5 хв's-maxage'+'SWR'на 10-30 хв; tag-purge при оновленні.
Лів-сторінки (коефіцієнти/таблиці): частковий кеш JSON-блоків, короткі TTL (5-30 с), для персональних блоків - клієнтський рендер.
PSP/платіжні ендпоінти: не кешуємо, суворе'no-store'; кешуйте тільки довідники (BIN-таблиці, статуси).
Антибот: кешування статик/GET, «сірі» маршрути для підозрілих ASN; не допускайте'Vary'по гучних заголовках.
Чек-лист впровадження
- Описано ключ кешу: нормалізація URL, список допускаються query,'Vary'тільки по потрібному.
- Розділені публічні/приватні шляхи; приватне -'no-store'і bypass CDN.
- Введені TTL-сходи за типами контенту; налаштований'SWR/if-error'.
- Налаштовані tiered-cache + origin-shield; включений negative-cache 5xx (короткий).
- Є tag/URL purge, soft purge; інтеграція з CI/CD.
- Включена компресія (br/gzip), веб-формати зображень і range-відповіді.
- Метрики: hit-ratio by layer, p95 TTFB, 304 rate, origin egress; алерти на провали.
- Плейбуки: прогрів кеша перед піками, екстрений purge, деградація origin.
Типові помилки
Без-версіо асети з великим TTL → «залиплі» бандли у користувачів.
Надмірний'Vary'( по'User-Agent', всім заголовкам) → вибух кардинальності і низький hit-ratio.
Кешування 4хх/401/403/приватного контенту.
Відсутність negative-cache → лавина запитів на деградний origin.
Немає tag-purge → масові точкові purge і «шторм» re-fill.
Ключ кешу включає «гучні» UTM/реф-параметри.
Занадто короткий TTL для статики → зайве навантаження на CDN і origin.
Міні-плейбуки
1) Прогрів кеша перед подією
1. Збір топ-N URL за логами → 2) Паралельний prefetch (rate-limited) по регіонах → 3) Перевірка hit-ratio ↑ і p95 ↓.
2) Екстрений soft-purge катологів
1. Відправити'PURGE '/tag-clear → 2) CDN віддає stale і фоном підтягує свіжі → 3) Перевірити відсутність шипів на origin.
3) Відмова origin
1.'stale-if-error'виручає X годин → 2) Включити банер «техроботи» на edge → 3) По відновленні - цільовий warm-up.
Підсумок
Сильна CDN-стратегія = правильний ключ кешу + осмислені TTL з SWR/if-error + керована інвалідація + tiered/shield + спостережуваність. Зафіксуйте політику в хедерах і IaC, вимірюйте hit-ratio і p95, плануйте прогрів під піки - і користувачі завжди отримають швидку відповідь, а origin залишиться живий навіть в найгарячіший час.