Topic Overview
HTTP/1.1 vs HTTP/2 vs HTTP/3
Compare HTTP versions: HTTP/1.1 (persistent connections), HTTP/2 (multiplexing, header compression), and HTTP/3 (QUIC, UDP-based).
HTTP has evolved through multiple versions, each addressing performance and security limitations of previous versions. Understanding the differences is crucial for building modern web applications.
HTTP/1.1
Released: 1997 Transport: TCP Key Features: Persistent connections, pipelining (limited)
Characteristics
- One request per connection (without pipelining)
- Text-based protocol: Human-readable headers
- No header compression: Headers sent in full
- Head-of-line blocking: One slow request blocks others
- Multiple connections: Browsers open 6-8 connections per domain
Limitations
Connection 1: Request 1 → Response 1
Connection 2: Request 2 → Response 2
Connection 3: Request 3 → Response 3
...
Connection 6: Request 6 → Response 6
Problem: Need multiple TCP connections for parallelism
Head-of-line blocking:
Request 1 (slow) → Blocks Request 2, 3, 4...
HTTP/2
Released: 2015 Transport: TCP Key Features: Multiplexing, header compression, server push
Key Improvements
- Multiplexing: Multiple requests over single connection
- Header Compression (HPACK): Compress headers
- Binary Protocol: More efficient than text
- Server Push: Server can push resources proactively
- Stream Prioritization: Prioritize important resources
Multiplexing
Single TCP Connection:
Stream 1: Request 1 → Response 1
Stream 2: Request 2 → Response 2
Stream 3: Request 3 → Response 3
Stream 4: Request 4 → Response 4
All streams multiplexed over one connection
Benefits:
- Fewer TCP connections
- Better resource utilization
- Reduced latency
Header Compression (HPACK)
HTTP/1.1:
GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0...
Accept: application/json
Cookie: session=abc123...
(Headers sent in full every time)
HTTP/2:
(Headers compressed using HPACK)
(Static table + dynamic table)
(Much smaller header size)
Limitations
- Still uses TCP: Head-of-line blocking at TCP level
- TCP handshake: Still requires 3-way handshake
- TCP congestion control: Can cause delays
HTTP/3
Released: 2022 Transport: QUIC (UDP-based) Key Features: QUIC protocol, connection migration, improved multiplexing
Key Improvements
- QUIC Protocol: UDP-based, eliminates TCP head-of-line blocking
- Built-in encryption: TLS 1.3 integrated
- Connection migration: Survives IP changes
- Faster handshake: 0-RTT or 1-RTT (vs 2-RTT for TCP+TLS)
- Independent streams: Stream blocking doesn't affect others
QUIC Protocol
HTTP/3 over QUIC (UDP):
- Multiple streams over single QUIC connection
- Each stream independent (no head-of-line blocking)
- Built-in encryption (TLS 1.3)
- Connection migration (survives IP changes)
Benefits:
- No TCP head-of-line blocking: Streams are independent
- Faster connection: 0-RTT or 1-RTT handshake
- Better mobile: Handles network changes better
Comparison
| Feature | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Transport | TCP | TCP | QUIC (UDP) |
| Multiplexing | No (needs multiple connections) | Yes (single connection) | Yes (single connection) |
| Header Compression | No | Yes (HPACK) | Yes (QPACK) |
| Head-of-line Blocking | Yes (application level) | Yes (TCP level) | No (streams independent) |
| Server Push | No | Yes | No (replaced by Early Hints) |
| Encryption | Optional (HTTPS) | Optional (HTTPS) | Required (built-in) |
| Connection Migration | No | No | Yes |
| Handshake | TCP (3-RTT) + TLS (2-RTT) = 5-RTT | TCP (3-RTT) + TLS (2-RTT) = 5-RTT | QUIC (0-RTT or 1-RTT) |
Examples
HTTP/1.1 Request
GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: application/json
Accept-Language: en-US,en;q=0.9
Cookie: session=abc123; theme=dark
Connection: keep-alive
Characteristics:
- Text-based, human-readable
- Headers sent in full
- One request per connection (without pipelining)
HTTP/2 Request (Binary)
HTTP/2 uses binary frames:
HEADERS Frame:
Stream ID: 1
Flags: END_HEADERS
Headers: (compressed with HPACK)
:method: GET
:path: /api/users
:scheme: https
:authority: example.com
user-agent: Mozilla/5.0...
accept: application/json
Characteristics:
- Binary protocol (more efficient)
- Headers compressed (HPACK)
- Multiple streams over single connection
HTTP/3 Request (QUIC)
HTTP/3 over QUIC:
QUIC Packet:
Connection ID: 0x1234
Stream ID: 1
Data: (HTTP/3 request)
:method: GET
:path: /api/users
:scheme: https
:authority: example.com
Encrypted with TLS 1.3 (built-in)
Characteristics:
- UDP-based (QUIC)
- Built-in encryption
- Independent streams
Performance Comparison
import time
import requests
def measure_http_performance(url, version='1.1'):
"""Measure HTTP performance"""
start = time.time()
if version == '1.1':
# HTTP/1.1: Multiple connections
with requests.Session() as session:
for i in range(10):
session.get(f"{url}/resource{i}")
elif version == '2':
# HTTP/2: Single connection, multiplexing
import httpx
with httpx.Client(http2=True) as client:
for i in range(10):
client.get(f"{url}/resource{i}")
elif version == '3':
# HTTP/3: QUIC
import httpx
with httpx.Client(http3=True) as client:
for i in range(10):
client.get(f"{url}/resource{i}")
elapsed = time.time() - start
return elapsed
# Results (typical):
# HTTP/1.1: ~2.0s (multiple connections)
# HTTP/2: ~1.2s (multiplexing)
# HTTP/3: ~0.8s (QUIC, no TCP blocking)
Migration Strategy
HTTP/1.1 → HTTP/2
Benefits:
- Multiplexing (single connection)
- Header compression
- Server push (optional)
Considerations:
- Requires HTTPS (most browsers)
- Server must support HTTP/2
- Still has TCP head-of-line blocking
HTTP/2 → HTTP/3
Benefits:
- No TCP head-of-line blocking
- Faster handshake (0-RTT or 1-RTT)
- Better mobile performance
- Connection migration
Considerations:
- Requires QUIC support
- UDP may be blocked by some firewalls
- Newer protocol (less widespread support)
Common Pitfalls
- Not using HTTPS: HTTP/2 requires HTTPS in most browsers. Fix: Always use HTTPS
- Ignoring HTTP/2 server push: Not utilizing server push. Fix: Use server push for critical resources
- Not optimizing for HTTP/2: Still using HTTP/1.1 optimizations (domain sharding). Fix: Remove unnecessary optimizations
- Firewall blocking UDP: HTTP/3 uses UDP, may be blocked. Fix: Ensure UDP port 443 is open
- Not monitoring performance: Not measuring actual improvements. Fix: Monitor metrics, A/B test
- Assuming HTTP/3 is always faster: Depends on network conditions. Fix: Test in your environment
Interview Questions
Beginner
Q: What are the main differences between HTTP/1.1, HTTP/2, and HTTP/3?
A:
HTTP/1.1 (1997):
- Transport: TCP
- Multiplexing: No (needs multiple connections)
- Header compression: No
- Limitations: Head-of-line blocking, text-based protocol
HTTP/2 (2015):
- Transport: TCP
- Multiplexing: Yes (single connection, multiple streams)
- Header compression: Yes (HPACK)
- Improvements: Binary protocol, server push, stream prioritization
- Limitation: Still has TCP head-of-line blocking
HTTP/3 (2022):
- Transport: QUIC (UDP-based)
- Multiplexing: Yes (single connection, independent streams)
- Header compression: Yes (QPACK)
- Improvements: No TCP blocking, built-in encryption, connection migration
- Benefits: Faster handshake, better mobile performance
Key Differences:
- HTTP/1.1: Multiple connections, text-based
- HTTP/2: Single connection, multiplexing, binary
- HTTP/3: QUIC, UDP-based, no TCP blocking
Intermediate
Q: Explain how HTTP/2 multiplexing works and why it's better than HTTP/1.1.
A:
HTTP/1.1 Problem:
Connection 1: Request 1 → (wait) → Response 1
Connection 2: Request 2 → (wait) → Response 2
Connection 3: Request 3 → (wait) → Response 3
...
Connection 6: Request 6 → (wait) → Response 6
Issues:
- Need 6 TCP connections
- Each connection has overhead
- Head-of-line blocking (slow request blocks connection)
HTTP/2 Solution:
Single TCP Connection:
Stream 1: Request 1 → Response 1
Stream 2: Request 2 → Response 2
Stream 3: Request 3 → Response 3
Stream 4: Request 4 → Response 4
Stream 5: Request 5 → Response 5
Stream 6: Request 6 → Response 6
All streams multiplexed over one connection
How it works:
- Single TCP connection: All requests use one connection
- Streams: Each request/response is a stream with unique ID
- Frames: Data sent in binary frames (HEADERS, DATA, etc.)
- Interleaving: Frames from different streams interleaved
- Reassembly: Receiver reassembles frames by stream ID
Benefits:
- Fewer connections: One connection vs multiple
- Better resource utilization: Single connection more efficient
- Reduced latency: No connection establishment overhead
- Header compression: HPACK reduces header size
Example:
HTTP/1.1: 6 connections × 3-way handshake = 18 packets
HTTP/2: 1 connection × 3-way handshake = 3 packets
Senior
Q: Design a web application that supports HTTP/1.1, HTTP/2, and HTTP/3. How do you handle protocol negotiation, fallback, and optimize for each version?
A:
class MultiProtocolWebServer {
private http1Server: HTTP1Server;
private http2Server: HTTP2Server;
private http3Server: HTTP3Server;
private protocolNegotiator: ProtocolNegotiator;
constructor() {
this.http1Server = new HTTP1Server({ port: 80 });
this.http2Server = new HTTP2Server({ port: 443 });
this.http3Server = new HTTP3Server({ port: 443 });
this.protocolNegotiator = new ProtocolNegotiator();
}
// 1. Protocol Negotiation
async handleConnection(connection: Connection): Promise<void> {
// ALPN (Application-Layer Protocol Negotiation)
const supportedProtocols = await connection.getALPN();
if (supportedProtocols.includes('h3')) {
// HTTP/3 (QUIC)
return await this.http3Server.handle(connection);
} else if (supportedProtocols.includes('h2')) {
// HTTP/2
return await this.http2Server.handle(connection);
} else {
// HTTP/1.1 (fallback)
return await this.http1Server.handle(connection);
}
}
// 2. HTTP/1.1 Optimization
class HTTP1Server {
async handleRequest(request: Request): Promise<Response> {
// Domain sharding (if needed)
// Connection keep-alive
// Resource bundling
return await this.processRequest(request);
}
}
// 3. HTTP/2 Optimization
class HTTP2Server {
async handleRequest(request: Request): Promise<Response> {
// Multiplexing (automatic)
// Header compression (HPACK)
// Server push for critical resources
// Push critical resources
if (request.path === '/') {
await this.pushResource('/styles.css');
await this.pushResource('/app.js');
}
return await this.processRequest(request);
}
async pushResource(path: string): Promise<void> {
// Server push
await this.stream.pushPromise({
':path': path,
':method': 'GET'
});
}
}
// 4. HTTP/3 Optimization
class HTTP3Server {
async handleRequest(request: Request): Promise<Response> {
// QUIC (UDP-based)
// Independent streams (no blocking)
// Built-in encryption
// Connection migration
return await this.processRequest(request);
}
}
// 5. Fallback Strategy
class ProtocolNegotiator {
async negotiate(clientCapabilities: ClientCapabilities): Promise<Protocol> {
// Try HTTP/3 first
if (clientCapabilities.supportsHTTP3 && this.supportsHTTP3()) {
return 'HTTP/3';
}
// Fallback to HTTP/2
if (clientCapabilities.supportsHTTP2 && this.supportsHTTP2()) {
return 'HTTP/2';
}
// Fallback to HTTP/1.1
return 'HTTP/1.1';
}
}
// 6. Performance Monitoring
async getMetrics(): Promise<Metrics> {
return {
http1: {
connections: await this.http1Server.getConnectionCount(),
avgLatency: await this.http1Server.getAvgLatency()
},
http2: {
streams: await this.http2Server.getStreamCount(),
avgLatency: await this.http2Server.getAvgLatency(),
pushCount: await this.http2Server.getPushCount()
},
http3: {
connections: await this.http3Server.getConnectionCount(),
avgLatency: await this.http3Server.getAvgLatency(),
migrationCount: await this.http3Server.getMigrationCount()
}
};
}
}
Features:
- Protocol negotiation: ALPN for automatic selection
- Fallback strategy: HTTP/3 → HTTP/2 → HTTP/1.1
- Optimization per version: Different strategies for each
- Server push: HTTP/2 server push for critical resources
- Monitoring: Track performance per protocol
- Graceful degradation: Fallback to older versions
Key Takeaways
- HTTP/1.1: Multiple connections, text-based, no multiplexing, head-of-line blocking
- HTTP/2: Single connection, multiplexing, header compression, binary protocol, still has TCP blocking
- HTTP/3: QUIC (UDP), independent streams, no TCP blocking, built-in encryption, connection migration
- Multiplexing: HTTP/2 allows multiple requests over single connection
- Header compression: HPACK (HTTP/2), QPACK (HTTP/3) reduce header size
- Protocol negotiation: ALPN for automatic protocol selection
- Migration strategy: Support multiple versions, fallback gracefully
- Best practices: Use HTTPS, optimize for each version, monitor performance