Skip to content

Instantly share code, notes, and snippets.

@jbgutierrez
Created April 1, 2026 08:50
Show Gist options
  • Select an option

  • Save jbgutierrez/710a344526034ed43a27bef18075be85 to your computer and use it in GitHub Desktop.

Select an option

Save jbgutierrez/710a344526034ed43a27bef18075be85 to your computer and use it in GitHub Desktop.
Investigación 360: Incremento anómalo de costes CDN en static.zara.net

Investigación: Incremento anómalo de costes CDN en static.zara.net

Contexto y evidencia de partida

El equipo de infraestructura ha detectado un incremento sostenido de costes en el CDN de Zara (dominio static.zara.net, servido via Akamai + Fastly) desde principios de febrero 2026. El incremento es de aproximadamente +300.000 €/mes respecto al baseline de enero 2026.

Las métricas disponibles en Grafana/Prometheus muestran:

  • Throughput por extensión de fichero (cdn_metrics_throughput_by_file_extension): incremento pronunciado en .m4s y .m3u8 a partir de la primera semana de febrero, sin cambio equivalente en .jpg ni en otros assets estáticos. El crecimiento en .m4s supone el ~80% del incremento total de bytes.

  • Bytes procesados (cdn_metrics_bytes_processed_lite): el dominio static.zara.net pasa de un baseline estable de ~3.5 GB/s a picos sostenidos de ~4.5 GB/s. No se observa patrón diario claro (no es solo tráfico de horas punta) — el incremento base sube.

  • Número de requests (cdn_metrics_requests): el volumen de requests .m4s crece más rápido que los bytes — lo que sugiere que no son archivos más grandes sino que se realizan más peticiones redundantes de los mismos archivos.

  • La anomalía está únicamente en static.zara.net. Los dominios de otras marcas del grupo (bershka, pullandbear, massimodutti) no muestran el mismo patrón.

  • No coincide con ningún deploy de infraestructura CDN conocido. La hipótesis del equipo es que un cambio en el cliente (app iOS, app Android, o web) está provocando un comportamiento de descarga ineficiente de los assets de vídeo HLS.

Objetivo: Identificar la causa exacta del incremento, cuantificar el desperdicio de ancho de banda, y elaborar un plan de remediación integral con priorización y estimación de impacto.


Herramientas disponibles

Tienes acceso a los siguientes MCPs. Actívalos al inicio de tu sesión:

SRE MCP (Prometheus + Loki + Tempo + Memento):

type: remote
url: https://iop-sremcp-obsassist.apps.axsv1ocp1.service.inditex.grp/mcp

Datasources disponibles: prometheus, loki, tempo, memento Notas importantes:

  • Límite de rango de consulta: ~745 horas (~31 días) por query
  • Para históricos de 90 días usa 3 queries consecutivas con ventanas de 31d
  • Queries con regex multi-dominio o avg_over_time con ventanas >24h pueden dar timeout — usa rate() con step explícito
  • Métrica de throughput: cdn_metrics_throughput_by_file_extension
  • Métrica de bytes: cdn_metrics_bytes_processed_lite
  • Métrica de requests: cdn_metrics_requests
  • Label de dominio: domain="static.zara.net"
  • Label de extensión: file_extension="m4s" (sin punto)

Playwright MCP (análisis de comportamiento web):

type: local
command: npx @playwright/mcp@latest

GitHub MCP (acceso a repositorios de código):

type: remote
url: https://api.githubcopilot.com/mcp/

Mobile MCP (análisis de comportamiento en iOS y Android):

Instala si no está disponible: npx @mobilenativefoundation/mobile-mcp

Requiere dispositivo físico o simulador conectado.


Plan de trabajo

Ejecuta los siguientes pasos en orden. Cada paso alimenta al siguiente.


Fase 1 — Caracterización del problema en CDN (SRE MCP)

Objetivo: Pasar de "hay un incremento" a "sabemos exactamente qué, cuándo, cuánto y con qué patrón".

1.1 Línea temporal del incremento

Obtén la serie temporal de bytes por extensión para static.zara.net desde noviembre 2025 hasta hoy, con granularidad semanal. Identifica:

  • Fecha exacta de inicio del incremento
  • ¿Es un salto escalón (deploy puntual) o una rampa gradual?
  • ¿Hay correlación con algún lunes/martes (día típico de releases iOS/Android)?

