Why websites get slower over time

Why a fast site slides: heavier pages, more scripts, piled-up plugins, drifting caches and nobody in charge. How to see what changed and how to stop the slide.

BeginnerExplainer5 min readUpdated October 30, 2026

In this guide
  1. The whole web is getting heavier
  2. Seven ways a fast site slides
  3. See what a page loads today
  4. Keep a baseline
  5. Stop the slide
  6. Mistakes to avoid
  7. Check your own page
  8. Sources

The whole web is getting heavier

The 2025 Web Almanac tracked the median mobile home page since 2015. In July 2015 it weighed 845 KB. In July 2025 it weighed 2,362 KB, an increase of 202.8%. The median desktop home page grew by 110.2% over the same ten years. In the latest year, the median home page grew 7.8% to 2.7 MB, and inner pages grew 9.5%. On inner pages, mobile weight is up 27.8% since the Almanac began tracking them in 2022.

The median mobile home page in 2025 was made of about 911 KB of images, 632 KB of JavaScript, 122 KB of fonts, 77 KB of CSS and 22 KB of HTML. The Almanac says JavaScript is heavier than its size suggests, because the browser must parse and run it. See page weight and requests.

Your site lives in that weather. Nobody has to make a mistake for a page to get heavier. They only have to keep adding.

Seven ways a fast site slides

1. Bigger content. New photos arrive straight from a phone or camera, at sizes far beyond what the page shows. A background video replaces a still. The first screen picks up a slider. Each addition is small. Together they decide the Largest Contentful Paint. See image optimization and video.

2. More scripts and tags. Marketing wants a pixel, sales want a chat tool, an agency adds a testing tool. Each is one more request to another company's server, and one more thing that can slow the page, change without notice or fail. Tag managers make it easy to add them and easy to forget them. See third-party scripts.

3. Plugins, themes and builders that stack up. On a content management system, every feature is another bundle of code and often another style sheet on every page. Plugins stay active long after anyone remembers why they were installed. See WordPress themes and plugins and page builders.

4. A growing database. On WordPress, options and data pile up as plugins come and go, and the server does more work on every uncached request. See database cleanup and server response time.

5. Software that changes underneath. Updates to a theme, a plugin, PHP or the hosting plan change speed in both directions. The yardstick changes too. The Almanac notes that Google replaced First Input Delay with Interaction to Next Paint in March 2024, which exposed responsiveness problems that the old measure had overlooked. A site that passed last year can fail the same test this year without a line of its own code changing. See Interaction to Next Paint.

6. Caches that drift. A theme switch, a new cookie, a marketing link with tracking parameters or a plugin that sets no-store can stop a page cache or CDN from helping. Nothing looks broken, and the server simply does more work. See caching explained and WordPress caching.

7. Nobody owns it. Speed belongs to the developer, the marketer and the content editor at once, which means it belongs to nobody. There is no limit on page weight, no check before a change goes live, and no record of how the site was last month. The slide is slow enough that no one notices, because the field data behind Core Web Vitals covers a rolling 28-day window. See real user monitoring.

See what a page loads today

The quickest way to find what has piled up is to list it. This script loads a page in a real browser and adds up what it downloads, by host and by type. It uses the browser's own transfer sizes. It needs Node and Playwright:

// inventory.mjs: node inventory.mjs https://example.com/
import { chromium } from 'playwright';

const url = new URL(process.argv[2]);
const browser = await chromium.launch();
const page = await browser.newPage();
const client = await page.context().newCDPSession(page);
await client.send('Network.enable');

const seen = new Map();
const sizes = new Map();
client.on('Network.responseReceived', (e) => seen.set(e.requestId, { host: new URL(e.response.url).host, type: e.type }));
client.on('Network.loadingFinished', (e) => sizes.set(e.requestId, e.encodedDataLength));

await page.goto(url.href, { waitUntil: 'networkidle' });
await browser.close();

const total = (key) => {
  const sums = {};
  for (const [id, info] of seen) {
    const k = info[key] + (key === 'host' && info.host !== url.host ? '  (other site)' : '');
    sums[k] ??= { requests: 0, KB: 0 };
    sums[k].requests++;
    sums[k].KB += (sizes.get(id) || 0) / 1024;
  }
  for (const k in sums) sums[k].KB = Math.round(sums[k].KB * 10) / 10;
  return sums;
};
console.table(total('host'));
console.table(total('type'));

I ran it against a test page that loaded a style sheet, an image and two scripts from two other hosts. It listed the page's own host with three requests and 91.2 KB, the two other hosts with one request each, and the totals by type, with the two scripts together at 88.2 KB. A real page will show a longer list. The things to look for are hosts that nobody can explain, scripts that are far larger than the feature they provide, and images that are bigger than any screen.

A www. host and a bare domain count as different hosts in this script, so read the list instead of trusting the label. For a lab view with Lighthouse, see how to read a speed report.

Keep a baseline

Write down a few numbers now, and again every month or quarter:

NumberWhere it comes from
Page weight and the number of requestsThe script above, or the Network panel
The number of other hostsThe script above
Largest Contentful Paint, Interaction to Next Paint and Cumulative Layout ShiftField data when available. See lab and field data
Server response timeA speed test or the Network panel
The date, and what changed since the last timeA short change log

Lighthouse's own documentation warns that scores vary between runs even when nothing changes, so compare medians of several runs, not single numbers. See why scores change.

Stop the slide

  1. Set a limit. A budget on page weight, requests or a metric turns "it feels slower" into a failed check. See automated testing and budgets.
  2. Ask before adding. Before a new script, plugin or widget goes live, ask what it costs and what it replaces. A good rule is one in, one out.
  3. Measure after each change. See how to test speed changes safely.
  4. Review on a calendar. Once a quarter, run the inventory, list the tags and plugins, and remove what nobody can justify.
  5. Name an owner. One person, inside or outside the company, who sees the numbers and can say no.

Mistakes to avoid

Check your own page

Run the free audit and save the report. Then run the inventory script on the same page, and write down the number of requests and the number of other hosts. In three months, do it again and compare.

Sources

Start here

Free website audit

Live Google data for any public page: mobile and desktop.

Mobile + desktop · Lighthouse lab test · Real-user Chrome data when Google has it

Rather have this done for you? Speed optimization · Book a call

Related guides

All guides →