HTTP 200 sin datos: la falla que tus monitores no ven

En pocas palabras: El sitio pasó cuatro horas sin vender porque su proyecto Supabase en plan gratuito dejó de existir, pero cada página siguió respondiendo HTTP 200 con HTML completo; los monitores de uptime solo verifican códigos de estado y tiempos de respuesta, no si los datos reales llegan, así que ninguna alerta se disparó.

Un sitio de viajes pasó cuatro horas sin poder procesar una sola reserva porque su base de datos dejó de existir. Nadie recibió una alerta: cada página respondió HTTP 200 sin datos ni funcionalidad real durante toda la caída, con tiempos de respuesta normales y HTML lleno de contenido.

Este tipo de incidente tiene nombre: fallo silencioso de HTTP 200. Es una condición en la que el servidor entrega un código de éxito y una página visualmente completa, pero los datos dinámicos que hacen útil el sitio nunca llegan. El caso fue documentado el mismo día del incidente, en agosto de 2026, por un desarrollador independiente en dev.to, cuyo negocio de viajes corría sobre una plataforma gestionada con base Postgres (Supabase) en el plan gratuito, con base de datos, autenticación, almacenamiento y funciones edge empaquetados en un solo proyecto.

En 30 segundos

  • Cuatro horas sin ventas: el sitio quedó sin base de datos, logins, imágenes y funciones edge a la vez, y ningún monitor de uptime saltó.
  • La causa fue económica: el proyecto llevaba nueve meses en producción sobre el tier gratuito; al agotarse la franquicia, la plataforma lo pausó y el panel solo ofrecía pasar a USD 25/mes.
  • El corte fue quirúrgico: el subdominio respondía NXDOMAIN en dos resolutores independientes (1.1.1.1 y 8.8.8.8), mientras el dominio padre seguía resolviendo bien.
  • El prerender encubrió todo: 623 rutas con HTML intacto, structured data correcto y datos horneados hicieron que status, tiempos y palabras esperadas dieran perfecto en cada chequeo.
  • El arreglo cabe en dos líneas: consultar el endpoint real de datos (por ejemplo /rest/v1/hotels?select=name&limit=1) y exigir código 200 con al menos una fila.

¿Qué es un fallo silencioso de HTTP 200?

Un fallo silencioso de HTTP 200 ocurre cuando el servidor responde con éxito y sirve una página completa, pero los datos dinámicos que dan utilidad a esa página no llegan: el usuario ve una interfaz vacía y los sistemas de vigilancia registran “salud perfecta”. El código 200 certifica que la petición llegó, se procesó y hay una representación válida como respuesta. Nada más.

Ponele que abrís el listado de hoteles de un sitio de viajes. La carga es instantánea, el diseño está pulido, los filtros responden. Y el contador dice “Found 0 verified stays”. Cero estadías verificadas. Eso vio cualquier visitante durante las cuatro horas del incidente: filtros en cero, skeletons en el área de listados, y ni un solo link de reserva, porque esas URLs salen de la base de datos en tiempo de render.

Son preguntas distintas, y acá está la raíz de todo: “el servidor responde” y “los datos que necesito existen” no miden lo mismo. Todo el monitoreo convencional vive en la primera. El negocio vive en la segunda. Ya lo cubrimos antes en montar la demo de Kubernetes de Google.

¿Cómo puede un sitio devolver HTTP 200 sin datos ni funcionalidad?

Porque el 200 opera a nivel de transporte, no a nivel de negocio. Un sitio moderno típico es una cáscara estática que se llena desde una API: el HTML llega rápido y lleno, y después JavaScript pide los datos frescos a un backend. Si ese backend no existe, la página no falla con un error visible: simplemente re-renderiza con un array vacío.

Mirá la cadena completa del incidente, porque es educativa: compilás el sitio, el prerender hornea cada ruta con sus datos en HTML estático, lo deployás, Google lo indexa contento, un visitante abre la página, React hidrata, dispara la query contra un host que ya no existe, no recibe respuesta, y re-renderiza el componente con un array vacío. Impecable. Una “tienda perfecta” que no vende absolutamente nada.

¿Y el checkout? No había qué cobrar. Ni un link de reserva saliente en el HTML estático: esos URLs vienen de la base al momento de renderizar. Ojo con esto, porque significa que no hubo estado degradado ni fallback accidental. Hubo confianza absoluta acompañando cero inventario.

¿Qué pasó exactamente?

El caso lo contó el propio protagonista en un post publicado en dev.to el mismo día del incidente, en agosto de 2026. Su backend corría sobre una plataforma gestionada que empaqueta base de datos, autenticación, archivos y funciones serverless en un solo workspace. El workspace estaba en el tier gratuito. La franquicia se agotó, y la plataforma pausó el proyecto. Sin opción de pagar el saldo pendiente y seguir: el panel tenía exactamente una acción disponible, subir a un plan de USD 25/mes.

