The Real Cost of a Megabyte

Written by

in

There is a number that quietly governs the experience of using the web, and most teams never look at it directly. It is the weight of the page — the total bytes a browser must fetch, parse, and execute before a person can read, tap, or buy. We obsess over design and copy and conversion funnels, and then ship four megabytes to a phone on a train and wonder why the bounce rate is high. The megabyte has a cost. It is worth learning to count it.

Bytes are not abstract

On a fast laptop wired to fibre, page weight is nearly invisible. That is precisely the trap. The people who build the web tend to test it on the best hardware and the best connections, and so the cost of every extra script is paid by someone they never meet: the reader on a three-year-old Android, on a congested cell network, with a metered data plan where each megabyte is money.

Page weight is paid by someone you never meet, on hardware you would never choose.

The costs are layered. There is the transfer cost — how long the bytes take to arrive. There is the parse-and-compile cost, which falls hardest on JavaScript, because a script is not merely downloaded but executed on the main thread, blocking everything else. And there is the memory cost, which is what finally makes a cheap phone stutter and a tab crash.

A rough budget

The most useful tool in performance work is not a profiler but a budget — a number you refuse to exceed. A reasonable starting point for a content page looks like this.

  • HTML: under 50 KB. If your markup is larger, you are probably shipping data you do not need.
  • CSS: under 75 KB, ideally critical styles inlined.
  • JavaScript: under 150 KB, and a real conversation about whether you need any.
  • Fonts: two families at most, subset and served as WOFF2.
  • Images: sized to their container, modern formats, lazy-loaded below the fold.

Budgets work because they force trade-offs to happen in the open. When a new carousel library wants 90 KB, the budget makes you ask what you will remove to afford it. Without a budget, every addition is free until, collectively, they are ruinous.

A waterfall chart of network requests
Every row in a network waterfall is a decision someone made, usually without measuring it.

The biggest wins are usually images and fonts

Before optimising a single line of JavaScript, look at what you are actually sending. On most content sites the heaviest assets are images that were never resized and fonts that were never subset. A photograph exported at 4000 pixels and displayed at 800 is wasting three-quarters of its bytes. Converting it costs minutes; the saving is permanent.

# Convert a heavy PNG to a sensible WebP at the display size
cwebp -q 80 -resize 1200 0 hero.png -o hero.webp

# Result on a typical photo:
#   hero.png   2,300 KB
#   hero.webp     120 KB   (~95% smaller, visually identical)

Fonts follow the same logic. A full variable font can weigh several hundred kilobytes because it carries every weight and every script on earth. Subset it to the characters and weights you actually use, serve WOFF2, and preload only the one or two faces that appear above the fold.

The fastest request is the one you never make. The second fastest is the one you make smaller.

An old performance proverb, still true

JavaScript is where weight hides

Images are heavy but honest; you can see them. JavaScript is heavy and deceptive, because a 150 KB bundle does far more damage than a 150 KB image. The image is decoded off the main thread; the script blocks it. A page can look finished and still be unresponsive for seconds while the browser chews through code. This is why a beautiful site can feel broken on a mid-range phone: the pixels arrived, but the page cannot yet respond to a tap.

The remedy is rarely a clever optimisation. It is subtraction. Audit the dependencies. Ask whether the framework is doing work the platform now does natively. Ask whether the analytics, the chat widget, and the consent banner are each worth their cost. Often the most effective performance patch is a delete key.

The lab and the field

There are two ways to measure speed, and confusing them causes endless wasted effort. Lab data comes from a synthetic test on a controlled machine — useful for debugging, reproducible, and completely artificial. Field data comes from real visitors on real devices, and it is the only measurement that describes the experience people actually have. A site can score beautifully in the lab and miserably in the field, because your test machine is not a worn phone on a crowded network at the edge of coverage.

The practical rule is to optimise against the lab but judge against the field. Use synthetic tools to find and fix specific problems, because they are fast and repeatable. But keep your eyes on field metrics to know whether any of it mattered, because the field is where your readers live and the lab is only where you work.

Core Web Vitals without the jargon

