HTTP/2 vs HTTP/3: What Changed for Developers
Photo by Unsplash on Unsplash
Table of Contents
The Short Version
The versions get discussed as if they change how you write code. They mostly don't. What they change is which old optimisations have quietly become harmful.
That's the practical value in understanding them: not new APIs, but a list of things to stop doing. Concatenating every stylesheet into one file made sense under HTTP/1.1 and actively hurts under HTTP/2.
I'll go through what each version changed and what it means for the way you build pages.
Why HTTP/1.1 Needed Replacing
Every workaround from that era exists because of this limit. Sprite sheets combined images into one file to save requests. Domain sharding spread assets across `static1.example.com` and `static2.example.com` to get more parallel connections. Inlining assets as data URIs avoided a request entirely.
Headers were the other cost. Every request repeated the full set — cookies, user agent, accept headers — as plain text, which on a small asset could exceed the size of the asset itself.
Both problems are what HTTP/2 set out to fix, and it fixed them well enough that the workarounds became liabilities.
What HTTP/2 Actually Fixed
Header compression came with it. HPACK maintains a shared table of previously-sent headers, so repeated fields cost a couple of bytes rather than several hundred. On a page with many small requests this is a bigger win than people expect.
The protocol also went binary rather than text, which mainly matters for parsing efficiency and for the fact that you can no longer read it over telnet.
Server push shipped as a headline feature and then died — browsers removed support because it wasted bandwidth pushing things clients already had. If a tutorial recommends it, that tutorial is out of date. The replacement is `103 Early Hints`, which tells the browser what to preload without sending it blind. Worth knowing if you're auditing HTTP status codes and wondering what the 1xx range is for.
What HTTP/3 Changes
HTTP/3 fixes this by abandoning TCP. It runs on QUIC, which sits on UDP and implements its own reliability and ordering per stream. A lost packet now blocks only the stream it belonged to.
Connection setup also gets faster. QUIC folds the transport and TLS handshakes together, so a new connection takes one round trip instead of two or three, with zero-round-trip resumption for repeat visits.
The underrated feature is connection migration. QUIC identifies connections by an ID rather than by the IP and port pair, so switching from wifi to mobile data doesn't drop the connection. On mobile, that's the difference between a download surviving a walk out of the house and starting over.
What You Should Stop Doing
Stop domain sharding. Splitting assets across subdomains now forces extra connections and extra handshakes, which is precisely backwards. One origin is faster.
Stop inlining images as base64 to save requests. The request is cheap now and inlined assets can't be cached separately, so you pay for them on every page load. Our note on when inlining is still worth it covers the narrow cases that survive.
Stop worrying about the number of requests as a metric in itself. Total bytes and critical path depth are what matter. A page making 80 small parallel requests can easily beat one making 12 large sequential ones.
Do You Need to Do Anything?
If your site sits behind a major CDN, HTTP/3 is probably already on. Check the protocol column in your browser's network panel; it'll show `h2` or `h3` per request.
Self-hosting means enabling it in your server config, and checking that UDP on port 443 isn't blocked by a firewall — that's the single most common reason HTTP/3 silently never activates. Everything still works over HTTP/2, so the failure is invisible unless you look.
One caveat worth knowing: some corporate networks block or throttle UDP, so a fraction of users will always fall back. Design for that rather than assuming QUIC everywhere. MDN's HTTP overview is a good reference for the parts that stayed identical across versions.
What Stayed Exactly the Same
A `GET` is a `GET`. A `404` means the same thing. `Cache-Control` behaves the same way. If you're reasoning about HTTP methods or request headers, none of that knowledge expires with a version bump.
What changed is purely how bytes move between client and server. Framing, compression, connection management — the plumbing.
That separation is the reason HTTP has survived thirty years of change. Applications talk in the same vocabulary while the transport underneath gets rewritten roughly twice a decade, and almost nobody using the web ever notices it happening.
Measuring the Difference
The honest expectation: on a fast, stable connection, HTTP/3 is barely distinguishable from HTTP/2. The gains show up on lossy networks, on mobile and on high-latency links, which is exactly where measurement is hardest and where real users live.
Synthetic tests on a wired connection will show you almost nothing. Field data will show you the tail — the slowest tenth of your users — improving, and that's where the win actually is.
If you're tracking this properly, look at the metrics that reflect network conditions rather than lab timings. Our Core Web Vitals guide covers which of those numbers respond to transport changes and which are dominated by your own JavaScript. The short version: transport upgrades move the numbers that depend on the network, and nothing on the wire will rescue a page that ships half a megabyte of blocking script.
Frequently Asked Questions
What is the main difference between HTTP/2 and HTTP/3?
HTTP/2 multiplexes many streams over one TCP connection, so a single lost packet stalls every stream. HTTP/3 runs on QUIC over UDP instead, giving each stream its own delivery guarantees, so packet loss affects only the stream it hit.
Should I enable HTTP/3 on my site?
Yes if your server or CDN supports it, since it's a config change with no code impact and clients fall back to HTTP/2 automatically. Just check that UDP on port 443 isn't blocked by a firewall, which is the usual reason it silently never activates.
Do I still need to bundle JavaScript with HTTP/2?
Not the way you did under HTTP/1.1. Multiplexing makes parallel requests cheap, so several smaller files download simultaneously and cache independently. Some bundling still helps with compression ratios, but one giant bundle is now a liability.
Is HTTP/2 server push still supported?
No — browsers removed it because it frequently pushed resources clients already had cached. The modern replacement is 103 Early Hints, which tells the browser what to preload without pushing the bytes. Our [status code guide](/blog/http-status-codes-explained-200-301-404-500) covers where the 1xx range fits.
Does HTTP/3 change how I write code?
No. Methods, status codes, headers and caching semantics are identical across HTTP/1.1, HTTP/2 and HTTP/3. Only the transport layer changed, which is why upgrading is a deployment decision rather than a development one.
Try ToolsFuel
23+ free online tools for developers, designers, and everyone. No signup required.
Browse All Tools