Fijate en el detalle que el autor destaca: esto no es el clásico olvido de factura. El tier gratuito venía sosteniendo producción hacía nueve meses, y el aviso de que iba a detenerse llegó siendo la detención misma. Un solo límite de consumo se llevó puestos cuatro subsistemas en simultáneo: la base de datos, todos los logins, cada imagen subida y la función edge que registra clics salientes. Parecían preocupaciones separadas hasta que compartieron destino.

El chequeo de DNS mostró lo completo de la retirada: consultas contra 1.1.1.1 y 8.8.8.8 no devolvían respuesta para el subdominio del proyecto, mientras el dominio padre resolvía bien. NXDOMAIN, no una página de pausa. El subdominio había sido retirado. Cubrimos ese tema en detalle en cómo evitar caídas por fallos de DNS.

La recuperación dejó números concretos. El autor dejó corriendo un script que sondeaba DNS y exportaba todo apenas el host volviera. Se disparó a las 15:42 y capturó cero bytes. ¿Por qué? Porque el DNS volvió unos cuarenta minutos antes que el servicio, y el script tomó un 401 del root de la API como señal de vida. Después pidió las dieciséis tablas, recibió errores del CDN por cada una, reportó todo como “no exportado” y cerró conforme con su trabajo. La corrida corregida, apuntando a una tabla real, bajó 91 MB: 220 países, 143 dispensarios, 58 propiedades y 563 objetos de almacenamiento, sin pérdidas.

“A 500 would have been better” (un 500 habría sido mejor), resume el autor. Un 500 pagina al guardia, dispara el monitor, manda un mail. Lo que tuvo fue un sitio que pasaba todos los chequeos automáticos sin convertir nada.

Queda la lección de arquitectura: cuando metés datos, auth, archivos y funciones en una misma plataforma, un aviso de facturación se transforma en un evento de disponibilidad total. Separar capas reduce el radio de explosión.

¿Por qué los monitores de uptime no detectan fallos silenciosos?

Porque cada señal que un monitor convencional recolecta responde una sola pregunta: ¿el servidor contesta? Durante la caída, todas las respuestas fueron afirmativas. La tabla siguiente arma el cuadro completo con los datos del incidente:

Chequeo del monitorLectura durante la caída¿Delata el fallo?
Código de estado HTTP200 OK en todas las rutasNo
Tiempo hasta el primer byteNormalNo
Texto esperado dentro del HTMLPresente (viene del prerender)No
Página vacíaAl contrario: llega llena de contenidoNo
Filas vivas desde la APINunca se consulta
http 200 sin datos funcionalidad diagrama explicativo

El hueco entre ambas preguntas no es exótico. Cualquier sitio que renderiza cáscaras estáticas y las llena desde una API lo tiene. Y acá viene la parte contraintuitiva: cuanto más exhaustivo tu prerendering, más ancho el punto ciego, porque la capa estática sigue pareciendo sana mucho después de que la dinámica murió. Esto se conecta con lo que analizamos en cómo evitar caídas por fallos de DNS.

¿Alguien validó los datos en algún momento de esas cuatro horas? Nadie.

¿Qué vio Googlebot y qué vieron los usuarios?

Al buscador le fue mejor que a tus clientes. Googlebot no ejecuta JavaScript con la agenda de un navegador de visita: recibió el HTML prerenderizado, 623 rutas de contenido intacto, structured data correcto y links internos funcionales. Durante toda la caída, la vista del índice estuvo sana. El prerender protegió el posicionamiento y abandonó al comprador.

Para un dominio de nueve meses todavía en evaluación, perder el índice hubiese sido más caro que perder una tarde de reservas, y el autor dice que no habría elegido distinto. Eso sí: conviene ser claro sobre qué se protegió y qué no, porque “el prerender nos salvó” es media verdad, y la otra media fueron todas las reservas de esa tarde.

Hay un matiz SEO adicional. Si el estado vacío se hubiese prolongado, las páginas servidas con 200 y sin contenido útil empiezan a rozar el territorio del soft 404, esa figura donde una URL responde éxito cuando debería señalar error. En este caso no llegó a pasar: el contenido horneado era genuino. Pero es el riesgo latente de dejar la capa dinámica muerta sin nadie mirando.

¿Cómo monitorear correctamente una SPA con prerendering?

Consultá un recurso que solo responda cuando el sistema de verdad funciona. El chequeo que el autor necesitaba nunca fue sobre el servidor: fue sobre los datos. Traé el endpoint de listados y exigí que el conteo sea mayor a cero:

curl -s "https://TU_PROYECTO.supabase.co/rest/v1/hotels?select=name&limit=1" \
 -H "apikey: TU_API_KEY"
# Criterio: código 200 y al menos una fila en la respuesta.

