Caché CDN y optimización TTL
Resumen breve
El caché CDN es un «acelerador + escudo» entre el usuario y el origin. Funciona bien cuando:1. La clave caché (cache key) es estable y no contiene «ruido».
2. Política TTL bajo carga: 's-maxage '/' max-age' + 'stale-while-revalidate/if-error'.
3. La discapacidad se controla: por etiquetas/prefijos + purge «blando».
4. Se incluyen tiered-cache/origin-shield y negative-cache.
5. Hay observabilidad: hit-ratio por capas, p95 TTFB, porcentaje de devoluciones 304.
Los headers básicos y lo que significan
`Cache-Control`:- 'max-age =
' - TTL para el navegador. - 's-maxage =
' - TTL para CDN/proxy (solapa 'max-age'). - 'stale-while-revalidate =
' - damos obsoleto, en paralelo actualizamos. - 'stale-if-error =
' - démosle el origin obsoleto en caso de error. - 'immutable' - el recurso no cambia (adecuado para assets versionados).
- 'ETag '/' Last-Modified' - condiciones para 304, ahorra bytes/CPU de origen.
- 'Vary' es una lista de títulos que afectan a la clave de caché (¡usa discretamente!).
- 'Surrogate-Control' - Cache-Control 'avanzado' para CDN (si se admite).
- 'Expires' es obsoleto, pero sigue siendo tomado en cuenta por los clientes.
Cache-Control: public, max-age=31536000, immutable
Ejemplo (semi-altavoz con obsolescencia segura):
Cache-Control: public, s-maxage=300, max-age=60, stale-while-revalidate=600, stale-if-error=86400
ETag: "a1c3..."
Clave de caché: diseño y normalización
El objetivo es que las mismas solicitudes esencialmente caigan en el mismo objeto.
Normalización de URL: registro, doble ranura, trailing slash, orden de los parámetros de query.
Ignora el «ruido»: 'utm _', 'fbclid', 'gclid', etiquetas de ref arbitrarias.
Vary restringido: sólo titulares realmente significativos ('Accept-Encoding', a veces 'Accept',' Accept-Language 'para local).
Clase de dispositivo: si es necesario, utilice 2-3 clases (mobile/desktop/tablet) en lugar de interminables ramas de usuario-agente.
Contexto automático: por defecto, no caché privado; utilice signed-URLs/cookies-bypass o separar rutas públicas/privadas.
Surrogate-Key: product:123 catalog
Cache-Control: public, s-maxage=300, stale-while-revalidate=600
Vary: Accept-Encoding
Estrategias TTL por tipo de contenido
Políticas
Por URL/Prefix: «desliza todo bajo '/static/2025-11-05/'».
By Tag/Key: «filmar todo 'catalog' y 'product: 123'».
Soft purge: etiquetar como obsoleto, no borrar el objeto - volver a rellenar más rápido.
Event-driven: CI/CD o evento de administración llama a webhook "invalidate tags'.
Recomendación: combine ambas tácticas: versionar rutas para assets + tag-purge para contenido/páginas.
Tiered-cache, origin-shield и prewarm
Tiered-cache: las capas regionales de CDN → menos solicitudes de origen.
Origen-escudo: un «escudo» POP al origen - mejora la localidad y el hit-ratio.
Prewarm (pre-fetch): calienta las URL/cachés calientes antes del evento/lanzamiento.
Cache negative: cache brevemente el 5xx/Timeout (30-120 s) para no inundar el origin con una tormenta de retraídas.
API de caché: cuando se puede
Sólo GET/HEAD e idempotente.
Clave: ruta + query esencial (por ejemplo, '? categoría =... & page =...').
Validación: 'ETag '/' Last-Modified' y el corto 's-maxage'.
Filtros por usuario: lleve la personalización a la función cliente/edge o utilice signed-requests + respuesta «pública».
Cache-Control: public, s-maxage=30, max-age=5, stale-while-revalidate=120, stale-if-error=600
ETag: "feed-v42"
Protección contra envenenamiento de caché
Normalización rígida de URL/encabezados; lista blanca de parámetros en la clave.
Recortar encabezados/duplicados sospechosos ('X-Forwarded-', extendidos por 'Accept').
Limitación de 'Vary' y control de tamaño/cola-wa de los encabezados.
Separación de dominios: privado/administrador - en un nombre separado sin caché.
Validación de respuestas: no almacene en caché 4xx (excepto 404 para estáticos), no almacene en caché páginas «personalizadas» sin una política explícita.
Compresión y formatos
Brotli para texto (js/css/json), gzip - fallback; los assets pre-comprimidos son válidos.
Images: webp/avif donde el soporte; utilice 'Vary: Accept' + derivados derivados.
Range-requests para vídeo/audio: CDN almacena en caché las chancas.
Content-Negotiation: Mantenga un cardenalito de clave bajo (device-class en lugar de UA crudo).
Observabilidad y SLO
Métricas clave
Hit-ratio (by bytes/requests) на edge/tier/shield.
p50/95/99 TTFB por región y tipo (estático/API).
Fill-rate/Origin egress - cuánto se va a origin.
304 tasa y tamaño de respuesta promedio.
Error budget: fracción de 'stale-if-error '/' SWR' de las entregas; frecuencia de purge.
Ejemplos de SLO
'p95 TTFB' estática regional ≤ 120-150 ms, API GET caché ≤ 200-250 ms.
Edge hit-ratio estática ≥ 90%, semi-altavoces ≥ 60%.
Porcentaje de respuestas de la rama stale en los errores ≤ 0. 5% en 30 días.
Opciones de configuración
Nginx (reverse-proxy antes de CDN o en 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, concepto)
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
Headers para assets «rápidos»
Cache-Control: public, max-age=31536000, immutable
ETag: "hash"
Content-Encoding: br
Headers para semi-altavoz (directorios)
Cache-Control: public, s-maxage=600, max-age=120, stale-while-revalidate=1800, stale-if-error=86400
Vary: Accept-Encoding, Accept
FinOps: cómo la caché ahorra dinero
Egress origin ↓, menos carga de CPU/DB → menor costo de infraestructura.
Menos solicitudes antes de los backends pagados (search/index/images).
Métricas de destino: $/reducción de p95 y $/reducción de 1 GB en egresos - seguimiento del efecto post-lanzamiento.
Características específicas para iGaming/Fintech
Catálogos de proveedores/assets: rutas versionadas + TTL de un año.
Lending de eventos/torneos: 1-5 min 's-maxage' + 'SWR' en 10-30 min; tag-purge cuando se actualiza.
Las páginas de Lima (coeficientes/tablas): caché parcial de bloques JSON, TTL cortos (5-30 s), para bloques personales - renderizador de clientes.
PSP/endpoints de pago: no caché, estricto 'no-store'; Sólo almacene en caché las referencias (tablas BIN, estados).
Antibot: caché estático/GET, rutas «grises» para ASNs sospechosos; no admita 'Vary' en títulos ruidosos.
Lista de comprobación de implementación
- Se describe la clave de caché: normalización de la URL, lista de query permitida, 'Vary' sólo según lo deseado.
- Caminos públicos/privados separados; privado - 'no-store' y bypass CDN.
- Se introdujeron escaleras TTL por tipo de contenido; configurado por 'SWR/if-error'.
- tiered-cache + origin-shield configurados; activado negative-cache 5xx (corto).
- Hay tag/URL purge, soft purge; integración con CI/CD.
- Se incluye compresión (br/gzip), formatos de imagen web y respuestas range.
- Métricas: hit-ratio by layer, p95 TTFB, 304 rate, origin egress; alertas de fallos.
- Playbucks: calentamiento de caché antes de los picos, purge de emergencia, degradación de origin.
Errores típicos
Los assets sin versio con TTL de gran tamaño → bandas «pegadas» entre los usuarios.
El excesivo 'Vary' (por 'User-Agent', todos los titulares) → una explosión de cardinalidad y un bajo hit-ratio.
Almacenamiento en caché 4xx/401/403/contenido privado.
La ausencia de un caché negative → una avalancha de solicitudes de origen degradado.
No tag-purge → purge de puntos masivos y «tormenta» re-fill.
La clave de caché incluye opciones UTM/REF «ruidosas».
Una TTL demasiado corta para estática → una carga extra en CDN y origin.
Minibuses
1) Calentar la caché antes del evento
1. Recopilación de la URL N superior por logs → 2) Prefetch paralelo (rate-limited) por región → 3) Verificación de hit-ratio ↑ y p95 ↓.
2) Católogos soft-purge de emergencia
1. Enviar 'PURGE '/tag-clear → 2) CDN regala stale y con el fondo aprieta fresco → 3) Comprobar que no hay espinas en el origin.
3) Denegación de origin
1. 'stale-if-error' elabora el reloj X → 2) Incluye el banner de «trabajo técnico» en edge → 3) Por recuperación - objetivo warm-up.
Resultado
Estrategia CDN fuerte = clave de caché correcta + TTL significativa con SWR/if-error + discapacidad controlada + tiered/shield + observabilidad. Fije la política en headers e IaC, mida hit-ratio y p95, planifique el calentamiento bajo picos - y los usuarios siempre recibirán una respuesta rápida, y origin permanecerá vivo incluso en la hora más caliente.