The Slow-Device Web: What Happens When CPUs Can’t Keep Up

Web bloat discussions have typically focused on bandwidth. In 2017, much of the web was effectively unusable for people on slow connections, even in the U.S. Bandwidth has since grown exponentially—Nielsen puts the rate at roughly 50% per year for high-end connections—so for typical sites, the over-the-wire payload problem has eased relative to connection speeds. But CPU performance has not scaled the same way. The result is a widening gap of a different kind: more of the web is now inaccessible to people with low-end devices, even when they have fast internet.

Consider a concrete example: browsing a modern Discourse-powered forum on a Tecno Spark 8C, a phone that sells for around USD 50-60 in Nigeria and USD 100-110 in India. As a fraction of median household income, that device costs substantially more than a current-generation iPhone costs in the U.S. It sometimes crashes the browser outright. Between crashes, responsiveness is worse than browsing a BBS on an 8 MHz 286 with a 1200 baud modem. The 2.6 MB compressed payload needed to load message titles is trivial on a 1Gbps connection—wire payloads have only grown ~1000x, dwarfed by bandwidth gains. But the 8-core CPU (two 1.6 GHz Cortex-A75 cores and six 1.6 GHz Cortex-A55 cores) is roughly 100000x faster than that 286—and it still can’t handle Discourse.

Measuring What Users Actually Experience

The Tecno Spark 8C isn’t even close to the lowest-end device in use worldwide. An Itel P32 sits further down the scale. To compare, tests also ran on an M3 Max Macbook (14-core), an M1 Pro Macbook (8-core), and the M3 Max with 10x CPU throttling in Chrome dev tools. All tests ran over high-speed internet—1Gbps with a low-latency router—to isolate device performance from connection quality.

For each site, two primary metrics were recorded: LCP* and CPU. Google defines LCP as measuring "when a user perceives that the largest content of a page is visible." The asterisk matters: Chrome’s LCP measures when a large fraction of the screen is painted, not when useful content appears. Sites have optimized around that definition—it’s a Core Web Vital and a primary PageSpeed Insights metric—to the point where a large but useless paint (like a loading screen) can register as the LCP while real content appears much later. In those cases, the timestamp for useful content was recorded instead.

CPU time on the main thread is not a Core Web Vital, but it correlates strongly with perceived usability on slow devices. If a page pegs the CPU at 100% for 30 seconds, it’s unusable for 30 seconds; at 50% for 60 seconds, it’s barely usable. Relative to other metrics, CPU time is also hard to game without genuinely improving user experience.

The table below covers blogging platforms (danluu.com, Substack, Medium, Ghost, Hugo, Tumblr), micro-blogging and social platforms (Mastodon, Twitter, Threads, Bluesky, Patreon, HN), forums (Discourse, Reddit, Quora, vBulletin, XenForo, phpBB, MyBB, NodeBB), and small-business platforms (Wix, Squarespace, Shopify, WordPress). Size columns show compressed wire bytes and raw bytes. Green indicates smaller/faster; red indicates larger/slower; extreme values are black.