Dos líneas. Habría detectado el incidente en el primer minuto, y es el único chequeo de todo el episodio que lo habría hecho. El resto de las lecciones sale del fracaso del script de backup: pedirle vida a un 401 es el mismo error del monitoreo, una capa abajo. La pregunta nunca fue “¿algo contestó?”, sino “¿la cosa que necesito anda?”. Y DNS recuperado tampoco implica servicio operativo: hubo unos cuarenta minutos de desfase entre uno y otro. Relacionado: comparativa de pipelines CI/CD para este año.

¿Cuál es la estrategia de fallback para una SPA con prerendering?

Horneá los datos en el build y usalos de red de seguridad. El prerender ya consulta cada listado al compilar, así que el cliente podría recurrir a esos datos horneados cuando el fetch en vivo falla, en vez de renderizar ceros. La lógica del autor es contundente: los listados desactualizados igual venden; los listados en cero no venden nada, y encima lucen impecables haciéndolo.

  • Guardá el snapshot del build junto al bundle, de modo que el frontend tenga los datos a mano sin depender de la red.
  • Envolvé el fetch en vivo con un manejo de error que caiga al snapshot en vez de a un array vacío.
  • Avisale al usuario la antigüedad de los datos con una etiqueta de última sincronización cuando esté sirviendo copia local.
  • Simulá la caída de la API en tus pruebas para confirmar qué muestra realmente la interfaz cuando el backend desaparece.

Honestidad obligatoria: el autor aclara que ese build todavía no lo hizo. La idea está escrita; la implementación, pendiente.

Errores comunes con este tipo de fallo

  • Tratar cualquier respuesta como señal de vida. El script de backup tomó un 401 como servicio activo y cerró dieciséis tablas sin exportar. La corrección: exigir 200 sobre un recurso real de datos, no sobre el root de la API.
  • Asumir que DNS recuperado implica sistema listo. El nombre volvió cuarenta minutos antes que el servicio, y el export programado capturó nada. Sondeá el endpoint de datos, no el nombre de host.
  • Vigilar el HTML prerenderizado como prueba de salud. Ese contenido sobrevive mucho tiempo a la capa dinámica que lo generó. Validá datos frescos con una aserción de conteo, no presencia de texto.
  • Correr producción en un tier gratuito sin umbrales de consumo. La primera noticia del límite fue la pausa misma. Configurá alertas de consumo y poné lo crítico en un plan pago con facturación predecible.

Preguntas Frecuentes

¿Qué significa exactamente un código de estado HTTP 200?

Que la petición llegó, se procesó y el servidor devuelve una representación válida según el protocolo. No informa si los datos que viajan dentro siguen vigentes ni si la lógica de negocio detrás opera. Por eso un sitio entero puede responder 200 y estar comercialmente muerto, como pasó durante cuatro horas en este caso.

¿Este caso es un soft 404?

Emparentado, pero no idéntico. Un soft 404 es una URL que responde 200 cuando debería señalar error o inexistencia, algo que los buscadores terminan detectando. Acá el HTML prerenderizado tenía contenido genuino, así que ningún crawler veía un soft 404: el vacío aparecía recién cuando JavaScript pedía datos al backend desaparecido.

¿Por qué el prerendering agrava estos fallos invisibles?

Porque mantiene viva la fachada mucho después de que murió el fondo. Cuanto más completo el prerender (texto, datos horneados, structured data), más sano parece todo para cualquier chequeo basado en HTML. El autor lo plantea directo: a más prerendering exhaustivo, más ancho el punto ciego entre el servidor que responde y los datos que cargan.

¿Cómo armo un healthcheck que detecte datos faltantes?

Con una consulta a un endpoint real y una aserción sobre el resultado. Pedí una fila (GET /rest/v1/hotels?select=name&limit=1 con tu apikey), exigí código 200 y verificá que venga al menos un registro. Programalo cada minuto y alertá solo si falla: ese chequeo único habría atrapado este incidente de inmediato.

¿Conviene mostrar datos viejos cuando la API está caída?

Sí, y es la recomendación explícita del autor: los listados desactualizados igual venden, los listados en cero no venden nada. Guardá el snapshot del prerender y mostralo con un aviso de última sincronización cuando el fetch vivo falle. El peor escenario posible es una tienda impecable con todos los contadores en cero.

Conclusión

Un posteo publicado en dev.to dejó una verdad incómoda sobre la mesa: una plataforma pausada por facturación, cuatro subsistemas caídos en simultáneo, seiscientas veintitrés rutas fingiendo salud y cero alertas en cuatro horas. Lo valioso del relato es que no se queda en la queja. Propone el chequeo de dos líneas (consultar el endpoint de listados y exigir conteo mayor a cero) y un fallback con los datos del build para que el cliente jamás vea ceros.

Si administrás sitios con datos vivos, hacé hoy dos cosas: agregá esa aserción a tu monitoreo y simulá una caída de API para ver qué muestra tu frontend cuando el backend desaparece. La verdad es que prefiero que lo descubra mi chequeo sintético un martes a la tarde, antes que mi cliente un viernes con ganas de reservar.

Fuentes

Te puede interesar...