Saltar al contenido

HTTP/3 y QUIC: qué deben saber los ingenieros backend

HTTP/3 reemplaza TCP por QUIC sobre UDP y elimina el head-of-line blocking en la capa de transporte: esto es lo que cambia para tus servicios.

5 min de lectura
Comparación en forma de diagrama de las pilas de protocolos HTTP/1.1, HTTP/2 y HTTP/3 ejecutándose sobre TCP frente a QUIC sobre UDP

La mayoría de los ingenieros backend tratan HTTP/3 como una casilla que marca el CDN — algo que Cloudflare o Fastly activan y en lo que nunca vuelves a pensar. Eso es cierto hasta que te toca depurar un pico de latencia que solo ocurre en redes móviles, o un load balancer que descarta tráfico UDP en silencio y obliga a todos los clientes a volver a HTTP/1.1. HTTP/3 no es solo un salto de versión. Reemplaza TCP por QUIC, un protocolo de transporte construido sobre UDP, y ese cambio repercute en el manejo de conexiones, los reintentos y la observabilidad de formas que HTTP/2 nunca tocó.

El problema que HTTP/2 nunca resolvió

HTTP/2 introdujo la multiplexación — múltiples streams lógicos sobre una única conexión TCP — para arreglar el head-of-line blocking de HTTP/1.1 en la capa de aplicación. Pero TCP en sí mismo es un único flujo de bytes ordenado. Si se pierde un paquete, TCP retiene todos los streams de esa conexión hasta que llega la retransmisión, incluso si el paquete perdido pertenecía a una request que ya nadie está esperando.

texttext
HTTP/1.1: 6 conexiones TCP en paralelo, sin multiplexación
HTTP/2:   1 conexión TCP, streams multiplexados
          -> la pérdida de un paquete bloquea TODOS los streams (head-of-line blocking de TCP)
HTTP/3:   1 conexión QUIC sobre UDP, streams multiplexados
          -> la pérdida de un paquete bloquea SOLO el stream afectado

Esta es la idea central: HTTP/2 movió el head-of-line blocking una capa más arriba en lugar de eliminarlo. QUIC lo elimina en la capa de transporte al darle a cada stream su propia recuperación de pérdidas independiente, que es justo por lo que el IETF estandarizó HTTP/3 sobre él en vez de volver a apoyarlo sobre TCP.

Lo que QUIC realmente cambia

Hay tres propiedades que importan a los ingenieros backend, en orden de impacto práctico:

PropiedadTCP + TLSQUIC
HandshakeTCP SYN + TLS 1.3 (2 RTT)Transporte + criptografía combinados (1 RTT)
ReconexiónHandshake completo de nuevoReanudación 0-RTT
Identidad de conexiónTupla IP + puertoConnection ID, sobrevive a cambios de IP

El connection ID es lo que la gente subestima. Una conexión TCP muere en el momento en que cambia la IP del cliente — pasar de Wi-Fi a datos móviles mata todas las requests en vuelo. Las conexiones QUIC se identifican mediante un connection ID incrustado en el paquete, no por la tupla de red, así que un teléfono puede cambiar de red a mitad de una descarga sin renegociar nada.

Habilitar HTTP/3 en tu edge

La mayoría de los equipos no terminan QUIC ellos mismos — dejan que lo haga un CDN o un reverse proxy, y usan HTTP/2 para el tráfico hacia el origen. Pero si operas tu propio edge con Nginx o Caddy, la diferencia de configuración es pequeña y fácil de arruinar de forma sutil.

nginxnginx
# ❌ HTTP/3 anunciado pero sin fallback — los clientes en redes
# restrictivas que bloquean UDP/443 se quedan sin conexión alguna
server {
    listen 443 quic reuseport;
    ssl_certificate     /etc/ssl/certs/example.com.pem;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    # missing: TCP listener + Alt-Svc header
}
nginxnginx
# ✅ HTTP/3 con fallback a HTTP/2 correcto y header de descubrimiento
server {
    listen 443 ssl;
    listen 443 quic reuseport;
    http2 on;
    http3 on;
 
    ssl_certificate     /etc/ssl/certs/example.com.pem;
    ssl_certificate_key /etc/ssl/private/example.com.key;
 
    # Tells clients that already connected over TCP that QUIC
    # is available, so the *next* connection can use it directly
    add_header Alt-Svc 'h3=":443"; ma=86400';
}