SiteSizeM3 MaxM1 ProM3/10Tecno S8CItel P32
wirerawLCP*CPULCP*CPULCP*CPULCP*CPULCP*CPU
danluu.com6kB18kB50ms20ms50ms30ms0.2s0.3s0.4s0.3s0.5s0.5s
HN11kB50kB0.1s30ms0.1s30ms0.3s0.3s0.5s0.5s0.7s0.6s
MyBB0.1MB0.3MB0.3s0.1s0.3s0.1s0.6s0.6s0.8s0.8s2.1s1.9s
phpBB0.4MB0.9MB0.3s0.1s0.4s0.1s0.7s1.1s1.7s1.5s4.1s3.9s
WordPress1.4MB1.7MB0.2s60ms0.2s80ms0.7s0.7s1s1.5s1.2s2.5s
WordPress (old)0.3MB1.0MB80ms70ms90ms90ms0.4s0.9s0.7s1.7s1.1s1.9s
XenForo0.3MB1.0MB0.4s0.1s0.6s0.2s1.4s1.5s1.5s1.8sFAILFAIL
Ghost0.7MB2.4MB0.1s0.2s0.2s0.2s1.1s2.2s1s2.4s1.1s3.5s
vBulletin1.2MB3.4MB0.5s0.2s0.6s0.3s1.1s2.9s4.4s4.8s13s16s
Squarespace1.9MB7.1MB0.1s0.4s0.2s0.4s0.7s3.6s14s5.1s16s19s
Mastodon3.8MB5.3MB0.2s0.3s0.2s0.4s1.8s4.7s2.0s7.6sFAILFAIL
Tumblr3.5MB7.1MB0.7s0.6s1.1s0.7s1.0s7.0s14s7.9s8.7s8.7s
Quora0.6MB4.9MB0.7s1.2s0.8s1.3s2.6s8.7sFAILFAIL19s29s
Bluesky4.8MB10MB1.0s0.4s1.0s0.5s5.1s6.0s8.1s8.3sFAILFAIL
Wix7.0MB21MB2.4s1.1s2.5s1.2s18s11s5.6s10sFAILFAIL
Substack1.3MB4.3MB0.4s0.5s0.4s0.5s1.5s4.9s14s14sFAILFAIL
Threads9.3MB13MB1.5s0.5s1.6s0.7s5.1s6.1s6.4s16s28s66s
Twitter4.7MB11MB2.6s0.9s2.7s1.1s5.6s6.6s12s19s24s43s
Shopify3.0MB5.5MB0.4s0.2s0.4s0.3s0.7s2.3s10s26sFAILFAIL
Discourse2.6MB10MB1.1s0.5s1.5s0.6s6.5s5.9s15s26sFAILFAIL
Patreon4.0MB13MB0.6s1.0s1.2s1.2s1.2s14s1.7s31s9.1s45s
Medium1.2MB3.3MB1.4s0.7s1.4s1s2s11s2.8s33s3.2s63s
Reddit1.7MB5.4MB0.9s0.7s0.9s0.9s6.2s12s1.2sFAILFAIL

The general pattern matches intuition: sites that feel slow on fast hardware are slow on cheap hardware. When asked to predict which platforms would fare worst, people correctly guessed that WordPress and Ghost would beat Substack and Medium, and that Discourse would be far slower than the older PHP forums. PageSpeed Insights scores were also pulled, but the correlation was weaker—several sites have optimized their PSI numbers without actually speeding up page loads for users.

The User Experience on a Budget Phone

On a Tecno Spark 8C, many modern sites are simply unusable. Although the phone can run PUBG at around 40fps, scrolling through text-centric social media or forums can drop below 0.4fps. Pages with 10s+ CPU time remain jerky after load—scrolling stutters, and tapping links produces delays so long that it’s impossible to tell if the tap registered. Tapping again risks the second tap landing on the wrong element after the first finally registers. Ironically, MyBB—which doesn’t serve a mobile site and is penalized by Google for it—is more usable on these devices than most mobile-optimized competitors, because scrolling and tapping actually work.

Performance does not scale predictably across devices. The M3/10 throttle approximates the Tecno Spark 8C for some sites (danluu.com, Ghost) but misses badly on others. The real phone is about 3x slower for Medium, Substack, and Twitter; roughly 4x slower for Reddit and Discourse; and over an order of magnitude faster than the throttled MacBook for Shopify. Chrome’s CPU throttling is a useful tool, but no combination of out-of-the-box settings reproduces real-device behavior. Slow pages often degrade super-linearly as devices get slower, and slowness on one page doesn’t predict slowness on another.

Device-centric analysis misses some of the worst behavior. A site-centric view shows that Discourse, Medium, and Reddit use modest CPU on an M3 or M1 but are among the slowest on the Tecno Spark 8C. Reddit’s CPU is listed as : it uses roughly ~90% CPU indefinitely with no interaction. Discourse sometimes crashed the browser after light interaction plus a minute of idle time—arguably a worse experience than a full FAIL, since the page did initially load.

Older and Simpler Wins

