headless.first
Why Your Website Is Slow: The 7 Real Causes and What to Actually Fix
PerformancePerformanceNext.jsSEO

Why Your Website Is Slow: The 7 Real Causes and What to Actually Fix

H
HeadlessFirst Team
9 min read

"My website feels slow." It is one of the most common complaints business owners have, and one of the most frustrating to diagnose — because slow is not a cause, it is a symptom. A website can be slow for a dozen different structural reasons, and the fix for each one is completely different. Applying the wrong fix wastes time and money while leaving the real problem in place.

This post identifies the seven most common causes of slow websites in 2026, explains why each one affects performance, and describes what the correct fix looks like. If your site has a Lighthouse Performance score below 60 or a PageSpeed Insights mobile score that makes you uncomfortable sharing it, one or more of these is likely responsible.

1. The LCP Image Is Being Loaded Too Late

Largest Contentful Paint (LCP) is the single most important performance metric for business websites, and the most common cause of a poor LCP score is that the main visible image on the page — the hero image, the product photo, the above-the-fold banner — is discovered by the browser too late in the loading process.

Here is what happens: the browser parses HTML, then fetches CSS, then parses CSS, then discovers that a background image is referenced in the CSS, then fetches that image. By the time the image starts downloading, 400–800ms of time has already been spent on preceding steps. Add the download time for a 500KB image and your LCP is already at 1.5+ seconds before anything else has happened.

The correct fixes:

  • Move the LCP image from CSS background-image to an <img> element — this makes it discoverable immediately during HTML parsing
  • Add fetchpriority="high" to the LCP <img> element — this tells the browser to prioritise this resource above other requests
  • Never apply lazy loading to the LCP image — lazy loading defers image fetching, which is exactly the opposite of what you want for the hero element
  • Use <link rel="preload"> in the HTML <head> to tell the browser about the LCP image before it even starts parsing the page body

On Next.js, the next/image component automatically adds priority={true} for hero images, uses responsive sizing to prevent oversized images from being downloaded on mobile, and serves WebP/AVIF formats that are 30–50% smaller than JPEG equivalents. This single component solves the majority of LCP issues that affect WordPress sites with manually managed images.

2. Too Much JavaScript Blocking Page Rendering

JavaScript that loads in the <head> of a page blocks HTML parsing. While the browser downloads and parses the script, no other work happens — the page is frozen. This is called render-blocking JavaScript, and it is one of the most common causes of slow Time to Interactive and poor LCP scores.

The sources of render-blocking JavaScript on a typical WordPress site include: the jQuery library (still required by most WordPress themes and plugins), the theme's own JavaScript bundle, plugin-specific scripts (sliders, popups, form libraries, cookie consent tools, chat widgets), and analytics scripts. A typical WordPress business site loads 8–15 separate JavaScript files, several of which are render-blocking.

The correct fixes:

  • Move non-critical scripts to load with defer or async attributes — this allows HTML parsing to continue while the script is downloaded
  • Audit and remove unused plugins — every plugin that ships JavaScript is a potential render blocker
  • Load third-party tools (chat widgets, analytics, heat maps) after the initial page is interactive — not during the critical loading path
  • Use a script loading strategy that distinguishes between critical JavaScript (required for the page to function) and non-critical JavaScript (analytics, marketing tools)

Next.js handles this architecturally: React Server Components ship zero JavaScript for non-interactive content. Interactive components are hydrated client-side, but the initial page render is delivered as complete HTML. The JavaScript payload is limited to what is actually needed for interactivity, not everything the framework and its plugins require.

3. Images Are Being Served at the Wrong Size and Format

A desktop hero image uploaded to a WordPress media library at 2400×1600 pixels is the same image served to a mobile phone with a 390-pixel-wide screen. The mobile browser downloads a 1.2MB image, scales it down to 390 pixels wide to display it, and throws away 85% of the pixels it downloaded. This is pure waste — wasted bandwidth, wasted loading time, wasted LCP score.

The 2026 standard for image delivery is:

  • AVIF or WebP format: AVIF typically achieves 50% smaller file sizes than JPEG at equivalent visual quality; WebP achieves 30% smaller
  • Responsive sizing: different image sizes delivered to different screen widths using srcset — a 390px mobile image, an 800px tablet image, a 1200px desktop image
  • Correct compression: images should be compressed to the minimum quality level that is visually indistinguishable from the original for the delivery context
  • Appropriate dimensions: images should never be scaled down in the browser — if a thumbnail is 200×200px in the design, the image served should be 200×200px (or 400×400px for retina screens)

For WordPress sites, achieving this requires a combination of an image optimisation plugin (like ShortPixel or Imagify), a CDN with image resizing capabilities (Cloudflare Images, BunnyCDN), and careful template management to ensure srcset attributes are correctly generated. For Next.js sites, next/image handles all of this automatically — format conversion, responsive sizing, lazy loading for off-screen images, and priority loading for above-the-fold images.

4. The Server Is Slow to Respond

Time to First Byte (TTFB) is the time between a browser sending a request and receiving the first byte of a response from the server. It measures how long the server takes to do its work before it can start sending anything to the browser.

A good TTFB is under 200ms. A WordPress site on shared hosting or budget managed hosting typically has a TTFB of 400–1500ms. Premium managed WordPress hosting (WP Engine, Kinsta, Flywheel) reduces this to 200–400ms. But even at 200ms, the server is taking 4× longer to respond than a CDN-delivered static file.