El header Alt-Svc es lo que hace que el descubrimiento funcione en la práctica — la primera request de un navegador a tu dominio sigue yendo por TCP, y solo las conexiones posteriores intentan QUIC directamente, según el flujo de negociación definido en RFC 9114. Nginx documenta el comportamiento de este módulo en su referencia del módulo HTTP/3 si necesitas la lista completa de directivas. Caddy toma un camino más simple y habilita HTTP/3 por defecto en cuanto TLS está configurado, sin un listener quic separado que gestionar.

El problema del bloqueo de UDP

Este es el detalle que realmente cuesta horas de debugging: una porción significativa de redes corporativas, algunos operadores móviles y middleboxes antiguos bloquean o limitan UDP/443 directamente, porque históricamente UDP significaba "esto no es una request web" para las reglas de firewall heredadas. Cuando eso pasa, HTTP/3 no falla de forma ruidosa — el cliente simplemente hace timeout en QUIC y cae de vuelta a TCP en silencio, sumando un round trip completo de latencia antes de que el fallback se active.

jsjavascript
// ❌ Assuming HTTP/3 succeeded because the request eventually completed
const res = await fetch("https://api.example.com/orders");
// no visibility into which protocol actually served this response
 
// ✅ Log the negotiated protocol so fallback rates are observable
const res = await fetch("https://api.example.com/orders");
const timing = performance.getEntriesByName(res.url).at(-1);
console.log("protocol:", timing?.nextHopProtocol); // "h3", "h2", or "http/1.1"
 
// Aggregate nextHopProtocol client-side and ship it to your
// analytics pipeline — a rising http/1.1 fallback rate on a
// specific network segment is your early signal, not a support ticket
!

Si tu tasa de fallback de HTTP/3 a HTTP/2 sube por encima de unos pocos puntos porcentuales en un segmento de red determinado, no lo persigas como si fuera un bug — normalmente es un middlebox bloqueando UDP. Monitoréalo, no intentes forzarlo.

Probarlo sin depender de la telemetría del navegador

No necesitas tráfico de producción para verificar que HTTP/3 realmente se negocia. curl lo soporta directamente cuando está compilado contra una librería TLS con capacidad QUIC:

shbash
# Verify HTTP/3 negotiation explicitly instead of trusting Alt-Svc alone
curl --http3 -v https://example.com/ 2>&1 | grep -E "using HTTP/3|ALPN"
 
# Compare latency across protocol versions from the same location
curl -w "%{time_connect} %{time_appconnect} %{time_total}\n" \
  --http3 -o /dev/null -s https://example.com/
curl -w "%{time_connect} %{time_appconnect} %{time_total}\n" \
  --http2 -o /dev/null -s https://example.com/

Ejecuta esto desde distintos puntos de red — banda ancha doméstica, un hotspot móvil y una VPN corporativa — antes de confiar en que tu despliegue de HTTP/3 se comporta igual en todas partes. La referencia de HTTP/3 de MDN es una buena base sobre el estado actual del soporte en navegadores, por si necesitas justificar el esfuerzo ante un equipo escéptico.

Puntos clave

  1. HTTP/3 arregla el head-of-line blocking en la capa de transporte al darle a cada stream su propia recuperación de pérdidas — HTTP/2 solo lo arregló en la capa de aplicación.
  2. El connection ID de QUIC sobrevive a cambios de IP, algo mucho más relevante para clientes móviles que para el tráfico servidor a servidor.
  3. Combina siempre http3 on con un fallback funcional a HTTP/2 o HTTP/1.1 y un header Alt-Svc — nunca asumas que QUIC funciona en silencio.
  4. El bloqueo de UDP/443 en redes corporativas y móviles genera tasas de fallback reales y medibles — instrumenta nextHopProtocol del lado del cliente en vez de adivinar.
  5. Verifica la negociación de protocolo explícitamente con curl --http3 antes de confiar solo en los dashboards del CDN o en el DevTools del navegador.
  6. La mayoría de los equipos deberían dejar que un CDN termine QUIC y mantener el tráfico hacia el origen en HTTP/2 — auto-alojar HTTP/3 vale la pena solo cuando entiendes bien sus modos de fallo.
Wilfredo Rujel

Wilfredo Rujel

Ingeniero de Software Full Stack

Compartir esta publicaciónX