GH GambleHub

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 або поділ публічних/приватних шляхів.

Fastly-стиль (псевдо):

Surrogate-Key: product:123 catalog
Cache-Control: public, s-maxage=300, stale-while-revalidate=600
Vary: Accept-Encoding

TTL-стратегії за типами контенту

ТипTTL CDN (`s-maxage`)Браузер ('max-age')Додатково
Версійовані асети ('/app. a1b2. js`)1 рік1 рік`immutable`; Інвалідація не потрібна
Каталоги/лендінги1-10 хв30-120 с`stale-while-revalidate=10–30 мин`
Зображення (ресайзи)10-60 хв5-15 хвVary по `Accept` (webp/avif)
API GET (кешовані)10-120 с0-30 сТільки ідемпотентні;'stale-if-error'5-60 хв
Помилки 500/timeout00Negative-cache 30-120 с (на рівні CDN), не кешувати 401/403/POST

Політики інвалідації

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 + «публічну» відповідь.

Приклад (API, 30 с + SWR):

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 залишиться живий навіть в найгарячіший час.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.