1.2 Desglose por tipo de asset de vídeo

Para .m4s y .m3u8, desglosa si es posible por:

  • Sub-path o pattern de URL (¿son assets de producto, de marketing, de home?)
  • Tamaño medio de response (¿cambia el tamaño medio de los segmentos descargados, o solo el número de veces que se piden?)

1.3 Cache hit ratio

Obtén el cache hit ratio CDN para .m4s antes y después del incremento. Un cache miss ratio alto en assets de vídeo (que deberían tener max-age=1y) indicaría que las URLs están cambiando por sesión (cache busting involuntario) o que los clientes no están reutilizando conexiones keep-alive.

1.4 Patrón horario

¿El incremento sigue el patrón de uso de la app (más tráfico en horas de mayor actividad)? ¿O el incremento base ha subido uniformemente? Esto distingue entre "más usuarios" vs "más bytes por usuario".


Fase 2 — Análisis del comportamiento web (Playwright MCP)

Objetivo: Determinar si el problema existe o no en web, y si es así, caracterizarlo.

2.1 Setup de captura

Navega a la home de Zara con interceptación de red activa:

https://www.zara.com/es/es/

Intercepta todos los requests a static.zara.net con extensión .m4s, .m3u8, .m4v, .mp4.

2.2 Comportamiento en carga inicial (sin scroll)

Registra todos los requests de vídeo lanzados en los primeros 5 segundos tras el DOMContentLoaded, sin ninguna interacción del usuario.

  • ¿Cuántos assets de vídeo se prefetchan fuera del viewport?
  • ¿Se solicitan manifests .m3u8 de vídeos no visibles?
  • ¿Qué atributo preload tienen los elementos <video>?

2.3 Comportamiento durante scroll

Haz scroll a velocidad normal por la página. Para cada vídeo que entra en viewport:

  • ¿Cuánto tiempo tarda en empezar la descarga de .m4s desde que es visible?
  • ¿Los requests de .m4s usan header Range con offset creciente (descarga continua) o reinician desde bytes=0 si el vídeo entra y sale del viewport?

2.4 Comportamiento al navegar entre páginas

Navega a una category page (ej. mujer/nuevo), vuelve atrás, navega de nuevo. ¿Los players de vídeo que ya habían empezado a descargar se pausan y liberan el buffer, o continúan descargando en background?

2.5 Análisis de manifests HLS en vivo

Para cada master.m3u8 que captures, descárgalo y analiza:

  • Renditions disponibles (resoluciones, bitrates)
  • ¿Son apropiados para el contexto de uso (vídeo de feed, autoplay, muted)?
  • ¿Hay renditions excesivamente pesados para móvil/conexión media?

2.6 Política de caché en respuestas

Registra los headers Cache-Control, ETag y Surrogate-Control de las respuestas .m4s y .m3u8. ¿Son coherentes con las mejores prácticas para assets inmutables (content-addressed)?


Fase 3 — Análisis del comportamiento en iOS (Mobile MCP)

Objetivo: Reproducir el comportamiento de la app iOS en condiciones controladas y medir el desperdicio de descarga con precisión.

3.1 Setup

Conecta un dispositivo iOS o simulador. Configura proxy de red para capturar tráfico HTTPS a static.zara.net.

3.2 Flujo de prueba 1 — Carga inicial de home

  1. Lanza la app Zara iOS desde cero (cold start)
  2. Sin hacer ningún gesto, espera 10 segundos
  3. Registra todos los requests a static.zara.net

Mide:

  • ¿Cuántos .m3u8 se fetchen antes de cualquier interacción?
  • ¿Se inician descargas de .m4s de vídeos fuera del viewport?

3.3 Flujo de prueba 2 — Scroll por carrusel

  1. Desplázate lentamente por el carrusel de la home (5-6 items)
  2. Vuelve al primer item
  3. Repite 3 veces

Para cada .m4s descargado, registra la secuencia de Range headers:

  • ¿Los requests son bytes=0-N (inicio completo) o bytes=M-N (continuación)?
  • ¿El mismo asset es solicitado múltiples veces con bytes=0?