The causes of slow TTFB on WordPress:

  • Database query overhead: every WordPress page request runs 15–50 database queries depending on the theme and active plugins
  • PHP execution time: processing WordPress core, theme functions, and plugin hooks takes CPU time before any HTML is generated
  • Shared hosting resource contention: on shared hosts, your server resources compete with hundreds of other sites on the same machine
  • Lack of full-page caching: without aggressive full-page caching, every request triggers the full PHP/MySQL stack

The structural alternative is serving pre-rendered HTML from a CDN edge — as Next.js does with Static Site Generation. There is no server computation because the page was computed at build time and stored as a static file. TTFB is a CDN network latency measurement, not a server computation measurement. The result is sub-50ms TTFB from a global CDN edge, regardless of where in the world the visitor is.

5. Third-Party Scripts Are Slowing Everything Down

The average business website loads 15–20 third-party scripts from external domains: Google Analytics or GA4, Google Tag Manager (which loads additional tags), Facebook Pixel, LinkedIn Insight Tag, a live chat widget (Intercom, Drift, HubSpot), a cookie consent tool, a heat map tool (Hotjar, Microsoft Clarity), and possibly an A/B testing script.

Each of these scripts:

  • Requires a DNS lookup to the third-party domain
  • Requires an HTTP connection to be established
  • Downloads JavaScript that must be parsed and executed
  • May inject additional resources (fonts, images, additional scripts) into the page
  • Blocks or competes with your own page resources for network bandwidth

The cumulative effect is significant: third-party scripts account for 30–50% of page weight and a disproportionate share of Time to Interactive on most business websites. The Intercom chat widget alone can add 400–600ms to page load on first visit.

The correct approach is not to remove all third-party tools — most serve legitimate business purposes. It is to load them strategically: defer non-critical tools until after the page is interactive, consolidate tracking through a single tag manager rather than individual pixels, audit and remove tools that are no longer actively used, and use server-side tracking for analytics where possible to eliminate the client-side script entirely.

6. Web Fonts Are Causing Layout Shifts and Invisible Text

Web fonts introduce two performance problems: the font file must be downloaded before the browser can render text, and if the fallback font is a different size than the web font, the layout shifts visibly when the web font loads — a CLS (Cumulative Layout Shift) problem.

The 2026 best practices for font loading:

  • Self-host fonts rather than loading from Google Fonts or Adobe Fonts CDN — eliminates the third-party DNS lookup and connection overhead
  • Use font-display: swap in the @font-face declaration — renders text immediately in the fallback font while the web font downloads, preventing invisible text (FOIT)
  • Preload critical font files in the HTML <head> using <link rel="preload" as="font"> — ensures fonts are fetched early in the loading process
  • Use size-adjust and other font descriptor overrides to reduce the layout shift when the web font swaps in over the fallback

Next.js has built-in font optimisation via next/font: it automatically self-hosts Google Fonts, applies font-display: swap, generates the correct preload hints, and uses CSS size-adjust to minimise layout shift when swapping between fallback and web font. This eliminates the font performance problem entirely without manual configuration.

7. There Is No CDN, or the CDN Is Configured Incorrectly

A Content Delivery Network (CDN) is a globally distributed network of servers that stores copies of your website's assets (and, for Next.js, entire pages) close to your visitors. Without a CDN, every visitor — regardless of where they are in the world — sends their request to a single origin server in a single location. A visitor in Sydney requesting a page from a server in Frankfurt experiences 150–200ms of network latency alone, before the server even starts responding.

With a CDN, the same visitor in Sydney is served from a CDN edge node in Sydney or Singapore. The network latency drops to 5–15ms. Combined with server-side caching, this can reduce TTFB from 800ms to under 50ms.

The common CDN configuration mistakes that negate these benefits:

  • Setting max-age=0 or no-cache on HTML pages — this forces every visitor to bypass the CDN and hit the origin server, eliminating the main performance benefit
  • Not caching static assets (JavaScript, CSS, images) aggressively — these should have max-age=31536000, immutable for content-hashed filenames
  • Using a CDN that is geographically under-represented for your visitor base — a CDN with excellent US coverage but limited Asia-Pacific nodes will underperform for APAC visitors
  • Not enabling HTTP/3 on the CDN — HTTP/3 significantly improves performance on high-latency and lossy connections (mobile networks)

Conclusion: Slow Is Fixable, But the Right Fix Depends on the Real Cause

Website performance problems are diagnosable and fixable. But the correct diagnosis must come first — applying a caching plugin to a site with a render-blocking JavaScript problem will not meaningfully improve the performance. Optimising images on a site with a 1.5-second TTFB will help, but the TTFB problem will dominate until it is addressed.

The most reliable path to genuinely good performance — sub-2-second LCP, Good Core Web Vitals across all three metrics, Lighthouse mobile scores above 90 — is building on an architecture that produces these characteristics by default rather than fighting against an architecture's structural limitations with incremental fixes.

That is what Next.js with proper static generation delivers: performance characteristics that are built into the rendering architecture, not bolted on after the fact.

Want to know exactly what is slowing your site down? We offer a free performance audit that identifies the specific bottlenecks on your site and quantifies the conversion rate impact of fixing them. No obligation — just clarity.