A clear pattern emerges: older sites are generally faster. MyBB, the least modernized and oldest-looking forum tested, beats Discourse by 3.6x / 5x (LCP* / CPU) on the M3—but by 19x / 33x on the Tecno Spark 8C. Similarly, an old WordPress theme beats Medium by 17.5x / 10x and Substack by 5x / 7x on the M3 Max; on the Tecno, those gaps widen to 4x / 19x for Medium and 20x / 8x for Substack. Ghost is a notable exception—a modern platform (launched a year after Medium) that stays competitive with older software. NodeBB is a partial exception among forums.

Modern techniques that partially load a page and fetch the rest dynamically—used by Discourse, Reddit, and Substack—tend to make the experience worse than the measured numbers suggest. Such pages are extremely janky on low-end devices. Scrolling an unpredictable distance can accidentally trigger more loads, locking up the page. Some pages even remove scrolled-past content from the DOM, making them effectively unusable. Browser search (ctrl/command+F) breaks on partially loaded pages, forcing sites to implement their own—with varying success. Discourse search has never worked well on slow devices. In principle, this up-front work could make later interactions cheaper, but none of the tested pages were faster on subsequent loads or after load completed.

Attitudes That Blame Hardware

The belief that CPU speed is effectively infinite—and that any shortfall is hardware incompetence—shows up in a notable public exchange. A distinguished Google engineer and the founder of Discourse (then CEO) disagreed about whether mobile sites should be tested with throttled CPUs:

  • Google: you also don't have slow 3G. These two settings go together. Empathy needs to extend beyond iPhone XS users in a tunnel.
  • Discourse: Literally any phone of vintage iPhone 6 or greater is basically as fast as the "average" laptop. You have to understand how brutally bad Qualcomm is at their job.
  • Discourse: we've been trending towards infinite CPU speed for decades now (and we've been asymptotically there for ~5 years on desktop)... I have zero empathy for Qualcomm. Fuck Qualcomm, they're terrible at their jobs.
  • Google: Mobile devices are not at all bandwidth constraint in most circumstances. They are latency constraint. Even the latest iPhone is CPU constraint before it is bandwidth constraint.
  • Discourse: The influential users who spend money tend to be [on iOS], I'll tell you that... Pointless to worry about cpu, it is effectively infinite already on iOS.

The founder’s justification for calling Qualcomm incompetent cites Kraken and Octane benchmarks where the Qualcomm chip hit 74% and 85% of Apple’s performance, respectively. By that standard, a product reaching ~80% of an all-time-great team’s output merits losing one’s job—while Discourse delivering roughly 3% the performance of a non-optimized application like MyBB is acceptable. Donald Knuth expressed a parallel sentiment about multicore hardware:

I might as well flame a bit about my personal unhappiness with the current trend toward multicore architecture. To me, it looks more or less like the hardware designers have run out of ideas, and that they’re trying to pass the blame for the future demise of Moore’s Law to the software writers by giving us machines that work faster only on a few key benchmarks!

When hardware engineers delivered ~100x per decade with no software effort, they were doing their jobs. When that free lunch ended and software had to adapt, the hardware engineers were "all out of ideas"—and learning 1970s-era concurrency concepts was deemed a waste of time. The pattern recurs: software teams expect hardware to solve their problems, and when it doesn’t, the issue gets passed to the user.

Who’s Affected, and Who Cares

The "influential users" comment reflects a broader attitude that non-wealthy users don’t matter. This shows up in comments on JavaScript bloat posts: "Phone apps are hundreds of megs, why are we obsessing over web apps that are a few megs? Starving children in Africa can download Android apps but not web apps?" and "surely no user of gitlab would be poor enough to have a slow device."

The evidence suggests otherwise. In Africa, popular apps are light—Facebook Lite is a couple of megabytes, and common apps run single-digit to low-double-digit MB. App makers care because size drives crashes and retention. Alex Russell notes that iOS holds 7% market share in India (1.4B people) and 6% in Latin America (600M people). Windows telemetry shows most desktop users are on low-end machines likely slower than a modern iPhone.

It has now been six years since the Discourse founder’s prediction that all Android users would soon have "infinite" CPU. Realistically, it will be at least a decade—possibly two—before most phone users worldwide have high-speed devices. Meanwhile, Discourse’s market share makes it the fastest-growing forum software by a large margin. The impact: many forums are now inaccessible to anyone without a device whose CPU is effectively infinite.