3.4 Flujo de prueba 3 — Background / foreground

  1. Abre un vídeo en la app, deja que empiece a reproducirse
  2. Pulsa home (la app va a background)
  3. Espera 5 segundos
  4. Vuelve a la app (foreground)
  5. Observa los requests generados en el momento de volver

¿Se reinicia la descarga del vídeo desde bytes=0?

3.5 Cuantificación del desperdicio

Para cada asset descargado más de una vez:

bytes_desperdiciados = sum(content_length de requests bytes=0)
                       - content_length de la primera descarga
porcentaje_redundante = bytes_desperdiciados / total_bytes_descargados

Fase 4 — Análisis del comportamiento en Android (Mobile MCP)

Repite la Fase 3 exactamente en Android (adb + proxy de red).

Presta especial atención a:

  • ¿ExoPlayer destruye y recrea el MediaItem al salir del viewport?
  • ¿Se usa SimpleCache de ExoPlayer para persistir segmentos entre sesiones?
  • ¿El RecyclerView llama a setPlayer(null) en onViewRecycled? Si es así, ¿se reasigna el player correctamente sin re-descargar?

Fase 5 — Análisis de código fuente (GitHub MCP)

Objetivo: Identificar en el código el mecanismo exacto que causa el comportamiento observado en las fases 3 y 4.

5.1 Repositorios a explorar

Busca en la organización inditex (o la organización correspondiente) los siguientes repositorios:

  • Player de vídeo iOS: busca repos con nombre similar a mlb-xmediaplayerios, xmedia-player-ios, zara-video-ios
  • SDK SDUI iOS: busca repos con nombre similar a mlb-sduicefios, sdui-ios, server-driven-ui-ios
  • Player de vídeo Android: equivalente Android
  • SDK SDUI Android: equivalente Android
  • Frontend web Zara: busca el componente de vídeo en el carrusel de la home

5.2 Preguntas a responder en el código iOS

En el player iOS, localiza:

a) Gestión del ciclo de vida del player:

  • ¿Dónde y cuándo se destruye el AVPlayer / AVPlayerItem?
  • ¿Se destruye al cambiar de asset, o se reutiliza cambiando solo la URL?
  • ¿La comparación para decidir si el asset "ha cambiado" es por URL o por identidad de objeto?

b) Integración con SwiftUI (si aplica):

  • ¿El wrapper UIViewRepresentable implementa updateUIView correctamente para reutilizar la vista, o está vacío?
  • ¿Un re-render del componente padre recrea el player entero?

c) Control de viewport / preload:

  • ¿Existe lógica para pausar/cancelar la descarga cuando el vídeo sale del viewport?
  • ¿Cuántos assets se precargan por adelantado? ¿Es configurable?

d) Gestión de background:

  • ¿Hay observadores de UIApplication.didEnterBackgroundNotification para pausar el player?

e) Selección de audio track:

  • ¿El bitrate del audio track se selecciona en función de la resolución de vídeo, o se descarga siempre el de mayor calidad?

5.3 Preguntas a responder en el código Android

Las mismas preguntas, adaptadas a Android/ExoPlayer:

  • ¿ExoPlayer.release() se llama cuando la vista sale del viewport?
  • ¿Se usa MediaItem con la misma URL sin recrear el player?
  • ¿SimpleCache está configurado con tamaño razonable?

5.4 Preguntas a responder en el código web

  • ¿Los <video> tienen preload="none" o preload="metadata" fuera de viewport?
  • ¿Hay IntersectionObserver con threshold adecuado?
  • ¿Al destruir el componente se hace video.src = ''?
  • ¿Se usa HLS.js, hls nativo, o Shaka Player? ¿Cuál es la configuración de buffer (maxBufferLength, maxMaxBufferLength)?

Fase 6 — Análisis de manifests HLS y tramos disponibles

Para los assets de vídeo representativos capturados en las fases anteriores, descarga y analiza los manifests completos:

