SSR en el edge: renderizar cerca del usuario
Renderizar en el servidor a milisegundos del usuario es la promesa del edge, pero solo rinde cuando los datos y el cómputo viven cerca. La ventaja real del SSR en el edge, la trampa de la localidad de datos, el streaming del HTML y por qué la caché es la otra mitad de la ecuación.
Renderizar en el servidor —SSR— siempre fue una elección entre HTML listo al instante y la latencia de un servidor lejano. El edge reescribe esa ecuación: si el servidor que renderiza está a milisegundos del usuario, obtienes lo mejor de ambos mundos, HTML dinámico y personalizado sin el peaje de la distancia. Pero mover el cómputo cerca del usuario abre una pregunta nueva y afilada: ¿dónde están los datos? El SSR en el edge es tan potente como cuidadoso hay que ser con eso, y esta lección es sobre ambas caras.
- Explicar qué gana el SSR al ejecutarse en el edge, cerca del usuario.
- Diagnosticar la trampa de la localidad de datos y el coste de los viajes de ida y vuelta.
- Aprovechar el streaming del HTML para adelantar la respuesta al cliente.
- Usar la caché del edge como la otra mitad de una estrategia de SSR sana.
Renderizar a milisegundos del usuario
En el SSR clásico, un servidor central —pongamos en una región de Estados Unidos— recibe la petición, renderiza el HTML y lo devuelve. Para un usuario en Madrid o en Yakarta, cada petición cruza el planeta dos veces antes de ver un solo píxel. El edge elimina ese viaje: el mismo código de renderizado se ejecuta en el centro de datos más cercano a quien pide, así que el HTML se genera al lado del usuario y no a un océano de distancia.
La ventaja se nota sobre todo en el tiempo hasta el primer byte, el TTFB. Como el isolate arranca sin cold start y renderiza localmente, el HTML empieza a fluir casi de inmediato. Y a diferencia de una página estática, sigue siendo dinámico: puedes personalizar por usuario, por región o por la hora, porque hay cómputo real detrás de cada respuesta.
Conviene contrastarlo con la alternativa que dominó la década anterior: el renderizado en el cliente. Ahí el servidor envía un armazón de HTML casi vacío y un paquete de JavaScript que, ya en el navegador, pide los datos y construye la interfaz. El usuario mira una pantalla en blanco mientras descarga y ejecuta ese paquete. El SSR en el edge invierte el reparto: el trabajo pesado ocurre en el servidor cercano, y lo que llega al navegador es HTML ya formado que se pinta sin esperar a un bundle. El cliente recibe contenido, no una promesa de contenido.
Cómputo cercano
El renderizado corre en el centro de datos más próximo al usuario. El HTML nace a su lado, no tras un viaje intercontinental.
Dinámico y personalizado
A diferencia del estático, cada respuesta puede cambiar por usuario, región u hora, porque hay lógica real ejecutándose.
Sin cold start
El isolate despierta en una fracción de milisegundo, así que el renderizado no arrastra el peaje de arrancar una máquina.
La trampa de la localidad de datos
Aquí está el matiz que separa una demo bonita de un sistema real. Mover el cómputo al edge no mueve tus datos. Si tu Worker renderiza en Yakarta pero tu base de datos vive en Virginia, cada consulta que el renderizado necesite cruza medio mundo, y basta con encadenar unas pocas para que la latencia de los datos devore por completo la que ganaste acercando el cómputo.
Es la reencarnación de los dos ejes que atraviesan todo el track: acercar el cómputo al usuario solo rinde si los datos que ese cómputo consume también están cerca. Un SSR en el edge contra una base de datos regional y lejana puede ser más lento que un SSR regional pegado a esa misma base, porque suma la distancia en cada viaje de ida y vuelta.
flowchart TB U[Usuario en Yakarta] --> W[Render en el edge cercano] W -->|consulta 1| DB[Base de datos en Virginia] DB -->|respuesta 1| W W -->|consulta 2| DB DB -->|respuesta 2| W W --> H[HTML al usuario] style W fill:#fab387,color:#11111b style DB fill:#f38ba8,color:#11111b
Las salidas son dos, y conviene tenerlas claras. La primera es acercar también los datos: usar almacenes pensados para el edge —KV para lecturas globales, D1 con réplicas, Durable Objects para estado coordinado— de modo que la lectura no cruce el planeta. La segunda, cuando los datos deben vivir en una base regional, es la colocación inteligente: pedir a la plataforma que ejecute el Worker cerca de esos datos en lugar de cerca del usuario, invirtiendo el reparto para minimizar el número y la longitud de los viajes.
El enemigo del SSR en el edge no es la distancia de una sola consulta, sino su multiplicación. Un renderizado que hace un waterfall de cinco consultas secuenciales contra una base lejana paga cinco veces la distancia, en serie. Antes de optimizar dónde corre el código, reduce y paraleliza las consultas: agrupa lecturas, evita el N+1, resuelve en paralelo lo que no dependa entre sí. Muchas veces el problema de latencia no es geográfico, es un patrón de acceso a datos mal diseñado que el edge se limita a amplificar.
Streaming: no esperes al HTML entero
El edge tiene una carta extra que el SSR tradicional rara vez juega bien: el streaming. Como el fetch handler puede devolver una Response cuyo cuerpo es un ReadableStream, el framework puede empezar a enviar el HTML de la cabecera y del armazón de la página mientras aún resuelve los datos de las partes lentas. El navegador recibe y pinta lo primero de inmediato, y el resto llega en cuanto está listo.
// el render devuelve un stream; el runtime envia bytes segun se producen
const stream = await renderToReadableStream(<App />);
return new Response(stream, {
headers: { "Content-Type": "text/html" },
});
Los frameworks modernos —React con sus Suspense, Astro con sus islas de servidor— exponen esto de forma declarativa. La consecuencia práctica es que la latencia de los datos deja de bloquear la primera pintura: el usuario ve estructura al instante y el contenido lento aparece en su hueco cuando llega, en lugar de mirar una pantalla en blanco hasta que todo esté resuelto.
El streaming mejora la latencia percibida —lo que el usuario siente— pero no reduce el tiempo total hasta que la página está completa. Una consulta lenta sigue siendo lenta; el streaming solo evita que bloquee todo lo demás. Es una herramienta magnífica para la experiencia, pero no sustituye a acercar y paralelizar los datos. Trátalo como el maquillaje que complementa una buena arquitectura de datos, nunca como el reemplazo de ella.
La caché es la otra mitad
La pregunta más sana ante cualquier SSR es: ¿de verdad necesito renderizar esto en cada petición? Muchísimo HTML cambia poco entre usuarios o entre minutos, y renderizarlo una y otra vez es quemar cómputo para reproducir un resultado idéntico. La caché del edge convierte ese derroche en una lectura instantánea.
Con la Cache API o con cabeceras Cache-Control, guardas el HTML renderizado en el mismo edge que lo produjo, de forma que las siguientes peticiones lo reciben sin volver a renderizar ni a tocar la base de datos. El patrón stale-while-revalidate afina la idea: sirve la versión cacheada al instante y revalida en segundo plano, así nadie espera por el renderizado y el contenido se mantiene fresco.
// sirve del cache al instante, revalida en segundo plano hasta 5 min
return new Response(html, {
headers: {
"Content-Type": "text/html",
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
},
});
La regla mental es sencilla: renderiza en cada petición solo lo que de verdad cambia en cada petición. Un panel personalizado para un usuario concreto lo justifica; una página de producto que cambia una vez al día, no. Situar cada ruta en el punto correcto entre el estático y el SSR puro es, en la práctica, la decisión que más afecta al coste y a la latencia de una aplicación en el edge.
No pienses en “estático contra SSR” como una elección binaria, sino como un espectro con la caché en medio. En un extremo, HTML totalmente prerenderizado; en el otro, SSR puro por petición; y entre ambos, todo un abanico: SSR con caché de larga vida, SSR con stale-while-revalidate, regeneración incremental. La destreza no está en elegir un bando, sino en situar cada ruta en el punto del espectro que su frecuencia de cambio y su grado de personalización justifican.
La lección que corona este nivel es que el SSR en el edge no es una victoria automática, sino un presupuesto de latencia que tú administras, y administrarlo bien exige pensar en tres dimensiones a la vez. La primera es el cómputo, y esa te la regala la plataforma: el renderizado corre sin cold start a milisegundos del usuario, y ahí no hay nada que optimizar porque ya es óptimo. La segunda es la de los datos, y esa es tuya: acercar el renderizado al usuario no acerca la base de datos, así que un SSR brillante contra un almacén lejano puede rendir peor que un SSR modesto pegado a sus datos. Por eso la decisión de dónde vive cada dato —en KV global, en D1 replicada, en un Durable Object, o en una base regional a la que conviene acercar el cómputo con colocación inteligente— pesa tanto como la de qué framework usas, y con frecuencia más. La tercera dimensión es la caché, y es la que convierte una arquitectura correcta en una rápida: la pregunta no es solo “dónde renderizo” sino “cuántas veces necesito renderizar de verdad”, y cada respuesta que puedas servir desde la caché del edge es cómputo que no gastas y latencia que no pagas. Cuando internalizas estas tres dimensiones dejas de ver el SSR en el edge como un botón que enciendes y empiezas a verlo como un diseño que equilibras: acercas el cómputo, colocas los datos donde el patrón de acceso lo pide, haces streaming de lo lento y cacheas todo lo que no cambia en cada petición. El edge te da el cómputo cercano gratis; el arte está en que los datos y la caché estén a la altura de esa cercanía. Quien enciende el SSR sin pensar en las otras dos dimensiones acaba con una app que renderiza cerca y espera lejos; quien las orquesta las tres entrega HTML dinámico a velocidad de estático, que es exactamente la promesa por la que existe el edge.
- Toma una ruta con SSR de tu app y cuenta cuántas consultas a datos hace para renderizarse; identifica si son secuenciales o paralelas.
- Razona dónde viven esos datos respecto al usuario y decide si conviene acercarlos —KV, D1 replicada— o acercar el cómputo a ellos con colocación inteligente.
- Añade streaming a una parte lenta de la página con
Suspenseo islas de servidor y observa cómo adelanta la primera pintura. - Elige una ruta que cambie poco y cachéala en el edge con
Cache-Controlo la Cache API; mide la diferencia deTTFBentre la primera petición y las siguientes.