Why did you click the "Speed Test" button and your site is still slow?
Run a speed test on your website right now. You'll probably see a score between 40 and 70 out of 100, and the report will say "compress images" or "defer JavaScript." These recommendations are correct, but their order is wrong. You're attacking links in the chain that aren't the bottleneck at all.
Website speed is a chain, not a single number. From the moment a user types the address to the moment the page fully renders, there are at least seven links: DNS, TCP/TLS connection, HTML delivery, CSS loading, JavaScript execution, fetching images and fonts, and finally the final render. Each link takes a few milliseconds, but it's their sum that creates the user experience.
Most site administrators only see the last two links and ignore the rest. This is a costly mistake.
The Speed Chain: How Many Milliseconds Does Each Link Take?
Let's talk with real numbers. These figures are averages I've seen in practice, not lab numbers:
| Link | Typical Time | Optimal Time |
|---|---|---|
| DNS Lookup | 20–80 ms | 5–15 ms |
| TCP + TLS Handshake | 50–150 ms | 30–60 ms |
| TTFB (Time to First Byte) | 300–800 ms | 100–200 ms |
| CSS Loading | 100–400 ms | 50–100 ms |
| JavaScript Execution | 300–1500 ms | 100–300 ms |
| Images and Fonts | 500–2000 ms | 200–500 ms |
| Final Render | 100–300 ms | 50–100 ms |
The sum of these figures in the worst case reaches 3.5 seconds. Google says 53% of mobile visits are abandoned when loading takes more than 3 seconds. Take this number seriously.
First Link: DNS — Where Everyone Forgets
Before even a single byte of your site is sent, the browser must convert the domain address to an IP. If your DNS has a high TTL (Time To Live) and weak Nameservers, this link alone wastes 80 milliseconds.
To check, use the command dig +trace example.com and see how long each step takes. If the response from your Nameserver is above 50 milliseconds, you have a problem. Solution: Choose DNS with Anycast and set the TTL for main records to 300 seconds, not 86400.
Second Link: TTFB — Where Hosting Makes the Decision
TTFB is the interval between the browser's request and receiving the first byte of the response. This number directly depends on your processor power, disk type, and web server configuration. If your TTFB is above 300 milliseconds, the problem isn't your code; it's the infrastructure.
Measure it precisely with curl -w "TTFB: %{time_starttransfer}s\n" -o /dev/null https://example.com. If the number is high, first check PHP-FPM: set pm.max_children based on the memory of each process. Simple formula: total memory divided by memory per PHP process. If each process consumes 128MB and the server has 4GB RAM, then pm.max_children = 30.
This is where people make mistakes: many, upon seeing high TTFB, go straight to image compression. Result? Zero. Images load after TTFB and have no effect on it. Fix the infrastructure first, then move on to optimizing assets.
Prioritization Based on Cost-to-Effect Ratio
You have limited time and budget. Every action you take should have the maximum effect with the minimum cost. I recommend this order:
- Enable HTTP/2 and Brotli — One change in web server settings, 20 to 30 percent reduction in transfer size. Cost: 15 minutes.
- Browser caching with Cache-Control — For returning visitors, 50% reduction in loading time. Cost: 10 minutes.
- Image optimization with WebP — 30 to 70 percent reduction in image size without noticeable quality loss. Cost: one hour.
- Removing unnecessary JavaScript — The biggest possible win, but the most expensive. Requires code review.
This order is based on the fact that 80% of speed improvement comes from 20% of the effort. Save the hard tasks for last.
Browser Caching: The Easiest Win You're Not Taking
Setting cache headers in nginx is just a few lines:
location ~* \.(jpg|jpeg|png|webp|svg|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
With this setting, the user's browser keeps static files for 30 days and doesn't send any request for subsequent visits. Result: the second and third page loads are almost instant.
Common problem: after changing CSS or JS, users see the old version. The solution is to add a file hash to its name: style.a3f2b9.css. With each change, the name changes and the browser is forced to fetch the new version.
WebP Images: Without Noticeable Quality Loss
The WebP format is on average 30% lighter than JPEG and 50% lighter than PNG. Conversion is done with the following command:
cwebp -q 80 input.jpg -o output.webp
Quality 80 is usually visually indistinguishable from the original. For product images, choose quality 85. For banners and backgrounds, 75 is sufficient.
If your site is WordPress, plugins like ShortPixel or Imagify do this automatically. But if you have a custom site, you need to set up a CDN or your own conversion script.
JavaScript: The Silent Killer of Core Web Vitals
JavaScript is the biggest threat to Core Web Vitals metrics, especially LCP (Largest Contentful Paint) and INP (Interaction to Next Paint). Every extra script increases execution time, and every heavy library consumes more memory.
The first step is measurement. In Chrome DevTools, open the Performance tab and record the page load. See which script takes the most time. Usually the culprits are old jQuery libraries, sliders, and analytics scripts.
Practical solution: Load unnecessary scripts with defer or async. The difference matters: defer preserves execution order, async doesn't. For independent scripts, async is better. For dependent scripts, defer.
A rule of thumb: if a script isn't needed for the initial render of the page, it shouldn't be in the main HTML. Load it with defer or execute it conditionally after user interaction.
Fonts: The Hidden 200 Milliseconds
Web fonts are usually overlooked, but each font file can be 100 to 300 kilobytes. If you use three fonts with four different weights, you've added the equivalent of a large image.
Solution: Use font-display: swap so text displays with the default font and the web font replaces it later. Also, only load the weights you need. If you only use Bold and Regular, remove the Italic and Black files.
Correct Measurement; Half the Cure
Before any action, record a baseline. Use PageSpeed Insights and note the LCP, INP, and CLS numbers. After each change, measure again. If the number didn't improve, your change was ineffective.
Another free tool is WebPageTest, which shows the complete loading waterfall. This tool precisely identifies which request is the bottleneck and how long it takes.
For continuous monitoring, you can use monitoring tools. If your site is on ServerNet's SEO services infrastructure, the technical team can directly help you with speed optimization.
This Is Where They Go Wrong: Optimization Without Measurement
The most common mistake I've seen: a site administrator who spent a week compressing images, but their site's TTFB was 800 milliseconds and they felt no change in speed. Why? Because the main bottleneck was the infrastructure, not the images.
The sign of this mistake: the PageSpeed report improved, but users still complain about the site being slow. If you're experiencing this situation, first measure TTFB. If it's above 300 milliseconds, the problem is with the hosting or web server settings, and no amount of frontend optimization will solve it.
Solution: Upgrade your hosting or migrate to a server with NVMe and PHP 8.2+. The difference between shared hosting and a dedicated server in TTFB is usually 3 to 5 times.
Frequently Asked Questions
Why is my website speed low in PageSpeed Insights but seems fast in practice?
PageSpeed Insights uses a simulated device with a 4G connection and weak hardware. This scenario is deliberately strict to show the worst case. If your users mostly visit with high-speed internet and modern devices, their real experience is better than the reported number. But this isn't an excuse to ignore the report; Google uses the same metric for ranking.
What's the difference between TTFB and LCP, and which is more important?
TTFB is the time until the first byte is received from the server, and LCP is the time until the largest element of the page is displayed. TTFB is a subset of LCP; if TTFB is high, LCP will also be high. But LCP can be high even with low TTFB if the main image loads late. For optimization, first get TTFB below 200 milliseconds, then move on to LCP.
Is using a CDN necessary for an Iranian website?
If your audience is inside Iran, a foreign CDN not only doesn't help but actually reduces speed. Physical distance and sanctions increase latency. For domestic sites, choosing hosting with a data center inside Iran and proper cache configuration is usually sufficient. CDN only makes sense for sites with an international audience.
How often should I check my website speed?
Once after every major change to the site. And at least once a month as regular monitoring. If your traffic suddenly drops, the first thing you do is check speed. Speed drops are one of the common reasons for traffic decline, which we've addressed in recovering from sudden traffic drops.
Comments 0
No comments yet — be the first!