Por cada master.m3u8 analizado:

  1. Inventario de renditions:

    Resolución | Bitrate vídeo | Codec | Audio track | Bitrate audio
    
  2. Evaluación de adecuación:

    • ¿Los bitrates ofrecidos son apropiados para el contexto de uso? (autoplay silencioso en feed vs. reproducción intencional con sonido)
    • ¿Hay renditions que nunca se seleccionarían en condiciones normales de red móvil (4G/5G)?
    • ¿El audio track de mayor calidad se incluye siempre en el master, o hay configuración por tipo de asset?
  3. Duración y número de segmentos:

    • ¿Cuánto dura cada segmento .m4s? (ideal: 2-6 segundos)
    • ¿Cuántos segmentos tiene el vídeo completo?
    • Si el usuario ve solo los primeros 3 segundos, ¿cuántos bytes son necesarios? ¿Cuántos se descargan en realidad?
  4. Init segments:

    • ¿Hay EXT-X-MAP con un init segment separado?
    • ¿El init segment se reutiliza entre renditions del mismo asset?

Fase 7 — Evaluación de política de caché CDN

Con los headers capturados en las fases anteriores, evalúa:

Para .m4s (segmentos, inmutables por naturaleza):

  • Cache-Control actual vs. recomendado
  • ¿Se usa immutable directive?
  • ¿Hay Vary headers que fragmenten el caché CDN?

Para .m3u8 (manifests):

  • Los manifests con hash en la URL son inmutables — ¿tienen TTL largo?
  • ¿El ?ts= o cualquier query param afecta al cache key en Akamai/Fastly?

Para .zip (si hay requests de ZIPs):

  • ¿Son assets que deberían cachearse agresivamente?
  • ¿Se pueden eliminar peticiones redundantes?

Fase 8 — Plan de remediación integral

Con toda la evidencia recopilada, elabora un plan estructurado.

Para cada item del plan, incluye:

### [P0/P1/P2] Título del fix

Plataforma: iOS / Android / Web / CDN / Manifests
Repo y fichero(s): ruta exacta
Descripción técnica: qué cambiar exactamente y por qué
Impacto estimado: X TB/mes (~Y €/mes)
Esfuerzo estimado: N días de desarrollo + QA
Riesgo: bajo / medio / alto — descripción
Criterio de éxito: métrica Prometheus o test que confirma la corrección
Dependencias: otros fixes previos necesarios

Prioridades esperadas (a confirmar con la evidencia):

  • P0 — Bugs de ciclo de vida del player que causan re-descargas desde bytes=0 del mismo asset en la misma sesión
  • P0 — Descarga de vídeos fuera del viewport sin intención del usuario
  • P1 — Optimización de renditions HLS (eliminar tracks innecesarios)
  • P1 — Fixes de comportamiento en background / foreground
  • P2 — Mejoras de política de caché CDN
  • P2 — Reducción de peticiones de verificación innecesarias (offline.zip, etc.)

El plan debe incluir:

  1. Tabla resumen con todos los ítems, impacto y esfuerzo
  2. Roadmap temporal: qué se puede hacer en sprint 1 (quick wins), sprint 2 (mejoras estructurales), sprint 3 (optimizaciones CDN)
  3. Estimación de reducción total de costes CDN si se aplica el plan completo
  4. Métricas de monitorización que deben implementarse para detectar regresiones futuras

Entregables

  1. Informe de hallazgos (markdown):

    • Evidencia de métricas CDN con gráficas o datos tabulados
    • Comportamiento observado en web (capturas Playwright)
    • Comportamiento observado en iOS y Android (network trace)
    • Diagnóstico de código con extractos relevantes y líneas exactas
    • Análisis de manifests HLS con inventario de renditions
  2. Plan de remediación (markdown):

    • Todos los fixes P0/P1/P2 con el formato especificado
    • Tabla resumen de impacto y esfuerzo
    • Roadmap por sprints
  3. Consultas Prometheus reutilizables para monitorización continua


Notas operativas

  • El MCP de SRE está configurado como enabled: false por defecto — actívalo en la configuración antes de empezar.
  • Las queries Prometheus con ventanas largas (>24h) y multi-dominio pueden dar timeout — parte de queries simples y amplía si funcionan.
  • Si Mobile MCP no está disponible, usa Charles Proxy / mitmproxy exportando el tráfico en formato HAR para análisis offline.
  • Los repositorios pueden estar en la organización inditex o en una organización específica de la marca — búscalos por nombre aproximado si no aparecen directamente.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment