Two independent models, built by people who never talked to each other, land on the same centre of gravity.
The Sustainable Web Design model (v3) splits the energy of a page view four ways: 15% datacentre, 14% transport network, 52% user device, 19% amortised hardware manufacturing, at 0.81 kWh per GB transferred. The French ADEME–Arcep study, working from national data rather than per-page arithmetic, puts end-user devices at 65–92% of digital's total footprint, with manufacturing, not electricity, as the dominant share.
Different methods, same answer: the thing you host is a rounding error next to the thing people hold.
That conclusion is now reasonably well known. What follows from it is not, and it is the reason I am writing this.
Both models scale with bytes. One of the four segments doesn't.
In a per-byte model, all four segments move together. Halve the payload, halve the datacentre share, the network share, the device-energy share, and the manufacturing share too, because it is expressed as a fixed proportion of transferred data.
That last step is the problem. Manufacturing impact is not a function of bytes. It is a function of replacement. A phone's embodied carbon is spent once, at the factory, and it is amortised over however many years that phone stays in service. What shortens that service life is not page weight. It is the accumulated experience of a device that feels broken.
So the model prices the single largest non-electrical chunk of the footprint as if it were proportional to the one variable that barely influences it.
Two pages, same weight, opposite consequences
Take a 45 KB page: HTML, CSS, no images, inline SVG for the charts. A carbon calculator gives it an A. Roughly 0.014 g CO₂e per visit, about 35× below the HTTP Archive median. Genuinely good work, and I am not being sarcastic, that page is better than almost everything shipped.
Now take another 45 KB page. Same payload to the byte. It runs a requestAnimationFrame loop for a decorative parallax. Its framework build target dropped Android WebView versions older than three years ago. It blocks the main thread for over a second on first interaction. It polls an endpoint every ten seconds and never reaches idle.
Same grade. Same gram count. One of those two pages participates in making a four-year-old phone feel like a broken phone, and the other does not, and the model cannot tell them apart, because nothing it measures changed.
There is a very clean illustration of this published on dev.to a few days ago. @giotramu measured a custom MultiSelect that mounted ~1,175 option components in one synchronous commit for about six visible rows: INP 1,256 ms, measured in DevTools at 4× CPU throttling. After hand-rolling a ~90-line virtual scroll hook, 13 mounted nodes and INP 96 ms. From a per-byte standpoint, that fix is invisible: the JS bundle barely moved, the transferred weight is the same, the carbon grade would not budge. From the standpoint of whether someone's phone still feels usable, it is one of the largest wins available in front-end work.
And @hanaharness measured third-party weight across 51 B2B SaaS homepages: median 6,072 KB, 34.6% of it someone else's code, and, the number I keep coming back to, 12 of those pages never reach an idle state at all. A page that never goes quiet keeps the CPU and the radio awake. That is battery cycles and thermal load, which is to say service life, which is to say manufacturing, which is to say 19% of the model that the model computes from bytes.
What I would measure instead, and I mean measure, not estimate
None of these is a carbon figure. Each one is a proxy for device service life, and each one is cheap enough to put in a definition of done.
1. The oldest device class you still support, written down and actually tested. Not "we support modern browsers". A named phone, a named OS version, a named year, in the ticket template. If nobody has written it down, the answer is decided accidentally by whatever your build tool defaults to, which is a sustainability decision made by a config file.
2. A main-thread budget at harsher throttling than the default.
Lighthouse's 4× CPU slowdown approximates a mid-tier phone, not an old one. Run your worst interaction at 6× or 10×, or better, on a real five-year-old handset from a drawer. The gap between 4× and the actual tail is exactly where the replacement decision gets made.
3. Time to idle after load. Does the page ever stop doing things? Set a threshold — no long tasks after N seconds, no network after settle, and treat a violation as a bug rather than as a characteristic.
4. Off-screen and background work. Animation frames while the tab is hidden, polling with no backoff, listeners that never detach. These cost nothing in bytes and run for as long as the page is open.
The honest limitation, stated plainly
I cannot convert any of the four into grams. There is no defensible coefficient that turns "we kept supporting one more device generation" into CO₂e, because the counterfactual, would that person have replaced the phone anyway, when, with what, is not observable from a web page.
So this is not a methodology, and anyone presenting it as one is selling something.
It is a narrower claim: the metric is missing, and its absence is systematic rather than accidental. Per-byte models are the only practical way to score a page today, and they structurally cannot see the largest lever, which means the industry optimises hard on 15% and guesses at 71%.
The question, and it's a real one
To @yel-martinez-green-tech, who implemented SWD v3 from scratch rather than calling someone's API, and to anyone else who has been inside these numbers: has anyone found a defensible way to represent a device-lifetime effect inside a per-byte model — or is the honest answer that it needs a second, separate metric that sits beside the gram count?
I have looked and I have not found one. I would rather be shown wrong than keep repeating that the gap exists.
Free and open, if it's useful: the eight product-arbitration questions I use to decide which features get built, the ones that put device impact before hosting, are published in English at https://perennova-eco.github.io/en/. No signup, no tracker, no network request after load. The full kit exists in French only, so there is nothing to sell you here.
Written and translated with AI assistance, declared with dev.to's AI-Assisted label. The measurements quoted are other people's published
work, credited above; the ADEME–Arcep and Sustainable Web Design figures
are public and linked in the sources of my previous article.
Top comments (0)