Capítulo 03 · El borde

CDN y edge

Las fotos del 123 no tienen que viajar a tu origen cada vez. PoPs, Cache-Control, purge. Estático por el borde; dinámico por el load balancer.

15 min intro

La foto no es el pedido

Imaginate que seguimos en la misma tienda. Ya tenemos base de datos: en products vive una URL, no el JPEG. Ya tenemos load balancer delante de varias APIs. Ana abre la ficha del 123. El JSON del producto (precio, tallas, título) es una cosa. Las fotos son otra: megas, públicas, iguales para todo el mundo.

Si cada vista de la ficha baja la imagen desde tu origen en Virginia, y Ana está en Madrid, pagás latencia de océano aunque el precio no haya cambiado. Si mil personas miran el mismo 123, son mil viajes al mismo disco. Eso no es un problema de Postgres. Es un problema de bytes cerca del usuario.

Un CDN (Content Delivery Network) es una red de cachés en el borde: servidores repartidos por el mundo (PoPs) que guardan copias de lo estático. Ana pide la foto a un hostname del CDN. Si el PoP de cerca la tiene, responde sin molestar a tu origen. Si no, el CDN la busca una vez, la guarda, y las siguientes Anas de esa región no cruzan el Atlántico.

Dos caminos en la misma ficha

La ficha del 123 mezcla dos tipos de request. Conviene no meterlos en el mismo tubo mental.

Dinámico. GET /products/123 (JSON), login, Comprar. Pasa por el load balancer hacia tus APIs. Ahí vive la lógica, la sesión, el cobro. Eso no es el trabajo principal del CDN (aunque algunos CDNs modernos puedan cachear respuestas GET públicas; el default de entrevista es: API detrás del LB).

Estático. Fotos, CSS, JS del storefront, a veces el HTML público del catálogo. Sale de object storage (S3) como origen, con el CDN delante. En products, solo la URL https://cdn.shop…/123/main.jpg.

Ana (Madrid)
  ├─ foto 123  → CDN (PoP cerca) → (miss) S3 origen
  └─ JSON 123  → load balancer → API → Postgres / Redis

En una entrevista de system design, dibujar “CDN” sin decir qué cachea es ruido. Decí: images and static assets on the CDN; product API behind the load balancer.

Cómo funciona (hit y miss en el borde)

Paso a paso, con la foto del 123:

  1. Ana pide cdn.shop…/123/main.jpg.
  2. DNS (a menudo anycast) la manda al PoP más cercano.
  3. Si el PoP tiene la foto y no expiró: hit. Responde en milisegundos locales.
  4. Si no: miss. El CDN pide al origin (tu bucket S3, o a veces un origen HTTP tuyo), guarda la respuesta según las reglas de caché, y se la da a Ana.
  5. La próxima Ana en esa región hace hit.

El origen sigue siendo la verdad del archivo. El CDN es copia, igual que Redis es copia del JSON. Si S3 no tiene la foto, el CDN no inventa zapatillas.

Cache-Control, TTL y purge

El CDN no adivina cuánto tiempo guardar. Lo decís vos (o tu origen) con headers: Cache-Control: public, max-age=86400. Un día de foto estable es normal. Un asset con hash en el nombre (main.a1b2c3.jpg) puede vivir mucho: si cambiás la foto, cambiás la URL y no hace falta pelear con cachés viejas.

Cuando el editor sube una foto nueva con la misma URL, hace falta invalidar (purge) en el CDN: “olvidate de esta key en todos los PoPs”. Sin purge y sin cambiar el nombre del archivo, Ana puede ver la foto vieja horas. Es el mismo oficio que el stale del caché, pero en el borde y con megas.

Regla práctica de tienda:

  • Assets con fingerprint en el nombre: TTL largo, casi no purgás.
  • URL estable que el marketing reusa: TTL más corto o purge al publicar.
  • HTML personalizado del checkout: no lo pongas en el CDN como si fuera un JPEG.

Qué sí, qué no

Sí al CDN: fotos del 123, videos de unboxing, CSS/JS del tema, favicon, PDFs públicos de talles. Todo lo que es igual para Ana y para Luis y no necesita cookie de sesión.

No (o con mucho cuidado): respuestas del checkout, “mis pedidos”, precios con descuento personalizado, cualquier cosa que dependa de quién sos. Si cacheás eso en el borde, Luis puede ver el carrito de Ana. En entrevista eso es yellow flag.

Algunos CDNs ofrecen “edge compute” (correr lógica cerca del usuario). Para este capítulo alcanza con el oficio clásico: caché de estáticos. Si el enunciado es solo la tienda, no hace falta inventar Workers en el borde el minuto dos.

Origen, TLS y el pico de Black Friday

El origen suele ser S3 (o compatible). El CDN habla HTTPS con Ana; el certificado puede vivir en el CDN. Tus APIs siguen detrás del LB con su propio TLS, como en el capítulo anterior.

En Black Friday el beneficio se siente doble. Las mil vistas de la ficha no son mil lecturas a S3 ni mil hits a tu red de origen: la mayoría muere en el PoP. Liberás ancho de banda y protegés el origen. Si el CDN se cae, el plan B es servir desde origen directo (más lento, más caro) o degradar la ficha sin imágenes. Igual que Redis: el borde es copia, no suelo.

Ojo al origen como SPOF mal dimensionado. Si todos los PoPs hacen miss a la vez (TTL mal puesto, purge masivo, deploy de assets), el thundering herd se parece al stampede del caché: mil PoPs golpean S3 juntos. Mitigación: TTL con algo de margen, purge selectivo, a veces “origin shield” (un PoP intermedio que absorbe misses). En pizarra, nombrar el riesgo ya suma.

La ficha, con borde

Ana abre el 123. El navegador pide el HTML/JS (CDN o tu front) y las fotos por cdn.shop…. Hit en Madrid: no toca S3. En paralelo, el JSON del producto va al load balancer y, en el próximo capítulo, al caché Redis.

Un editor cambia la foto principal. Sube a S3. Si la URL tiene hash nuevo, actualizás la fila en Postgres y listo. Si reusa la misma URL, purge en el CDN. El precio de cobro no vive en el CDN: vive en Postgres.

Dos caminos en la ficha 123: fotos por CDN hacia S3, JSON por load balancer hacia la API y Postgres.

Dos caminos. Un solo producto en la cabeza de Ana.

Qué espera cada nivel

Un mid pone fotos en S3 con CDN delante y la API detrás del load balancer.

Un senior separa estático de personalizado, habla de Cache-Control o fingerprint, purge vs URL nueva, y no cachea el checkout en el borde.

Si te lo preguntan

¿Para qué un CDN? Product images and static assets are the same for everyone; we serve them from edge PoPs so Madrid does not fetch Virginia on every view.

¿Dónde está el origen? Object storage — S3 — with the product row holding the URL. Metadata in Postgres, bytes in the object store.

¿Qué no va al CDN? Authenticated or personalized responses — checkout, my orders, per-user prices. Those go through the API.

¿Cómo actualizás una foto? Prefer fingerprinted URLs. If the URL stays the same, purge the CDN after uploading to S3.

¿CDN vs Redis? CDN for public static bytes at the edge. Redis for application data like product:123 JSON close to the API.