This attitude is not an anomaly—it’s an unspoken assumption many programmers hold. That’s why so many modern sites are unusable on the income-adjusted equivalent of a new iPhone purchased in a low-income country.

Appendix: When LCP Gets Gamed

LCP originally measured when the largest visible change occurred, which correlated well with perceived load time. As it became a Core Web Vital, it attracted gaming. Many sites made small tweaks that improved LCP without helping users; others deliberately flash a large, useless loading screen immediately, then carefully keep all subsequent changes small enough to avoid triggering a new LCP measurement.

Such gaming is rarely discussed publicly—resembling the VW emissions scandal in that respect—but Discourse announced theirs outright. Their "Discourse Splash" feature shows a visual preloader while assets load, hugely reducing reported LCP. Official Discourse guidance advises keeping page elements smaller than the splash so the LCP timestamp comes from the useless preloader rather than actual content:

If your banner is larger than the element we use for the "Introducing Discourse Splash - A visual preloader displayed while site assets load" you gonna have a bad time for LCP.

The most extreme ratios of useful-content LCP to Chrome’s measured LCP were:

  • Wix
    • M3: 6
    • M1: 12
    • Tecno Spark 8C: 3
    • Itel P32: N/A (FAIL)
  • Discourse
    • M3: 10
    • M1: 12
    • Tecno Spark 8C: 4
    • Itel P32: N/A (FAIL)

Appendix: The Business Case for Speed

Performance work pays off measurably. At large companies, A/B tests show that improving site and app performance drives growth and retention—and unlike many interventions, those gains persist in long-term holdbacks. The effect is visible even among users with fast devices: a change that moves p99 latency from 60s to 50s on a low-end device might improve a high-end device from 5s to 4.5s, which still moves revenue.

At Twitter, user-observed p99 latency was about 60s in India, several African countries, and the United States alike. Every country has enough slow devices and connections that user patience—not population-level hardware distribution—is the limiting factor. Even focusing solely on U.S. ad revenue, performance improvements for low-end devices show measurable impact. Yet this kind of quantifiable work is chronically underfunded relative to flashier product features that show little long-term effect.

Appendix: Designing for Low-End Hardware

The best experiences on slow devices come from pages that load substantial content at once into a static page. Proper width and height attributes on images, plus alt text, help considerably; progressive JPEG does not. On a slow device with fast bandwidth, any lightweight static page works, and lightweight dynamic pages can work if designed carefully. Heavy dynamic pages are essentially doomed.

Dynamic loading breaks the interaction model that makes slow devices tolerable: load a page, step away, return, and open links in new tabs. Pages that remove scrolled-past content or hijack search (because browser search can’t handle partially loaded pages) eliminate even that workflow. Screen-reader users additionally report that dynamic loading makes pages worse. Parolees given "lifeline" phones—often below the Itel P32’s tier—face similar issues, compounded by limited data plans that make huge pages impossible.

Andy Kelley offers a counterexample for up-front work: the Zig standard library documentation fetches all source code up front and renders locally. On the Tecno Spark 8C it uses 4.7s of CPU, then remains reasonably responsive. It’s the kind of example people cite when defending heavy payloads—but such cases are rare.

Appendix: Test Setup

Each site was tested in its "most default" configuration: WordPress with its current default theme (twentytwentyfour), Shopify’s first-listed theme, and so on. Testing was deliberately time-boxed, so real-world sites—which often add customizations—may be slower than these defaults. Laptops ran at ~60% battery, unplugged, at thermal equilibrium in a 20°C room. Phones ran at 100% charge and plugged in (to avoid charging heat), with no other apps or browser tabs, over 1Gbps WiFi. DevTools itself may slightly degrade performance on the Itel P32; the effect wasn’t quantified.

Speed tests showed the M3 Max reaching 850-900 Mbps down and 840 Mbps up with 3ms unloaded latency. The Tecno Spark 8C managed 390 Mbps down, 210 Mbps up, with 2ms unloaded latency. The Itel P32 maxed out around 44-45 Mbps down, couldn’t complete upload tests, and loaded latency hit 400ms. Notably, the P32’s hardware can’t actually use its nominal bandwidth; phone reviewers describe it as having "no sluggish performance" and delivering "the best performance beyond its capabilities."