Short answer: With HTTP/2 and HTTP/3, the raw number of requests matters much less than it used to, because browsers can fetch many files over one connection at the same time. What still slows pages down is requests that block rendering, chains where one file has to load before the next is even discovered, and requests to many different domains, each needing its own connection. Focus on those, and on removing files a page does not use, rather than on merging everything into one file.
Why “reduce HTTP requests” became a rule
For many years “make fewer HTTP requests” was the first rule of web performance. It came from HTTP/1.1, in which a browser could only send one request at a time per connection and opened only a handful of connections per domain, typically six. A page with 80 files had to queue them. Every extra file meant more waiting.
Developers responded with a set of techniques: combining all CSS into one file, all JavaScript into another, merging icons into image sprites, and spreading files across several subdomains (“domain sharding”) to get more parallel connections.
HTTP/2, now supported by practically every browser and web server, changed the underlying problem. It sends many requests and responses over a single connection at the same time, with compressed headers. HTTP/3 does the same over a newer transport that copes better with lost packets on mobile networks. Our comparison of HTTP/2 and HTTP/3 explains the differences in more detail.
So is the old rule dead? Not entirely. It is just aimed at the wrong thing if you apply it literally.
What still makes requests expensive
Even over HTTP/2, a request is not free. The costs that remain are different from the old ones.
- Render-blocking requests. CSS files in the head and synchronous scripts stop the browser from showing the page until they arrive. Five blocking stylesheets are worse than one, not because of the count itself, but because the page waits for the slowest of them.
- Request chains. When file A loads file B, which loads file C, the browser cannot request C until B has arrived. A font referenced inside a CSS file imported by another CSS file is a classic three-step chain. Each step adds at least one round trip.
- New origins. Every different domain, whether a font service, an analytics tool, a chat widget or a CDN for one library, needs its own DNS lookup, connection and TLS handshake before the first byte arrives. On mobile that can easily be several hundred milliseconds per origin.
- Main-thread work. Every script must be parsed and executed. Ten small scripts that each do a little can add up to long tasks that delay interaction.
- Useless requests. Files for features the page does not use, tracking pixels nobody reads, and requests that end in 404 errors all consume bandwidth and attention for nothing.
How to see your requests
Before changing anything, look at what the page actually requests.
- Open Chrome or Firefox developer tools, go to the Network panel, tick “Disable cache” and reload.
- Look at the total number of requests and the transferred size at the bottom of the panel.
- Sort by domain to see how many different origins the page contacts, and which files come from each.
- Look at the waterfall. Long staircases, where each bar starts only after the previous one ends, are chains.
- Filter by status to find any 404 or 3xx responses among the page’s own resources.
- Repeat on a typical inner page, not only the home page. Templates often load very different sets of files.
In a PageSpeed Insights or Lighthouse report, the diagnostics “Avoid chaining critical requests”, “Reduce the impact of third-party code” and “Eliminate render-blocking resources” point to the same problems in a more structured way.
Old advice vs current practice
| Old technique | Under HTTP/2 and HTTP/3 | What to do today |
|---|---|---|
| Combine all CSS and JS into one file | Less needed; one huge file also caches poorly | Bundle sensibly; split by page or feature |
| Image sprites for icons | Rarely worth the complexity | Inline small SVG icons or use a single SVG sprite |
| Domain sharding | Harmful: extra connections, no gain | Serve your own files from one origin |
| Inline everything small | Useful for critical CSS; bad for cacheable assets | Inline only what the first view needs |
| Fewer requests at any cost | Misleading goal | Fewer blocking, chained and third-party requests |
Cut the requests that matter
These changes usually give the biggest improvement for the least effort, roughly in order.
Remove what the page does not use
The cheapest request is the one that never happens. On many sites, especially WordPress sites, plugins load their CSS and JavaScript on every page even though the feature, such as a contact form, slider or booking widget, appears on only one. Unload those assets on pages that do not need them, either with the plugin’s own settings or with an asset management tool, and delete plugins that are no longer used at all.
Shorten request chains
Avoid CSS @import, which forces the browser to download one stylesheet before discovering the next. Reference critical files directly in the HTML. Where a font or hero image is discovered late, a preload hint lets the browser start it early; the guide to preload, preconnect and prefetch explains when each hint helps.
Reduce the number of origins
Self-host fonts and small libraries instead of loading them from separate public CDNs. Question every third-party tool: is anyone reading that heatmap or using that chat widget? For the ones you keep, load them after the page is usable. Our article on how third-party scripts slow down your website shows how to audit them.
Trim fonts
Each font weight and style is usually a separate file. A design that uses regular, italic, medium, semibold and bold in two families can mean ten font requests. Two or three weights, or a single variable font file, usually look the same to visitors. See web font performance for loading strategies.
Defer below-the-fold images and embeds
Images further down a long page, maps and video players do not need to load before the visitor scrolls. Native lazy loading with loading="lazy" delays them, but never apply it to the main image at the top. The guide on lazy loading images covers where it helps and where it hurts.
Fix broken and redirected assets
Requests for files that no longer exist, or that redirect from HTTP to HTTPS or to a new path, add wasted round trips. Update the references so every asset loads directly with a 200 response.
When bundling still helps
Combining files is not wrong; it is just no longer automatic. It still makes sense when:
- A page loads dozens of tiny JavaScript modules, each of which is discovered only after the previous one is parsed.
- The site still serves some visitors over HTTP/1.1, for example through an old proxy or server configuration.
- Several small CSS files are all needed for the first view anyway.
It makes less sense when it creates one very large file that changes with every small edit, forcing returning visitors to download everything again, or when it packs code for every page into one bundle that each page mostly ignores.
A realistic target
There is no universal “good” number of requests. A simple article page may need 20; a product page with a gallery, reviews and a payment widget may reasonably need 80. More useful targets are:
- No more than a few render-blocking files in the head.
- No critical chain longer than two or three steps.
- As few third-party origins as your business really needs before the page is usable.
- Zero 404s and zero redirects among the page’s own assets.
- Good Core Web Vitals in field data, which is what visitors actually experience.
How Site AI Audit helps
Site AI Audit measures your mobile speed and Core Web Vitals with Google PageSpeed, and checks server response time, compression and page weight, together with SEO, SSL, security headers and e-mail authentication. Each finding is explained in plain words and ranked by impact, so you can tell whether request problems are worth your time. Plans with re-checks are on the pricing page.
Related reading
- Page Weight: How Heavy Is Too Heavy and How to Trim It
- How to Eliminate Render-Blocking Resources on Your Website
- Minifying CSS and JavaScript: What It Really Saves You
The bottom line
Counting requests is a rough guide, not a goal. With modern protocols, a page with many small, well-ordered requests can be faster than one with a few huge, blocking files. Remove what pages do not use, shorten chains, cut unnecessary third-party origins and fonts, lazy-load what is below the fold, and fix broken assets. Then judge the result by Core Web Vitals, not by the request counter.
FAQ
Does the number of HTTP requests still matter?
Less than it did under HTTP/1.1. With HTTP/2 and HTTP/3, many requests share one connection. Blocking requests, request chains and connections to many different domains still slow pages down.
Should I combine all my CSS and JavaScript files?
Not automatically. Combining can help when there are many tiny files, but one huge bundle caches poorly and loads code that pages do not use. Split files sensibly by page or feature.
Is domain sharding still useful?
No. With HTTP/2 it adds extra DNS lookups and connections without any benefit. Serve your own assets from as few origins as possible.
How many HTTP requests is too many?
There is no fixed limit. Focus on few render-blocking files, short critical chains, few third-party origins and good Core Web Vitals rather than on a specific request count.
Why does my WordPress site make so many requests?
Plugins often load their CSS and JavaScript on every page, even where their feature is not used. Removing unused plugins and unloading assets per page usually cuts requests significantly.



