HTTP/2 represents a major revision of the HTTP protocol, bringing significant performance improvements. Let's explore the key differences visually.
This article assumes basic familiarity with HTTP concepts like requests, responses, and headers.
In HTTP/1.1, requests are processed sequentially over a single connection:
sequenceDiagram
participant Client
participant Server
Client->>Server: GET /index.html
Server->>Client: 200 OK (HTML)
Client->>Server: GET /style.css
Server->>Client: 200 OK (CSS)
Client->>Server: GET /script.js
Server->>Client: 200 OK (JS)
Note over Client,Server: Each request waits for previous response
Problem: Head-of-line blocking - each request must wait for the previous one to complete.
HTTP/2 allows multiple requests simultaneously over a single connection:
sequenceDiagram
participant Client
participant Server
par Parallel Requests
Client->>Server: Stream 1: GET /index.html
Client->>Server: Stream 3: GET /style.css
Client->>Server: Stream 5: GET /script.js
end
par Parallel Responses
Server->>Client: Stream 1: 200 OK (HTML)
Server->>Client: Stream 3: 200 OK (CSS)
Server->>Client: Stream 5: 200 OK (JS)
end
Note over Client,Server: Multiple streams over single connection
Benefit: No head-of-line blocking at the application layer.
graph TD
A[Browser] -->|Connection 1| B[Server]
A -->|Connection 2| B
A -->|Connection 3| B
A -->|Connection 4| B
A -->|Connection 5| B
A -->|Connection 6| B
style A fill:#4A90E2,stroke:#2E5C8A,color:#fff
style B fill:#50C878,stroke:#2E7D4E,color:#fff
Typical behavior: Browsers open 6-8 parallel connections per domain to work around the sequential limitation.
graph TD
A[Browser] -->|Single Connection| B[Server]
B -->|Stream 1: HTML| A
B -->|Stream 2: CSS| A
B -->|Stream 3: JS| A
B -->|Stream 4: Image 1| A
B -->|Stream 5: Image 2| A
B -->|Stream N: ...| A
style A fill:#4A90E2,stroke:#2E5C8A,color:#fff
style B fill:#50C878,stroke:#2E7D4E,color:#fff
Improvement: All resources transfer over a single TCP connection with multiple virtual streams.
HTTP/2 introduces a binary framing layer that transforms how data is exchanged:
graph LR
A[HTTP/1.1<br/>Text Protocol] --> B[Plain Text]
C[HTTP/2<br/>Binary Protocol] --> D[Binary Frames]
D --> E[HEADERS Frame]
D --> F[DATA Frame]
D --> G[SETTINGS Frame]
style A fill:#E74C3C,stroke:#C0392B,color:#fff
style C fill:#50C878,stroke:#2E7D4E,color:#fff
style B fill:#95A5A6
style D fill:#3498DB
style E fill:#9B59B6,color:#fff
style F fill:#9B59B6,color:#fff
style G fill:#9B59B6,color:#fff
HTTP/2 enables servers to proactively send resources:
sequenceDiagram
participant Client
participant Server
Client->>Server: GET /index.html
Note over Server: Server knows client needs these
Server->>Client: PUSH_PROMISE: /style.css
Server->>Client: PUSH_PROMISE: /script.js
Server->>Client: 200 OK: /index.html
Server->>Client: 200 OK: /style.css
Server->>Client: 200 OK: /script.js
Note over Client: Resources already in cache!
Benefit: Reduced latency by eliminating round trips for critical resources.
graph TD
subgraph V1 [HTTP/1.1 Headers]
A[Per Request] --> B["Full Text Headers<br/>~800 bytes"]
end
subgraph V2 [HTTP/2 Headers]
C[HPACK Compression] --> D["Compressed Headers<br/>~100 bytes"]
D -->|Static Table| E[Common Headers]
D -->|Dynamic Table| F[Previous Headers]
end
style A fill:#E74C3C,stroke:#C0392B,color:#fff
style C fill:#50C878,stroke:#2E7D4E,color:#fff
style B fill:#95A5A6
style D fill:#3498DB,color:#fff
| Feature | HTTP/1.1 | HTTP/2 |
|---|---|---|
| Transport | Text-based | Binary frames |
| Multiplexing | ❌ No | ✅ Yes |
| Header Compression | ❌ No | ✅ HPACK |
| Server Push | ❌ No | ✅ Yes |
| Stream Priority | ❌ No | ✅ Yes |
| Connections | 6-8 per domain | 1 per domain |
graph LR
A[Same Website] --> B[HTTP/1.1]
A --> C[HTTP/2]
B --> D[Load Time: 3.2s]
B --> E[Requests: 42]
B --> F[Connections: 6]
C --> G[Load Time: 1.8s<br/>44% faster]
C --> H[Requests: 42]
C --> I[Connections: 1]
style A fill:#95A5A6
style B fill:#E74C3C,stroke:#C0392B,color:#fff
style C fill:#50C878,stroke:#2E7D4E,color:#fff
style G fill:#F39C12,color:#fff
HTTP/2 is now supported by all major browsers and servers. If you're not using it yet, it's time to upgrade!
const http2 = require('node:http2');
const fs = require('node:fs');
const server = http2.createSecureServer({
key: fs.readFileSync('localhost-privkey.pem'),
cert: fs.readFileSync('localhost-cert.pem')
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200
});
stream.end('<h1>Hello HTTP/2</h1>');
});
server.listen(8443);System Architecture Group
Experts in distributed systems, scalability, and high-performance computing.
A deep dive into how PostgreSQL's query planner works, from parsing SQL to generating optimal execution plans. Understand EXPLAIN output like never before.
How to run schema migrations on billion-row tables without any downtime. Covers expand-contract pattern, online DDL tools, and rollback strategies.
Why REST is failing your microservices. A gentle introduction to defining services with .proto files.