The industry’s current vocabulary for speed sounds intimidating and is actually intuitive once translated into human terms.

  • Largest Contentful Paint asks: how long until the main thing shows up? Usually gated by your hero image or web font.
  • Interaction to Next Paint asks: when I tap, how long until something happens? This is where heavy JavaScript exacts its price.
  • Cumulative Layout Shift asks: does the page jump around as it loads? Caused by images and ads without reserved space.

Notice that each maps to a felt experience: the wait, the unresponsive tap, the maddening jump just as you go to click. Strip away the acronyms and the metrics are simply formal names for frustrations every person already recognises.

A pragmatic order of operations

Performance work goes wrong when teams start with the most interesting problem rather than the most impactful one. The impactful order is almost always the same, and it is rarely the glamorous one.

  1. Right-size and modernise images. The single biggest win on most sites, and the least clever.
  2. Subset and self-host fonts; preload only what appears first.
  3. Audit and remove third-party scripts you cannot justify.
  4. Reserve space for media so the layout stops shifting.
  5. Only then reach for code-level micro-optimisations.

Most performance problems are not solved by writing faster code. They are solved by sending less of it.

The lesson teams learn last

Caching and the edge

Once a page is lean, the next lever is distance. A request that travels to a single origin server on another continent will always feel slow, no matter how small it is. Caching at the edge — serving static assets and, where possible, whole pages from a location near the reader — collapses that distance. For a content site this is transformative, because most pages change rarely and can be served from cache to almost everyone almost all of the time.

The discipline here is cache invalidation: making sure readers see updates without forcing the browser to refetch unchanged files. Fingerprinted asset names — a hash in the filename that changes only when the content does — let you cache aggressively and update instantly. It is a small technique with an outsized effect on repeat-visit speed, and it costs nothing once configured.

The myth of the average user

Performance reports love an average: a mean load time, a median device, a typical connection. Averages are comforting and frequently misleading. The distribution of real-world conditions is not a tidy bell curve clustered around your assumptions; it has a long, heavy tail of slow devices and worse networks, and a meaningful share of your readers live in that tail. Designing for the average abandons them precisely because they are inconvenient to picture.

A more honest practice is to design for a difficult case on purpose. Pick a representative low-end device and a constrained network, and make that your reference experience. If the site is pleasant there, it will be delightful everywhere else. This inverts the usual incentive, which is to test on the machine you happen to own. The hardware you own is the least representative sample available to you, and trusting it is how good intentions ship slow sites.

Budgets are a culture, not a config

A performance budget written once and forgotten is just a number in a file. A budget that works is a shared agreement the whole team treats as real — enforced in the build, visible on a dashboard, and discussed when a change threatens to breach it. The technical mechanism matters far less than the social one. The teams that stay fast are not the ones with the cleverest tooling; they are the ones where shipping something heavy feels like a decision that must be justified rather than a default that goes unquestioned.

This is why performance so often regresses after a redesign or a reorganisation. The number did not change; the culture did. When the people who guarded the budget move on, and no one inherits the habit of asking “what will this cost the reader?”, weight creeps back one harmless-seeming addition at a time. Speed, like a garden, is not a state you achieve but a practice you sustain. Stop tending it and it reverts, quietly, to the heavy default the rest of the industry will happily supply.


Performance is an ethic, not a sprint

It is tempting to treat speed as a project — a week of optimisation before launch, then back to shipping features. But weight accumulates the moment you stop watching it. The teams that stay fast are the ones who treat the budget as a standing commitment: a check in the pipeline, a number on a dashboard, a question asked of every pull request.

The reward is not an abstract score. It is a site that works on the phone in someone’s pocket, on the connection they actually have, in the few seconds of attention they are willing to give. Counting the cost of a megabyte is, in the end, a way of taking your readers seriously.

In the end, performance is the most concrete form of empathy a builder can offer. You will never meet most of the people who load your pages, never see the cracked screen or the spinning indicator or the data warning that flashes as your hero image downloads. The budget, the subset font, the deleted dependency — these are the ways you reach those people anyway, the ways you say, without ever speaking to them, that their time and their connection and their hardware were worth respecting. A fast site is not a technical achievement that happens to be kind. It is a kindness that happens to require some technical care.

Measured honestly and revisited often, speed stops being a launch-day scramble and becomes simply how the team works: a small, standing promise kept to every reader, on every device, and with every single release.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *