This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Sunday, 28 December 2025
HTTP no evolucionó. forzada cambiar por la física, la latencia y el mal uso.
Cada versión existe porque la anterior golpeó una restricción dura. Si usted entiende esas restricciones, usted entiende por qué la web funciona como lo hace - y por qué tantas "mejores prácticas" son realmente soluciones para las limitaciones del protocolo que hemos estado arrastrando durante treinta años.
He estado construyendo aplicaciones web desde 1997. He depurado HTTP/1.0 tormentas de conexión, he visto navegadores abrir seis conexiones por host como una "característica", maldecido en HTTP/2 TCP de bloqueo de cabeza de línea en redes móviles, y finalmente he visto HTTP/3 admitir lo que sabíamos todo el tiempo: la red es el problema.
Esto no es un tutorial de protocolo, es la historia de cómo llegamos aquí.
HTTP/1.0 fue diseñado en 1996 para un mundo que ya no existe. Para entender por qué funcionó, es necesario entender lo que "la web" significaba en 1996:
En este mundo, el cuello de botella era ancho de bandaUna página de 50KB tardó 15 segundos en descargarse en el dialup. ¿A quién le importaba un apretón de manos extra de 200ms?
Para qué se optimizó HTTP/1.0:
GET /index.html HTTP/1.0
Host: example.com
HTTP/1.0 200 OK
Content-Type: text/html
<html>...
Simple. Elegante. Perfecto para 1996. Y completamente inutilizable para cualquier cosa más allá de la recuperación de documentos.
Luego la telaraña cambió, rápido.
En 1998, las páginas no eran sólo documentos. Tenían hojas de estilos, JavaScript, múltiples imágenes. Una sola página podría necesitar 20-30 recursos separados.
Cada solicitud requiere:
Una página con 20 recursos significa 20 apretones de manos TCP. En una conexión de latencia de 200 ms (todavía común), eso es 4 segundos de solo apretando la mano antes de que se transfiera cualquier contenido.
La suposición fundamental de HTTP/1.0:
El tiempo era barato.
En 1996, fue. Bandwidth era el cuello de botella. En 1999, el ancho de banda estaba mejorando, pero La latencia no era - y de repente esos viajes de ida y vuelta importaron.
HTTP/1.0 fue diseñado para documentos. La web se había convertido en una plataforma de aplicaciones. Algo tenía que dar.
HTTP/1.1 llegó en 1997, justo cuando la web estaba explotando. El boom de dotcom estaba comenzando. Cada negocio necesitaba un sitio web. Las páginas web se estaban volviendo complejas - tablas para el diseño, JavaScript para la interactividad, imágenes en todas partes.
La presión era clara: conexión-por-solicitud estaba matando el rendimiento. Pero rediseñar completamente HTTP no era una opción. De eso dependía ya demasiada infraestructura. La solución tenía que ser compatible con el pasado.
Lo que cambió:
Connection: keep-alive por defecto) - reutilizar la conexión TCPCache-Control, ETag, solicitudes condicionales)Lo que no cambió:
GET /page.html HTTP/1.1
Host: example.com
Connection: keep-alive
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Cache-Control: max-age=3600
...
HTTP/1.1 no resolvió realmente el problema de rendimiento. Simplemente lo movió.
El pipelining fue un fracaso. La especificación permitió enviar múltiples peticiones en una conexión, pero:
Así que los navegadores engañaron. En lugar de arreglar el protocolo, trabajaron alrededor de él:
static1.example.com, static2.example.com) para multiplicar las conexionesNada de esto era el protocolo que funcionaba como estaba diseñado. Era todo el ecosistema compensando la limitación fundamental de HTTP/1.1.
HTTP/1.1 escalado por el engaño, no por la fijación del modelo.
HTTP/1.1 trabajado lo suficientemente bien. No porque fuera bueno, sino porque el medio ambiente compensaba:
El protocolo aún estaba roto, tuvimos suerte de que el mundo lo escondiera.
Esas seis conexiones por anfitrión no eran gratuitas:
La web se hizo más rápida en la era HTTP/1.1. Pero no por HTTP/1.1. Se hizo más rápida porque:
Estábamos construyendo una plataforma de aplicaciones en un protocolo de recuperación de documentos, el protocolo estaba perdiendo, pero aún no lo sentíamos.
En 2010, el rendimiento web fue una batalla constante contra HTTP mismo.
Las "mejores prácticas" de la época cuentan la historia:
Cada una de ellas es una solución para "HTTP/1.1 no puede manejar muchas peticiones de manera eficiente".
Construí muchas de estas pequeñas herramientas como generadores de sprite, compresores CSS, empezamos a usar compresión de respuesta, etc...
Los navegadores no eran más rápidos porque HTTP mejoraba. Eran más rápidos porque ellos trabajado alrededor de HTTP.
Seis conexiones por host no es una característica. Es un hack. El desgarro de dominio no es una buena práctica. Es una admisión de fracaso.
Pasé años enseñando a desarrolladores a combinar activos, imágenes sprite y recursos críticos en línea. Nada de eso era "buena arquitectura". protocolo de control de daños.
El mito de "HTTP es simple" persistió porque la complejidad estaba oculta en:
HTTP/1.1 funcionó porque todo alrededor Trabajó horas extras para compensar.
Si alguna vez has visto un diagrama de HTTP que no muestra latencia, pérdida o modos de fallo, te está mintiendo. El protocolo es simple. La realidad no lo es.
En 2010, la web se había transformado de nuevo. Dos cambios masivos lo cambiaron todo:
1. El móvil ocurrió. El iPhone lanzado en 2007. En 2012, el tráfico web móvil estaba explotando. De repente los usuarios no estaban en banda ancha por cable - que estaban en 3G, a continuación, 4G, con latencia variable y pérdida frecuente de paquetes.
2. Las aplicaciones web sustituyeron a las páginas web. Gmail. Google Maps. Facebook. Twitter. Estos no eran documentos con enlaces. Eran aplicaciones que necesitaban docenas o cientos de recursos, actualizaciones en tiempo real y respuesta instantánea. El hack "seis conexiones por host" estaba mostrando su edad.
Google sintió este dolor agudamente. Tenían una escala masiva, ingenieros obsesionados con el rendimiento, y los datos para probar HTTP/1.1 fue el cuello de botella. En 2009, comenzaron SPDY - un protocolo experimental que influyó fuertemente HTTP/2 (no idéntico, pero la misma dirección).
Lo que cambió:
┌──────────────────────────────────────────┐
│ Single TCP Connection │
├──────────────────────────────────────────┤
│ Stream 1: GET /page.html │
│ Stream 3: GET /style.css │
│ Stream 5: GET /app.js │
│ Stream 7: GET /logo.png │
│ (all interleaved, no ordering required) │
└──────────────────────────────────────────┘
Esto es lo que debería haber sido HTTP/1.1 pipelining. Las corrientes son independientes. Una respuesta lenta no bloquea a otros. Los encabezados están comprimidos. El protocolo finalmente coincide con cómo usamos la web.
HTTP/2 fue perfecto para la red de banda anchaY en 2015, cuando estandarizó, la banda ancha era omnipresente en el mundo desarrollado.
Lo que mejoró:
Para los usuarios en conexiones cableadas con baja pérdida de paquetes, HTTP/2 fue una verdadera mejora. Los puntos de referencia se veía muy bien. Las métricas mejoraron. Google declaró la victoria.
Pero el mundo ya había avanzado. Móvil era ahora la mayoría del tráfico web.
Y las redes móviles tienen una propiedad fundamental que la banda ancha no: pérdida de paquetes es común e impredecible.
Garantías TCP parto en el orden. Si el paquete 47 se pierde, los paquetes 48-100 esperan hasta que 47 se vuelva a transmitir - incluso si pertenecen a flujos HTTP/2 completamente independientes.
┌──────────────────────────────────────────┐
│ TCP Receive Buffer │
├──────────────────────────────────────────┤
│ [pkt 45][pkt 46][ ? ][pkt 48][pkt 49] │
│ ↑ │
│ Waiting for packet 47 │
│ │
│ Stream 1 data: BLOCKED │
│ Stream 3 data: BLOCKED │
│ Stream 5 data: BLOCKED (has pkt 48-49) │
│ Stream 7 data: BLOCKED │
└──────────────────────────────────────────┘
HTTP/2 resolvió el bloqueo de cabeza de línea en la capa de aplicación. Luego TCP lo reintrodujo en la capa de transporte.
Un paquete perdido para todas las corrientes. En una conexión cableada limpia, la pérdida de paquetes es rara. ¿En redes móviles, WiFi con pérdidas o enlaces congestionados? La pérdida de paquetes es constante. solo conexión (por diseño), un paquete perdido ahora bloquea todo en lugar de solo una de seis conexiones.
Rendimiento HTTP/2:
La ironía: HTTP/2 estaba destinado a solucionar el problema de multiplexación de la web - al igual que el móvil hizo la pérdida imposible de ignorar. Las garantías de TCP lo hicieron peor en el móvil que el protocolo que reemplazó.
Las implementaciones iniciales HTTP/2 mostraron mejoras reales:
¿Todas esas herramientas que construí para 1.1? Todo se fue con HTTP/2, de repente juntando era una cosa BAD. El multiplexado de HTTP/2 era ideal para los activos en el mismo origen, pero no ayudó con las peticiones de origen cruzado. Tuvimos que construir nuevas herramientas para combinarlas (webpack en este sitio, por ejemplo!).
Pero la latencia de cola contó una historia diferente. mediana El P99 empeoró.
Vi esto de primera mano: un cliente habilitado HTTP/2 a través de su CDN y vio latencia móvil P99 aumento Los tickets de soporte provenían de usuarios móviles. Pasamos una semana averiguando que la "mejora" de HTTP/2 estaba empeorando las cosas para la mayoría de su tráfico.
Cuando HTTP/2 funciona, funciona maravillosamente. Cuando un paquete cae en una conexión móvil en el peor momento, todo se congela. Y los usuarios notan que se congela más de lo que notan medianas rápidas.
El problema fundamental:
HTTP/2 asumió que TCP era lo suficientemente bueno.
Para la banda ancha, lo era. Para el móvil, no lo era. Y para el momento en que HTTP/2 estaba estandarizado, el móvil ya estaba ganando. Habíamos empujado tan lejos como TCP podía llevarnos.
Para 2015, las pruebas eran claras: TCP fue el problema.
Google había estado ejecutando QUIC experimentalmente desde 2012. Tenían los datos. En redes móviles, WiFi con pérdidas y conexiones de alta latencia, HTTP/2 sobre TCP estaba fallando en formas que no se podían arreglar sin cambiar la capa de transporte.
Pero no se puede "arreglar TCP". Se implementa en los núcleos del sistema operativo. Se cuece en cada router, firewall y middlebox en Internet. Cambiar TCP significa esperar décadas para que toda la infraestructura de Internet se actualice.
Así que Google hizo algo audaz: Construyeron un nuevo protocolo de transporte encima de UDP.
UDP es "tonto" por diseño - sólo envía paquetes sin garantías. Pero eso es exactamente lo que necesitas si quieres implementar tu propio Semántica de fiabilidad. QUIC implementa las garantías de TCP (confiable, entrega ordenada) pero lo hace por riachuelo en lugar de por conexión.
HTTP/3 (2022) es HTTP sobre QUIC. Es la admisión que necesitábamos para ir por debajo de HTTP para arreglar HTTP.
Lo que cambió:
┌──────────────────────────────────────────┐
│ QUIC Connection │
├──────────────────────────────────────────┤
│ Stream 1: [pkt][pkt][pkt] ← flowing │
│ Stream 3: [pkt][ ? ][pkt] ← waiting │
│ Stream 5: [pkt][pkt][pkt] ← flowing │
│ Stream 7: [pkt][pkt] ← flowing │
│ │
│ Lost packet only affects Stream 3 │
└──────────────────────────────────────────┘
Lo que sigue siendo lo mismo:
HTTP/3 no cambió HTTP. Cambió cómo HTTP sobrevive a la realidad.
QUIC implementa las garantías de fiabilidad de TCP por riachuelo, no por conexión. Esta es la perspicacia clave.
La promesa de TCP: "Cada byte llega en orden." La promesa de QUIC: "Cada byte en esta corriente llega en orden."
Esa distinción es la razón por la que HTTP/3 no colapsa en redes con pérdidas.
Otras características QUIC que solucionan problemas de larga data:
Migración de la conexión:
Phone on WiFi → walks out of range → switches to cellular
TCP: Connection dies. Restart everything.
QUIC: Connection ID maintained. Streams continue.
Esto importa porque los usuarios móviles constantemente Con TCP, cada conexión muere. Con QUIC, la conexión continúa.
Reanudación de 0-RTT:
First connection: Full handshake (1-RTT)
Returning user: Send data immediately (0-RTT)
Cifrado en todas partes:
TCP + TLS: Handshake, then encrypted tunnel
QUIC: Encryption is the handshake (TLS 1.3 integrated)
HTTP/3 está diseñado para el mundo en el que vivimos:
El protocolo finalmente coincide con la realidad de la red. Treinta años después de HTTP/1.0 asumió conexiones cableadas confiables, HTTP/3 reconoce que la fiabilidad es la excepción, no la regla.
HTTP/3 no es gratis:
Pero para aplicaciones móviles, redes poco fiables y servicios sensibles a la latencia, HTTP/3 es la primera versión que coincide con el comportamiento real de las redes.
Cada cambio de versión HTTP ocurrió porque el entorno cambió más rápido que el protocolo.
|---------|-----|-------------|------------|--------------| HTTP/1.0 1996 Dialup, documentos Bandwidth es el cuello de botella Páginas se convirtió en aplicaciones, la latencia importa
HTTP/2 2015-2022 pico de banda ancha, el aumento móvil TCP es lo suficientemente fiable Móvil se convirtió en dominante, TCP falló HTTP/3 2022+ Móvil-primero, global Nada es confiable Todavía desplegándose...
El patrón es claro:
El protocolo sigue siendo empujado más cerca de la red. Cada abstracción que parecía suficiente se despegó cuando el ambiente lo exigió.
Otras observaciones:
A pesar de treinta años de evolución protocolaria:
Las peticiones siguen fallando. Partición de redes. Los servidores se bloquean. Los tiempos de espera ocurren. Su código todavía necesita la lógica de reintentar.
Las redes todavía mienten. 200 OK no significa que la respuesta sea correcta. Conexión cerrada no significa que la petición no haya tenido éxito. Tiempos de espera no significa que el servidor no haya procesado su solicitud.
Caches todavía sirven datos rancios.
Cache-Control es una petición, no una orden. Las proxies hacen lo que quieren. La invalidación de CDN es eventual en el mejor de los casos.
Los clientes aún lo intentan mal. El usuario hace clic en el botón, no pasa nada, hace clic de nuevo. Ahora tienes dos peticiones.
Los desarrolladores siguen malinterpretando la idempotencia. GET debe ser seguro. PUT debe ser idempotente. Mensaje es el salvaje oeste. La mayoría de APIs se equivocan.
// This is still your problem, regardless of HTTP version
public async Task<Result> CreateOrderAsync(Order order)
{
// What happens if this times out?
// Did the server receive it?
// Did it process it?
// Will the client retry?
// Will you create duplicate orders?
// HTTP/3 doesn't save you here.
// Idempotency keys do.
}
Si no entiendes esto, HTTP/3 no te salvará.
Después de construir aplicaciones web en todas estas versiones de protocolo, esto es lo que se quedó:
1. El protocolo no es su capa de fiabilidad.
HTTP te da semántica de petición/respuesta. No garantiza la entrega, corrección o procesamiento exactamente una vez. Ese es tu trabajo.
2. La latencia es el enemigo, no el ancho de banda.
La mayoría de los problemas de rendimiento son de ida y vuelta, no de salida. Reducir las solicitudes importa más que comprimir cargas útiles.
3. Cada "mejor práctica" tiene una fecha de caducidad.
El desmenuzamiento de dominios fue esencial para HTTP/1.1. Es activamente dañino para HTTP/2 (rompió el beneficio de conexión única). "Bundle todo en un archivo" fue gospel; ahora enviar muchos módulos pequeños sobre HTTP/2 o HTTP/3 es a menudo mejor. La táctica cambia. El objetivo (reducir la latencia) sigue siendo el mismo.
4. Medir en redes reales.
Los benchmarks en localhost no prueban nada. Sus usuarios están en redes móviles, WiFi del hotel y conexiones saturadas de cafetería.
5. Las partes aburridas son las que más importan.
Tiempos de espera. Retries. Interruptores de circuitos. Idempotencia. Junta de conexiones. Estos detalles poco glamorosos determinan si su sistema funciona bajo carga.
HTTP no se hizo más rápido porque se hizo más inteligente. Se hizo más rápido porque finalmente admitimos la red era el problema.
Cada versión era correcta para su tiempo:
El error era pensar que cualquiera de ellas eran soluciones permanentes, todas respuestas a presiones ambientales específicas, y cuando el medio ambiente cambiaba, tenía que seguir el protocolo.
Las versiones HTTP no son actualizaciones en el sentido del consumidor. Están optimizadas para diferentes distribuciones de fallos.
Y aún así, después de todo eso, los fundamentos permanecen:
El protocolo evolucionó, los problemas no desaparecieron, sólo se mudaron.
Construir sistemas que sobrevivan a fallas. Probar en redes reales. Comprender que cada versión HTTP es una compensación conformada por su época, no una actualización que obsoleta lo que vino antes.
Eso son treinta años de HTTP. Esa es la web que construimos. Y en otra década, las suposiciones de HTTP/3 probablemente se verán tan fechadas como las de HTTP/1.0 ahora.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.