<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Infrequently Noted</title>
  <subtitle>Alex Russell on browsers, standards, and the process of progress.</subtitle>
  <link href="https://infrequently.org/feed/feed.xml" rel="self"/>
  <link href="https://infrequently.org/"/>
  <updated>2026-04-03T00:00:00Z</updated>
  <id>https://infrequently.org</id>
  <author>
  <name>Alex Russell</name>
  <email>alex@infrequently.org</email>
  </author>
  <entry>
    <title>The Web Is An Antitrust Wedge</title>
    <link href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/"/>
    <updated>2026-04-03T00:00:00Z</updated>
    <id>https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/</id>
    <content type="html"><![CDATA[
      <aside class="tldr">
<p><strong><abbr title="&quot;Too long; didn't read&quot;; a summary of a post">TL;DR</abbr>:</strong>
<a href="https://digital-markets-act.ec.europa.eu/index_en">Armed with new powers</a> to <a href="https://en.wikipedia.org/wiki/Digital_Markets,_Competition_and_Consumers_Act_2024">rein in</a> the <a href="https://www.gov.uk/cma-cases/mobile-ecosystems-market-study">worst excesses</a> of mobile's duopolists, antitrust bodies around the world are struggling to find their footing, and an incurious tech press is letting it pass with nary a nod. Browsers are app stores, but that perspective is almost entirely absent from the antitrust conversation.</p>
<p>Instead of prioritising the one, narrow intervention that can safely unlock maximal competition, regulators are gripped by alt store fever dreams; driving down cul-de-sacs that will leave the duopolists' power intact even if new native app stores materialise. Worse, enforcers of new regulations are choking in the face of blatant non-compliance. Laws designed to kickstart competition and unchain web apps are being flouted, but regulators seem unfazed.</p>
<p>The web as an engine of interoperability; this was understood by the drafters of these laws, but enforcers have not internalised the lesson, with the UK's CMA being only the latest to <a href="https://open-web-advocacy.org/blog/apples-interoperability-commitments-to-the-uk-cma-promise-nothing/">pose capitulation</a> as success. Instead of unlocking growth and dynamism, overcautious regulators are ratifying non-compliance through inaction. Timidity today reduces room for manoeuvre tomorrow while hampering home-grown competitors to Big Tech.</p>
<p>As it did twenty-five years ago, the web can unlock maximum change with the lowest risk, but regulators are falling down on the job, and tech reporters are not informing readers of the options or the stakes. It's time we spoke plainly about these overlapping institutional failures.</p>
</aside>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#open-societies-necessitate-interoperability">Open Societies Necessitate Interoperability</a></li><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#shared-premises">Shared Premises</a><ul><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#alt-stores%2C-pwas%2C-and-the-app-store-endgame">Alt Stores, PWAs, and the App Store Endgame</a></li></ul></li><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#regulators-are-missing-the-ripest-opportunity">Regulators Are Missing The Ripest Opportunity</a><ul><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#cupertino-is-running-circles-around-brussels%2C-tokyo%2C-and-london">Cupertino is Running Circles Around Brussels, Tokyo, and London</a></li></ul></li><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#browsers-are-app-stores">Browsers Are App Stores</a></li><li><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#our-tech-press-is-missing-the-story%2C-too">Our Tech Press is Missing the Story, Too</a></li></ul></nav>
<p>It's a day that ends in &quot;y&quot;, which means The Verge is at it again: <a href="https://www.theverge.com/column/902668/apple-antitrust-app-store-war">covering the regulatory tussle over mobile ecosystems</a> without mentioning browsers, the web, or <abbr title="Progressive Web Apps">PWAs</abbr>.</p>
<p>This <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">long-established pattern</a> is as frustrating as it is predictable. Silicon Valley's journalists fail readers by neglecting to connect the dots between the forces that kept desktop OSes open and the suppressive tactics the mobile duopolists<sup class="footnote-ref"><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fn-co-monpoolists-1" id="fnref-co-monpoolists-1">1</a></sup> deploy to prevent similar outcomes. And this despite connections <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">handed to them on a platter</a> by <a href="https://open-web-advocacy.org/"><abbr title="Open Web Advocacy">OWA</abbr></a> and others. In 2026, the choice to cover app store regulation exclusively through the lens of steering and native app alt stores is a yawning blind spot.</p>
<p>Capable browsers, and the <abbr title="Progressive Web Apps">PWAs</abbr> they support, hold the power to grow an ecosystem of applications that no gatekeeper can own or tax, based on standardised APIs that resist enclosure. Apple <a href="https://open-web-advocacy.org/blog/how_apples_key_tactic_could_prevent_japans_smartphone_act_from_improving_browser_competition/">goes to extreme lengths</a> to prevent the emergence of browser engine choice to obstruct the app store's most credible disruptor. But few outlets are connecting these dots for readers.</p>
<p>Cupertino is terrified of the web's potential, but you'll never read about it on the pages of Wired, MIT Tech Review, The Verge, or 404. Loyal readers remain uninformed, never clocking how regulators have acquiesced to the gatekeepers' stalling and misdirection. Only <a href="https://www.theregister.com/">The Register</a> and <a href="https://thenewstack.io/">TNS</a> understand what time it is, covering the essential points regularly:</p>
<ul>
<li>Apple is succeeding in delaying real browser choice through underhanded and unlawful tactics</li>
<li>Regulators are not enforcing the laws effectively in these areas</li>
<li>Users and local businesses lose as a result</li>
</ul>
<p>These regulatory and journalistic failures are not victimless, circumscribing what technology can be for us all, both positive and negative.</p>
<h2 id="open-societies-necessitate-interoperability" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#open-societies-necessitate-interoperability">Open Societies Necessitate Interoperability</a></h2>
<p>In 2026, it should go without saying that billionaires at the helm of Big Tech firms cannot be trusted to do anything but <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/">cower</a> and <a href="https://www.anildash.com/2025/09/09/how-tim-cook-sold-out-steve-jobs/">pirouette</a> for <a href="https://iandunt.substack.com/p/the-mad-emperor-has-triggered-chaos">Mad</a> <a href="https://www.theatlantic.com/magazine/archive/2025/12/trump-third-term-authoritarianism/684616/?gift=VjLv3Dd1h8jJ03YjTtjfrWTIQmj770ivAvgxyR17xRI&amp;utm_source=copy-link&amp;utm_medium=social&amp;utm_campaign=share">King</a> <a href="https://www.theatlantic.com/ideas/2026/01/trump-letter-to-norway/685676/?gift=VjLv3Dd1h8jJ03YjTtjfrTTCQ_v6L-oJ5rf1SQ2o-LQ&amp;utm_source=copy-link&amp;utm_medium=social&amp;utm_campaign=share">Trump.</a> The &quot;good ones&quot; have been proven <a href="https://www.theverge.com/policy/859902/apple-google-run-by-cowards">feckless</a> when presented with opportunities to defend democracy and decency. The rest are either <a href="https://archive.is/1qNRA">actively fascist</a>, <a href="https://fortune.com/2026/03/25/trump-appoints-zuckerberg-huang-ellison-for-tech-advisory-council-but-excludes-elon-musk-sam-altman/">fascism-curious,</a> <a href="https://www.theatlantic.com/technology/archive/2025/02/jeff-bezos-great-emboldening/681886/">fascist-enabling,</a> or <a href="https://fortune.com/2026/01/07/did-larry-page-leave-california-billionaire-tax-jensen-huang/">so engrossed in tax dodging</a> they haven't clocked the rule of law succumbing to attacks by their peers. Not that there's much hope they'd stand up for it; they've got theirs, Jack.</p>
<p>These are the masters of the universe demanding control over what happens on our most personal computers.</p>
<p>In an era when they still claimed to be changing the world for the better, <a href="https://infrequently.org/2026/01/naked-power/#vertigo">the lies told to justify an invasive, unsafe ecosystem of native apps</a> went down more easily. The duopolists provided shockingly deep hooks into our lives for native app developers while shielding them from <a href="https://www.eff.org/deeplinks/2019/10/adversarial-interoperability">adversarial interoperability.</a> In exchange, they demanded control over distribution and taxed the pants off the gambli... — sorry, <em>&quot;casual games&quot;</em> — and privacy degrading social media apps that powered the growth of the native app ecosystem.</p>
<p>Accomplishing this feat required defeating threats from open technologies, because open systems allow users to assert their interests in the face of abusive and predatory software. If users had a vote where useful software could be acquired, or could use browsers for more of their needs, it wouldn't be possible to tax developers at such a high rate. The anti-privacy, anti-user agenda that Apple and Google draw excess profits from cannot survive serious challenges by open technology, which is why the duopolists have worked to hobble them. This is reason enough for democracies to demand portable, standards-based software.</p>
<p>Democratic societies also have wider interests, and we see clearly that trusting Apple and Google with as much market power as they demand is a threat to those goals. The <a href="https://infrequently.org/2026/01/naked-power/">shocking ethical derelictions</a> of the app stores provide yet more reasons to demand regulators legalise open technology.</p>
<p>Software and digital services benefit from network effects, creating acute winner-take-all dynamics in markets where countervailing forces are suppressed. Traditionally, those crosswinds for would-be monopolists have included over-the-top applications, Open Source software, adversarial interoperability, and end-user modulation within open ecosystems (e.g., ad-blocking extensions). Over time, these disciplining factors can break the hold of short-term monopolists, returning power to users and forcing abusive proprietors of services to do better by society or risk losing market share as moats dry up from the pressure.</p>
<p>The iOS and Android duopoly have rendered these recourses illegal and impractical, minting a small number of durable winners. The CEOs and founders of these colossuses are the new tech oligarchs, and their actions in recent years provide compelling arguments against both money in politics and the idea that there can be such a thing as a &quot;good&quot; billionaire.</p>
<p>The broligarchs have shown no compunction towards subverting the state for illegitimate private ends. Having corrupted American politics with torrid rivers of cash, news of their support for anti-democratic, authoritarian regimes around the world no longer surprises. <a href="https://www.reuters.com/sustainability/boards-policy-regulation/eu-fines-us-companies-are-biggest-source-friction-state-department-official-says-2026-04-01/">Shocking evidence of this corruption is on display almost daily.</a> Not content to <a href="https://www.theguardian.com/us-news/2026/feb/12/us-antitrust-gail-slater-ousted-trump-administration">curdle American governance,</a> the broligarchs now <a href="https://www.techpolicy.press/how-trumps-data-regulation-crackdown-undermines-digital-sovereignty/">demand others desist in enforcing their laws</a> lest governance dampen their accelerating profits.</p>
<p>This corrosive effect is only possible thanks to the intense concentrations of wealth enabled by perverted market structures. These twisted markets are themselves the result of <a href="https://press.uchicago.edu/ucp/books/book/chicago/U/bo252799883.html">decades of neo-liberal anti-antitrust groupthink.</a> Contra Bork, the social contributions of robust antitrust enforcement aren't limited to lower prices. Reducing the power of private actors promotes stable institutions and honest dealing across a wide swath of society. <a href="https://www.samuelbagg.com/">Samuel Bagg</a> frames the opportunities for antitrust enforcement similarly:</p>
<blockquote>
<p>...many practices of constitutionalism are justified on similar grounds: i.e., that first-order constraints on the abuse of power can only be sustained through second-order limits on the concentration of power more generally. Where modern constitutionalism aims primarily to limit the concentration of public power, however, the anti-monopoly tradition follows earlier materialist forms of constitutionalism in viewing the concentration of private power as equally dangerous (Andrias 2015; <a href="https://www.law.berkeley.edu/files/csls/FISHKINFORBATH-THEANTI-OLIGARCHYCONSTITUTIONBERKELEYCSLS2014OCT.pdf">Fishkin and Forbath 2014;</a> <a href="https://yalelawjournal.org/pdf/e.710.Khan.805_zuvfyyeh.pdf">Khan 2018</a>). After all, problems of capture arise not from the existence of public power as such, but from its relationship to private interests.</p>
<p><span class="credit">        <a href="https://www.samuelbagg.com/book" taget="_blank">— Samuel Ely Bagg,<br />&quot;The Dispersion of Power, Chapter 6.1&quot;</a>      </span>    </p></blockquote><p></p>
<p><a href="https://www.penguinrandomhouse.com/books/691177/the-age-of-extraction-by-tim-wu/">Tim Wu charts this history of antitrust thinking,</a> noting that:</p>
<blockquote>
<p>Back in the 1950s and 1960s, the anti-monopoly enforcers were of a different and much tougher mindset. They were closer in disposition to Theodore Roosevelt and tended to see the stakes of anti-monopoly as transcending mere economics and spilling into questions of democracy and political destiny. Influenced by the recent experience of the Second World War, American officials believed that fascism and corporate monopoly were linked. They feared that excessive corporate power would bleed into fascism or contribute to a communist uprising. Famed antitrust enforcer Thurman Arnold blamed German monopolies for helping Hitler rise to power.</p>
<p><span class="credit">        <a href="https://www.penguinrandomhouse.com/books/691177/the-age-of-extraction-by-tim-wu/" taget="_blank">— Tim Wu,<br />&quot;The Age of Extraction, Chapter 2: Platformization&quot;</a>      </span>    </p></blockquote><p></p>
<p>Like Wu and other Brandeisian thinkers, Bagg finds counterweights to these corrosive forces useful, both structurally and specifically:</p>
<blockquote>
<p>Countervailing power is the natural complement to anti-monopoly. Both demands are set in motion by the insight that capture is most often perpetrated by certain hegemonic actors and groups — i.e., those with the most concentrated private power and organizational capacity — and that protecting the public interest thus entails special attention to those specific forces. Where anti-monopoly entails targeting their resources and organizational capacity directly, however, practices of countervailing power aim to support their opponents.</p>
<p><span class="credit">        <a href="https://www.samuelbagg.com/book" taget="_blank">— Samuel Ely Bagg,<br />&quot;The Dispersion of Power, Chapter 6.2&quot;</a>      </span>    </p></blockquote><p></p>
<p>The web is such a <a href="https://en.wikipedia.org/wiki/American_Capitalism">countervailing power,</a> bringing with it a large ecosystem of developers and publishers that can jump-start mobile contestability. Real browsers and web apps present a potent, <a href="https://www.sciencedirect.com/science/article/abs/pii/S0167718715000363">two-sided ecosystem competitor.</a> Because browsers feature <a href="https://www.sciencedirect.com/science/chapter/handbook/abs/pii/S1573448X06030317">low switching-costs compared with replacing phones</a>, and provide a standards-based, interoperable app platform, they carry maximum potential to disrupt the market-concentrating effects of app stores whose software catalogues are welded to specific OSes. These properties pose a credible threat to the smartphone duopoly's extractive, anti-competitive <em>status quo.</em> Indeed, we can expect real browser competition to finally make Apple and Google competitors. This can return economic surpluses to users and businesses, rather than the duopolist's shareholders.</p>
<p>A web liberated to compete has already demonstrated the power to align forces that erode gatekeepers' influence through competition between browsers and their engines. Interoperability and a grounding in <a href="https://www.w3.org/Consortium/Patent/">royalty-free standards</a> pairs with this competitive engine to expand the penumbra of capabilities that enable new entrants without simultaneously convincing all developers to build for a new OS.</p>
<p>Because browsers commoditise OS features, the competition between them — both internal to, and across the existing Android and iOS deployed base — grows a corpus of essential apps that any new entrant needs (<a href="https://infrequently.org/2024/03/why-browsers-get-built/#bridges">the Bridge Strategy</a>). Instead of forcing a new smartphone OS to convince every software house to build new apps for their new APIs (simultaneously), or to brave legal and technical threats as they implement Apple and Google's APIs wholesale, browsers and <abbr title="Progressive Web Apps">PWAs</abbr> shrink the missing software gap tremendously. Should browsers make hay on iOS and Android the way the <abbr title="The EU's Digital Markets Act">DMA</abbr>'s drafters hoped, new market entrants only need to port competent browsers (a much smaller lift) and fill in a greatly reduced app gap.</p>
<p>But even if a new competitor doesn't emerge thanks to the web, browsers discipline incumbents in-place by providing competition with their proprietary software ecosystem. When mobile OSes feature sustained browser competition, incumbents help expand the web's carrying capacity or risk marginalisation.</p>
<p>This dynamic played out in the 2000s and 2010s as Internet Explorer lost share to competitors thanks to Microsoft's under-funding. Firefox, Chrome, and Safari worked to expand the power of the web, pushing <abbr title="Internet Explorer">IE</abbr>'s once 90+% dominance to the curb while dramatically growing the list of tasks users turn to the web for. Eventually, Microsoft capitulated, switching to Chromium to regain compatibility with a dynamic, growing web that threatened to pass it by.</p>
<p>Proprietary incumbents prioritise user needs over their own extractive agendas when competition from open ecosystems is enabled by low switching costs.<sup class="footnote-ref"><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fn-new-phone-who-dis-2" id="fnref-new-phone-who-dis-2">2</a></sup> This paves the way for competitors, <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">expanding the power and relevance of low-cost, interoperable technology with each competitive iteration.</a> We have seen the web's wedge work against API enclosure on the desktop, with a large majority of all new desktop software being written first as web applications and only later (and optionally) wrapped in WebViews to deliver needs from a shrinking set of &quot;last mile&quot; capabilities that the web doesn't provide out of the box.</p>
<p>Such is the power of interoperability made manifest; it's far past time for the tech press and regulators to speak clearly about the anti-web game the duopolists are playing to prevent the web from breaking out.</p>
<h2 id="shared-premises" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#shared-premises">Shared Premises</a></h2>
<p>Several points are plain to anyone engaged in mobile ecosystems. There are many sub-points to quibble about, and various parties talk their own books, but the broad strokes are accepted by all sides:<sup class="footnote-ref"><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fn-alternative-formulations-3" id="fnref-alternative-formulations-3">3</a></sup></p>
<ul>
<li>The web provides a portable and (potentially) capable way to deliver software.</li>
<li>Every contemporary phone with a touch screen has more than enough computing power to run full-fledged browsers that can support capable web apps.</li>
<li>Yet the smartphones almost every wealthy person carries support only <a href="https://infrequently.org/2021/04/progress-delayed/">less-capable,</a> <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">lower-quality</a> browsers.</li>
<li>This suppresses the web's relevance through compounding wealth and quality effects.</li>
</ul>
<p>A publicly contested (but privately conceded) corollary is that the web is not dominating mobile the way it does desktop because it has not been allowed to compete. From Apple <a href="https://infrequently.org/2021/04/progress-delayed/">explicitly suppressing competing browsers</a> and <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">breaking critical features OS-wide on the regular</a>, to Google's history of discouraging internal teams from writing mobile web apps and <a href="https://open-web-advocacy.org/es/blog/google-must-share-the-ability-to-install-web-apps-in-android/">denying competing browsers access to critical <abbr title="Progressive Web App">PWA</abbr> features,</a> the fix has been in for 15 years.</p>
<p>Apple and Google's anti-competitive policies keep web apps from threatening the foundations of their App Store revenues by forcing developers to build to the APIs that the incumbents control. This grounding in Apple and Google's proprietary APIs is the root of the duopolist's power. They use it in combination with threats and promotional inducements from their stores to enlist developers in promoting features of the hardware and services they monetise.</p>
<p>Open, interoperable, safe-by-default runtimes with standardised APIs threaten the foundations of this structure by breaking the duopolist's chokehold over software distribution. Browsers, and their core function of abstracting away the proprietary APIs of OS vendors, create a tax-free zone outside the grasp of the OS incumbents' mafioso App Store tactics. To ensure the web cannot threaten the API enclosure today's mobile ecosystems are founded on, browser competition must be suppressed and browsers themselves incapacitated.</p>
<p>That Apple has managed to pull this off is a scandal. But our tech press and commentariat do not cover the web as a true threat to App Stores. Instead, they <a href="https://www.techpolicy.press/as-competition-enforcers-gather-they-should-open-the-app-store-gates/">fixate on alt stores as a mechanism to supplant gatekeeper control.</a> This is a gift-in-kind to the duopolists. By failing to acknowledge the power of the web to disrupt entrenched OSes (as demonstrated by the past 20 years of desktop computing), the press are failing to communicate the stakes of regulatory failure to enable browser competition. This, in turn, excuses woolly regulators as they squander the ripest opportunity for reform in living memory.</p>
<h3 id="alt-stores%2C-pwas%2C-and-the-app-store-endgame" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#alt-stores%2C-pwas%2C-and-the-app-store-endgame">Alt Stores, <abbr title="Progressive Web Apps">PWAs</abbr>, and the App Store Endgame</a></h3>
<p>The dream of the alt store is a mirage, or at least a distraction. Windows is able to sustain several successful native app distribution systems in addition to Microsoft's own (e.g., Steam and The Epic Games Store), but these systems are tied to specific verticals and the APIs desktop developers target are <em>de facto</em> open and stable. The incumbent's app stores have significantly larger scope and tie together a host of services that require critical mass to disrupt.</p>
<p>The web presents one of the only ecosystems with enough existing use and investment to plausibly re-create a substantial fraction of this ecosystem value without the cold-start problem. Other challengers face a daunting choice: focus on a less expansive vision by diverting into narrow app categories, or depend heavily on OS services and APIs. Either option reduces contestability and detracts from the potential for a successful, interoperable mobile software ecosystem.</p>
<p>Browsers provide an alternative. Because they synchronise payment instruments, identity, and user preferences over the top of the OS, users experience reduced friction when transferring to the web versus a competing native ecosystem. And because most folks already invest a significant fraction of their digital lives with their browser, apps that run on the web are a more credible threat to the <em>status quo</em> than alt stores filled with native apps that must choose between rebuilding all of this from scratch or buttressing the lock-in of OS vendors.</p>
<p>Regulators facing choices about where to invest scarce resources should foreground browser engine choice and web apps because they create mass behind their agenda and bring a powerful, pre-existing ecosystem to bear. The alternative is <a href="https://www.theverge.com/news/693512/apple-eu-dma-app-store-concessions">playing whack-a-mole with gatekeepers</a> over easily divide-and-conquered alt stores.<sup class="footnote-ref"><a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fn-easily-confounded-4" id="fnref-easily-confounded-4">4</a></sup> Once browser-based apps can address the bulk of the market, the lift required to institute fair distribution terms in other verticals will be substantially reduced.</p>
<p>Instead of promulgating proprietary APIs, the web provides an answer to regulators' central problem: how to bootstrap an ecosystem of interoperable software?</p>
<p>Capable browsers are the proven answer. Unleashed by aggressive policy intervention a quarter century ago, <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">the web has become the most abundant app store of all time.</a> As the D.C. Circuit Court predicted in finding against Microsoft in 2001:</p>
<blockquote>
<p>...were middleware to succeed, it would erode the applications barrier to entry. Because applications written for multiple operating systems could run on any operating system on which the middleware product was present with little, if any, porting, the operating system market would become competitive. Id. p p 29, 72.</p>
<p>But as the District Court found, middleware will not expose a sufficient number of APIs to erode the applications barrier to entry in the foreseeable future.</p>
<p><span class="credit">        <a href="https://law.justia.com/cases/federal/appellate-courts/F3/253/34/576095/#:~:text=Of%20course%2C%20were,p%2028%2D29." taget="_blank">— US D.C. Circuit Court, Per Curiam,<br />&quot;U.S. v. Microsoft Corp., 253 F.3d 34 (D.C. Cir. 2001)&quot;</a>      </span>    </p></blockquote><p></p>
<p>What the court failed to understand in 2001 was that Microsoft had <em>already</em> made the browser a complete platform. Even after Redmond disbanded the <abbr title="Internet Explorer">IE</abbr> team after the 6.0 release, it would go on to midwife applications like Google Maps, GMail, and Google Docs; in its zeal to see off Netscape, Microsoft sowed the seeds of Win32's irrelevance. Firefox, Chrome, and (yes) Safari built on the momentum, <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">unlocking adjacent possibilities</a> that brought new categories into the web at a rapid clip. Today, design, CAD, software development, and scientific computing regularly happen in-browser and more than 70% of desktop &quot;jobs to be done&quot; are now handled on the web.</p>
<p><abbr title="Progressive Web Apps">PWAs</abbr> complete the story for the mobile era, unlocking participation in the tap-and-swipe ecosystem today's duopolists are working enclose through app stores. Just like a quarter century ago, the web is <em>already</em> the answer; we just need to clock it as such and legalise powerful browsers.</p>
<p>So-called alt stores are a less compelling solution because they hold less power to create competition with low switching costs. Instead of providing developers with standardised APIs, they continue to weave the duopolist's proprietary technologies and services into each app. This reduces app portability, increases developer costs, and implicitly helps to build a moat against new OS entrants. A hat-trick of lock-in.</p>
<p>Instead of settling for a world in which alternatively distributed apps must attempt to re-create the technical foundations of interoperability for themselves, regulators can win both interoperability and momentum for their efforts by unblocking real browser choice and <abbr title="Progressive Web Apps">PWAs</abbr> enabled by it. Browser engine projects feature large teams whose entire job is to intermediate between OS-specific APIs and web apps, enabling developers to write to a single interoperable platform out of the box.</p>
<p>The opportunity to harness both a large ecosystem of developers used to building for an interoperable platform, and teams of C++/Rust engineers accustomed to competing to provide improvements to that interoperable platform should have rocketed the web to the forefront of every regulator's thinking. The new powers that <a href="https://digital-markets-act.ec.europa.eu/index_en">the EU's <abbr title="The EU's Digital Markets Act">DMA</abbr>,</a> the <a href="https://en.wikipedia.org/wiki/Digital_Markets,_Competition_and_Consumers_Act_2024">UK's DMCCA,</a> and <a href="https://www.csis.org/blogs/charting-geoeconomics/starting-competition-japans-mobile-software-act">Japan's MSCA</a> provide in theory need concrete enforcement actions to bring the duopolists to heel, and the web's advantages in efficiency of regulatory intervention, reduction in security risk, and pre-existing cross-OS interoperability are unparalleled.</p>
<h2 id="regulators-are-missing-the-ripest-opportunity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#regulators-are-missing-the-ripest-opportunity">Regulators Are Missing The Ripest Opportunity</a></h2>
<p>It pains me deeply to acknowledge that the institutions handed new powers by <a href="https://digital-markets-act.ec.europa.eu/index_en">the <abbr title="The EU's Digital Markets Act">DMA</abbr>,</a> <a href="https://en.wikipedia.org/wiki/Digital_Markets,_Competition_and_Consumers_Act_2024">the DMCCA,</a> and <a href="https://www.csis.org/blogs/charting-geoeconomics/starting-competition-japans-mobile-software-act">the MSCA</a> are universally failing to prioritise the transformative power of browsers as they work to enforce the provisions of these laws. Instead of focusing fire on the lowest-risk, highest leverage intervention, regulators are being side-tracked and talked down from pursuing aggressive browser choice enforcement.</p>
<p>Consider Apple's opening offer to the EU. The <abbr title="The EU's Digital Markets Act">DMA</abbr> only allows gatekeepers to <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?toc=OJ%3AL%3A2022%3A265%3ATOC&amp;uri=uriserv%3AOJ.L_.2022.265.01.0001.01.ENG#:~:text=4.%C2%A0%C2%A0%C2%A0The%20gatekeeper%20shall%20allow%20and%20technically,settings%20are%20duly%20justified%20by%20the%20gatekeeper.">impose necessary and proportional security restrictions</a> on competing browsers and their engines.</p>
<p>Regardless, Cupertino <a href="https://developer.apple.com/contact/request/download/web_browser_engine.pdf">larded up its package of <abbr title="The EU's Digital Markets Act">DMA</abbr> deliverables with terms for building browsers that include clearly unlawful contractual obligations (pdf)</a> having nothing to do with security. These restrictions <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">levy costly and unworkable demands on the architecture of competitors' products.</a> Alternative browser engines have long featured better security, performance, extensibility, and even privacy than Safari. Should they <em>not</em> be superior, the <abbr title="The EU's Digital Markets Act">DMA</abbr> provides a straightforward solution: competition, rather than legal arm-twisting.</p>
<p>In case procedural hurdles weren't enough disincentive, Apple also hobbled its browser SDK, omitting support for obviously in-scope features including the ability to handle in-app links, support web apps on the home screen, and disambiguate push notifications. It has built and shipped all of this for Safari, in some cases relatively recently, so it wasn't a case of forgetfulness. Brushed back from <a href="https://infrequently.org/2024/02/home-screen-advantage/">attempting to murder web apps</a> on the eve of <abbr title="The EU's Digital Markets Act">DMA</abbr> enforcement, Apple simply chose to duck complying with the law by <a href="https://www.apple.com/newsroom/2024/01/apple-announces-changes-to-ios-safari-and-the-app-store-in-the-european-union/">dressing up violation in umbrage and legalese.</a></p>
<p>Cupertino's design carefully omits the capabilities that would unlock direct competition with the app store, safe in the knowledge that so long as Safari is the only browser with access, it can <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">keep the web hobbled and broken.</a> This is a blatant affront to the <abbr title="The EU's Digital Markets Act">DMA</abbr>'s plain meaning and <a href="https://op.europa.eu/en/publication-detail/-/publication/21dc175c-7b76-11e9-9f05-01aa75ed71a1/language-en">legislative intent,</a> and dovetails with extralegal attempts to apply maximum pressure on the EC to accept less than half a loaf.</p>
<p>Recall that Apple initially argued that it <a href="https://infrequently.org/2024/02/home-screen-advantage/#:~:text=To%20comply%20with,all%20very%20unfair.%22">didn't have time to comply given a mere two-year run-up.</a> It was enough time for all of Apple's competitors, but somehow not for the self-proclaimed titans of software from Cupertino.</p>
<p>That was two years ago.</p>
<p>Has the offer improved regarding these strategic omissions? Not one iota.</p>
<p>Indeed, Apple is now lying to our faces; from its latest <abbr title="The EU's Digital Markets Act">DMA</abbr> compliance report (emphasis added):</p>
<blockquote>
<p>(45) <strong>For the purposes of allowing alternative web browser engines to interoperate with iOS and iPadOS, Apple makes a suite of functionalities available so that browser apps and apps providing in-app browsing using alternative browser engines can be installed and run on iOS and iPadOS in the EU.</strong> Apple provides authorized developers access to technologies within the system that enable critical functionality and help developers leverage high-performance modern browser engines. These technologies include Just-in-Time compilation (which provides performance benefits by helping browsers to quickly and efficiently render JavaScript content), multiprocess support, and more. <strong>Third-party browser apps using third-party web browser engines can support and run web apps.</strong></p>
<p><span class="credit">        <a href="https://www.apple.com/legal/dma/NCS-March-2026.pdf" taget="_blank">— Apple, March 7, 2026 (pdf),<br />&quot;<abbr title="The EU's Digital Markets Act">DMA</abbr> Compliance Report Summary, Page 201, Section V.&quot;</a>      </span>    </p></blockquote><p></p>
<p>This misleading text suggests that Apple has provided APIs to competitors to support these core use-cases through their own engines; it manifestly has not.</p>
<h3 id="cupertino-is-running-circles-around-brussels%2C-tokyo%2C-and-london" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#cupertino-is-running-circles-around-brussels%2C-tokyo%2C-and-london">Cupertino is Running Circles Around Brussels, Tokyo, and London</a></h3>
<p>Faced with such strategic flouting of these the law, one might assume regulators with a sense of their own prerogatives and legislative intent might respond with overwhelming force.</p>
<p>Instead, the <abbr title="The EU's Digital Markets Act">DMA</abbr> team at the EU have moved haltingly as Apple plays for time through processes the EC <a href="https://ec.europa.eu/competition/digital_markets_act/cases/202523/DMA_100204_2073.pdf">forced Cupertino to create after previous bouts of transparent gamesmanship (pdf).</a> Clear, <a href="https://issues.chromium.org/hotlists/5909213">unambiguously in-scope requests from competitors languish</a> while the Commission settles for tweaks that cannot change the balance of power. Far from fulfilling the law's legislative intent, contemporary <abbr title="The EU's Digital Markets Act">DMA</abbr> enforcement appears unable to prioritize action that will unleash the tools of revolution from action on necessary-but-insufficient nips and tucks.</p>
<p>Rather than treating Apple's belligerent, maximalist strategy as a joined-up attack aimed to deny oxygen to the most effective competing ecosystem, the <abbr title="The EU's Digital Markets Act">DMA</abbr>'s enforcement group has ratified Apple's redrawn boundaries through studious inaction. Like Sykes and Picot with a ruler, Apple has drawn lines that favour its interests above all else, and authorities that could countermand its declarations are notable only by their absence. The perspective from Brussels seems to be that these questions are now simply competing claims by equally mucky mud wrestlers, rather than galling non-compliance and an affront to the point of the <abbr title="The EU's Digital Markets Act">DMA</abbr>.</p>
<p>Rather than bearing down on structural issues, regulators appear immersed in dense debates with the scofflaw's counsel over inconsequential details. Even in <a href="https://www.npr.org/2025/04/23/nx-s1-5373560/apple-meta-eu-tech-fines">the areas that it is levying fines, the EC is not challenging the structure of Apple's power.</a> This is tantamount to settling for minor tweaks on the <em>status quo.</em> If the <abbr title="The EU's Digital Markets Act">DMA</abbr> was designed to redress <a href="https://eur-lex.europa.eu/eli/reg/2022/1925/oj/eng#:~:text=In%20particular%2C%20online,their%20own%20purposes.">the problems it enumerates,</a> this is failure by the EC's own yardstick. We're entering year three of <abbr title="The EU's Digital Markets Act">DMA</abbr> enforcement, and meaningful change is not obviously closer. Why not?</p>
<p>To hear the regulator's apologists tell it, they're concerned with litigation. Litigation! <a href="https://www.euractiv.com/news/apple-challenges-european-commissions-unreasonable-demands-in-court-appeal/">As though Apple wouldn't sue regardless.</a></p>
<p>No amount of punch-pulling or case-buttressing will prevent Cupertino from rolling out its shockingly large army of lawyers. <em>Apple <strong>already</strong> <a href="https://venturebeat.com/technology/apples-former-top-lawyer-1-billion-budget-enabled-high-risk-strategies">spends more on lawyers every year</a> than the fines the EU is proposing!</em></p>
<p>This is the same company that used lawyerly nonsense <a href="https://open-web-advocacy.org/blog/cma-reopens-investigation-into-apple/">to hold up the UK CMA's investigation for nine months,</a> implausibly arguing the regulator hadn't brought the boom down fast enough on its own bad behaviour, and therefore couldn't do so later. It was never a serious argument, but when dressed up in enough £1000/hr legalese, Apple's calculated attempt to create delay paid massive dividends. Nine months of regulatory delay is worth <em>many billions</em> to Cupertino.</p>
<p>Apple is conducting a maximalist <a href="https://infrequently.org/2022/02/minimum-standards/">campaign against the very concept of the rule of law when its profits are at risk,</a> and having paid off a deeply corrupt US administration, the intensity and reach of that campaign is <a href="https://www.ft.com/content/b6d9fb9c-901e-42e3-9610-5a449247fd49">only increasing.</a> All of this should create a deep, abiding suspicion of Cupertino's motives, removing the benefit of the doubt wherever it claims contestability is a reality on iOS. No self-respecting regulator can take anything Apple's lawyers say at face value in 2026. But there's only a price for duplicity when those with authority recognise the pattern and apply suspicion, rather than deference.</p>
<p>Regulators (not to mention the press) are well within their rights to take on board Apple's misrepresentations, <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">astro-turfing,</a> and serial non-compliance when calculating how aggressively to act. Instead, the EU's <abbr title="The EU's Digital Markets Act">DMA</abbr> team, the UK's CMA, and Japan's regulators are falling for the same shenanigans over and over; treating each encounter as a blank slate, happy to pretend a disquieting history of belligerent non-compliance is immaterial to arguments offered today.</p>
<p>This is both a tactical error and a strategic blunder.</p>
<p>At a tactical level, extending deference to each new pile of misdirections allows Cupertino to play for time; when you're the incumbent, delay is winning, and regulators that do not demand prompt changes weaken their own future hand. Strategically, failure to demand changes <em>right bloody now</em> in the face of material non-compliance denies the regulator the benefit of even a weak <a href="https://en.wikipedia.org/wiki/Fleet_in_being">fleet in being effect.</a> And declining to demand immediate change in areas most likely to create the deepest, most generative effects grants Apple ongoing regulatory relief in the form of reduced structural competition.</p>
<p><em>Of course</em> it harms EU businesses that they cannot target a platform across mobile OSes, and that EU businesses instead have to bear high ongoing development and servicing costs to participate in proprietary app stores. It is <em>obviously</em> negligence on the part of newly empowered regulators to allow Apple's gerrymandering attempts. Cupertino has worked to draw constrictive borders around browsers for the last several years; demarcations that <em>just happen</em> to exclude capabilities that would make mobile computing truly contestable.</p>
<h2 id="browsers-are-app-stores" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#browsers-are-app-stores">Browsers Are App Stores</a></h2>
<p>Since regulators and the tech press are not connecting the dots from first principles, desktop computing analogues, <a href="https://law.justia.com/cases/federal/appellate-courts/F3/253/34/576095/#:~:text=Of%20course%2C%20were,p%2028%2D29.">legal precedent,</a> or the lengths Cupertino has gone to prevent the web from breaking out, it must be repeated:</p>
<p><em><strong>Browsers are app stores.</strong></em></p>
<p>If we want effective alternatives to the gatekeeper's app shops, nothing will be more effective than unleashing real competition from the web. Browsers are stores filled with <em>a priori</em> interoperable software and with low friction installation thanks to <abbr title="Progressive Web Apps">PWAs</abbr>! And they <a href="https://open-web-advocacy.org/blog/break-googles-search-monopoly-without-breaking-the-web/#:~:text=Web%20apps%20run%20securely%20within%20the%20browser%E2%80%99s%20sandbox%2C%20recognized%20by%20even%20Apple%20as%20%E2%80%9Corders%20of%20magnitude%20more%20stringent%20than%20the%20sandbox%20for%20native%20iOS%20apps%E2%80%9D.">feature <em>incredible</em> security!</a> Protections so strong that you don't even have to <a href="https://appleinsider.com/articles/20/08/23/apple-versus-epic-games-fortnite-app-store-saga----the-story-so-far#:~:text=It%20also%20attacks%20assertions%20that%20the%20App%20Review%20process%20is%20robust%2C%20referring%20to%20internal%20documents%20in%20which%20Apple%27s%20head%20of%20Fraud%20Engineering%20Algorithms%20and%20Risk%2C%20Eric%20Friedman%2C%20likened%20App%20Store%20defenses%20to%20%22bringing%20a%20plastic%20butter%20knife%20to%20a%20gunfight.%22">hang a <em>&quot;beware of dog&quot;</em> sign out front.</a></p>
<p>Should we collectively accept this premise and expand our understanding of software contestation to include the web as a viable alternative in the app store story, <em>what would that mean</em>? The duopolists are working overtime to silo the discussion to their preferred proprietary technologies, <em>why</em>? Is that worthy of investigation and discussion?</p>
<p>For regulators, this perspective is a treasure map. Enabling true browser competition unlocks both internal and cross-OS competitive forces, unleashing firms with an interest in interoperability on both sides of the browser market. But for regulators to get credit for converting on this incredible opportunity, their constituents will need to hear about it. And on that front, we've got a lot of work to do.</p>
<h2 id="our-tech-press-is-missing-the-story%2C-too" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#our-tech-press-is-missing-the-story%2C-too">Our Tech Press is Missing the Story, Too</a></h2>
<p>We get plenty of TopGear-but-for-phones and <a href="https://karlbode.com/the-press-is-still-propping-up-elon-musks-supergenius-engineer-mythology/"><em>&quot;CEO said a thing&quot;</em></a> coverage, but very little coverage of the way access to APIs shapes our digital lives. Most outlets still <a href="https://infrequently.org/2025/09/apples-antitrust-playbook/#dear-tech-reporters%3A-access-is-not-a-beat">treat access like it's a real beat,</a> depriving them of the distance necessary to contextualise the duopolists' actions in a frame their PR staff dislike. The closer a publication gets to the mainstream, the worse the distortion seems to get.</p>
<p>Few tech outlets, including irreverent youtubers, seem to recognise that the web is the single biggest threat to mobile app stores, opting instead to cover minor news of alt stores tremors like The Big One. This misleads readers about the stakes and distorts the incentives of regulators.</p>
<p>Reporting that borrows the narrative frame the duopolists prefer enlists otherwise excellent outlets as allies of the billionaire class. Too many reporters uncritically accept that app stores are how we must think about mobile software, regurgitating this narrative through stories filed in a browser on their laptops. Apple, Google, and the handful of &quot;winners&quot; the app stores bless profit massively from centralisation. Reporters and editors further the goals of the broligarchs by failing to reframe mobile competition in a more historically grounded light.</p>
<p>Perhaps regulators will find their way without the help of a thoughtful, tenacious tech press; stranger things have happened. But judging by The Verge, Wired, and the FT, they're going to need all the luck in the world.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-co-monpoolists-1" class="footnote-item"><p>Understood through <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#average-selling-prices">the lens of price segregation,</a> we can see that there is no real competition between Android and iOS. For more than a decade, the mobile market has presented a pantomime of competition, wherein all wealthy users buy iPhones and everyone else buys Androids, while OEMs not named Apple continue to send low-volume &quot;halo&quot; Android devices to reviewers to keep up the appearance that they are somehow a challenge to Apple's dominance of the high-margin premium and ultra-premium market segments.</p>
<p>Apple and Google preside over stable co-monopolies, separated like oil and water by point-of-sale device pricing. Both understand the other will not challenge the market's segmentation, buttressed by incompatible proprietary software and services ecosystems.</p>
<p>For Apple, this assurance comes from the financial model for its entire enterprise. Apple does not enter lines of business where it cannot guarantee at least 30% net margin. This is a stable property of Apple's behaviour that market analysts now rely on. Any deviation from trend would not enhance Apple's market value as it expanded its market sized, but would paradoxically discount its shares by reducing traders' ability to understand Cupertino’s imputed future profits per share.</p>
<p>Google, for its part, doesn't understand the profitability bear trap Apple finds itself in, and fears Cupertino might release a low-margin iOS device, wiping out what little profit remains in the Android ecosystem. The Android and Pixel teams yearn to see and Android-based &quot;iPhone Killer&quot;. For similarly structural reasons, they never will.</p>
<p>The Pixel brand cannot succeed because the firm will never allocate enough capital to make vertically integrate and generate scale for sales. This leaves it — along with the rest of Android ODMs — without sufficient leverage and integration discipline to produce devices with similar quality, longevity, and post-sale monetisation upside. Because Android OEMs lack the same low-<abbr title="Stock Keeping Unit, or an individual item with a price">SKU</abbr>-count concentration of buying and production scale, profits never materialise for a promising device. Apple might only have 20% of the market, but it pours that entire volume into a small number of custom high-volume orders. From CPUs to screens to custom connectors, Cupertino always buys in extreme volume.</p>
<p>Android OEMs, meanwhile, split their purchasing across hundreds of <abbr title="Stock Keeping Units">SKUs</abbr>, and most have smaller war chests than Google and worse prospects for vertical integration. As long as Qualcomm has everyone over the barrel (and they do), it will never be possible for an Android OEM to break the structure of the duopoly. Android is therefore destined to define low-margin devices. Knowing this drags all Android participants away from post-sale quality improvements that might allow the ecosystem to aspire to better. This sucks for OEMs and ODMs, but the volume of the business makes the structure stable, and for some, comfortable. <a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fnref-co-monpoolists-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-new-phone-who-dis-2" class="footnote-item"><p>It's no coincidence that Apple's basic stance towards browser competition is that you can have a better mobile browser, you just need to buy a different phone, suffer the loss of all of your Apple-ecosystem services and data, and worry about the availability of important apps.</p>
<p>High and uncertain switching costs are core to Cupertino's suppression of browser competition, and it's bewildering that neither the tech press nor regulators seem to have clocked the gambit for what it is. <a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fnref-new-phone-who-dis-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-alternative-formulations-3" class="footnote-item"><p>There are, of course, multiple ways to speak about these undisputed facts, and native app partisans are particularly practised at their variant of three-card monty.</p>
<p>When pressed, some begin reciting a list of missing <abbr title="Progressive Web App">PWA</abbr> capabilities. This is offered as a reason to prefer native apps, and a reason why web apps are &quot;not serious&quot;.</p>
<p>If handed evidence that open, interoperable versions of these features are not available because of Apple's suppression, they will claim that it is not safe for browsers to offer them. This is often couched as evidence of Cupertino's far-reaching wisdom.</p>
<p>Evidence that Apple's alternate — authoritarian control over APIs and software distribution — has not been particularly safe is usually dismissed out of hand. Point out that most energy invested in APIs over the past decade has worked to attenuate their power to the position browsers begin the bidding, and native app partisans reframe this work as proof of the necessity of gatekeepers, rather than evidence of their frequent fallibility.</p>
<p>There are also generally digressions into privacy, where native app fans seem unable to understand that it was the duopolists that provided unfettered access to shocking amounts of invasive data to native apps <em>by default</em>. Despite performative curbs, this situation largely persists, facilitated <em>by the gatekeepers</em>. The idea that we should trust them <em>now</em>, when they are the same unrepentant players that took shockingly little care when handing unrestricted APIs to tech's worst actors, is generally parried with <em>&quot;but Facebook bad!&quot;</em>. <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">Kayfabe</a> is treated as serious drama. The deeper complicity is not engaged, and this line of inquiry is generally fruitless. Many wear the brand of phone in their pocket like a jersey for their favourite team, not a complex business with many incentives and cross-pressures.</p>
<p>These counterparties are also generally unfamiliar with the ads ecosystem and how the native duopolists created a &quot;snoopers gap&quot; that generated pressure for ad-funded apps to push users away from more privacy-respective, adblock-enabling browsers, and towards less mediated and transparent native app alternatives. The reality that those prompts were not the result of an intrinsic <em>positive</em> technology difference is not seriously entertained.</p>
<p>The web has a long track record of protecting users more effectively on both privacy and security than native API monocultures, and providing extension points to allow users to further shield themselves without waiting on beneficent App Store proprietors. Should that reality make a dent, the next conversational shuffle turns to browsers not <em>already</em> having won the field. This is couched either as evidence of some ineffable technical inferiority on the web's part or a claim for why it wouldn't be possible for a transition to start now; never mind that both Windows and macOS made similar turns on a similar time scale. It is never accepted as evidence of active suppression of the web by the gatekeepers.</p>
<p>Which brings us back to the start of the game.</p>
<p>Having played many pointless rounds with folks who, on the surface, seemed open to discussing the issue, I can only recommend checking to see what sort of phone your counterparty carries before wading in. iOS partisans are particularly attached to the idea that Apple knows best. It is often counterproductive to engage, no matter how loudly they claim to support the web.</p>
<p>One of the benefits of being locked in the privilege bubble, after all, is freedom from introspection. Wealth's blanket soothes the anxieties of the status-seeking mind, and supporting the nonsensical positions by those with higher status is imagined to be a harmless bit of in-group signalling. <a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fnref-alternative-formulations-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-easily-confounded-4" class="footnote-item"><p>It didn't take a genius to predict that a successful alt store would prod the duopolists to make life inhospitable for developers trying to straddle open ecosystems where they are available and gatekeeper options where they aren't. The unpredictable element was that Apple <a href="https://www.theverge.com/news/636196/apple-eu-dma-probe-alternative-app-stores-tax">played those cards before a store even got going in earnest.</a> <a href="https://infrequently.org/2026/04/the-web-is-an-antitrust-wedge/#fnref-easily-confounded-4" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Naked Power</title>
    <link href="https://infrequently.org/2026/01/naked-power/"/>
    <updated>2026-01-20T00:00:00Z</updated>
    <id>https://infrequently.org/2026/01/naked-power/</id>
    <content type="html"><![CDATA[
      <p>Twitter's descent into a gutter of the lowest order has been <a href="https://www.theatlantic.com/technology/2026/01/elon-musk-cannot-get-away-with-this/685606/?gift=VjLv3Dd1h8jJ03YjTtjfrXZwxMfoYP94XM2xrWOrT6A&amp;utm_source=copy-link&amp;utm_medium=social&amp;utm_campaign=share">wrenching</a>:</p>
<p><lite-youtube videoid="EDzZjBXOI8U" videotitle="Elon Musk’s Grok and the Mass Undressing Scandal" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=EDzZjBXOI8U">Elon Musk’s Grok and the Mass Undressing Scandal</a>        <img src="https://i.ytimg.com/vi_webp/EDzZjBXOI8U/hqdefault.webp" alt="Elon Musk’s Grok and the Mass Undressing Scandal" slot="image" />      </lite-youtube></p>
<p>As I draft this, a week later, it appears pressure from civil society, <a href="https://www.theguardian.com/technology/2026/jan/12/ofcom-investigating-x-outcry-sexualised-ai-images-grok-elon-musk">investigations by regulators</a>, and <a href="https://www.nytimes.com/2026/01/11/world/asia/malaysia-indonesia-grok-ban.html?unlocked_article_code=1.F1A.q-wN.cs7_YcuZJvKU&amp;smid=url-share">outright bans</a> on multiple continents <a href="https://www.bbc.com/news/articles/ce8gz8g2qnlo">have forced Musk to back down to an uncertain degree.</a></p>
<p>As this scandal roiled, Twitter's apps have been continuously available in <a href="https://play.google.com/store/apps/details?id=com.twitter.android&amp;hl=en_US">Google's Play</a> and <a href="https://apps.apple.com/us/app/x/id333903271">Apple's App Store,</a> marking new lows in moral cowardice and non-enforcement of <a href="https://www.bbc.com/news/technology-46275138.amp">the duopolist's own policies.</a></p>
<p>Now we sit on tenterhooks, <a href="https://www.bloomberg.com/news/features/2026-01-19/grok-ai-sexualized-images-expose-gaps-in-oversight-enforcement">wondering if the worst has actually passed.</a> What outrage the will the valley's billionaire man-children unleash next? Meanwhile, we brace for this episode to embolden <a href="https://www.theguardian.com/us-news/2025/dec/18/tennessee-charlie-kirk-meme-arrest-lawsuit">censorious authoritarians</a> keen to suppress a free press and legitimate speech they dislike.</p>
<p>This is the backdrop to <a href="https://www.theverge.com/policy/859902/apple-google-run-by-cowards">Elizabeth Lopatto's must-read denunciation in The Verge</a>:</p>
<blockquote>
<p>It is genuinely unbelievable to me that I wasted <strong>hours of my actual life</strong> on a court case where Apple explained it needed total control of its App Store to protect its users. Total control of the App Store was Apple’s main argument against antitrust enforcement: The company insisted that its monopolistic control of what users could install on their phones was essential to create a walled garden where it could protect children from unsafe content.</p>
<p>Ha! Ha ha ha!!</p>
<p><span class="credit">        <a href="https://www.theverge.com/policy/859902/apple-google-run-by-cowards#:~:text=It%20is%20genuinely,Ha%20ha%20ha!!" taget="_blank">— Elizabeth Lopatto,<br />&quot;Tim Cook and Sundar Pichai are cowards, The Verge&quot;</a>      </span>    </p></blockquote><p></p>
<p>Failure to react to the “everything app” going all-in on abuse of women and girls for weeks reveals the illegitimacy of their mobile monopolies<sup class="footnote-ref"><a href="https://infrequently.org/2026/01/naked-power/#fn-the-rich-and-the-rest-1" id="fnref-the-rich-and-the-rest-1">1</a></sup>; anyone pretending otherwise is a fool or a dupe.</p>
<p>We don't need to guess why they sat on their hands.</p>
<p>Acting against Musk's abusive apps might put Apple and Google out of favour with an <a href="https://www.theatlantic.com/ideas/2026/01/trump-letter-to-norway/685676/?gift=VjLv3Dd1h8jJ03YjTtjfrTNmTkJW3u5woT5x6t-touA&amp;utm_source=copy-link&amp;utm_medium=social&amp;utm_campaign=share">erratic, power-tripping administration</a> which in turn could impact short-term business prospects. Their stated principles are incompatible with maximizing shareholder value under competitive authoritarianism.</p>
<p>Recall that both firms <a href="https://www.wired.com/story/apple-took-down-ice-tracking-apps-their-developers-arent-giving-up/">lent their monopolies on software distribution to ICE,</a> citing the implausible claim that federal agents are a <a href="https://www.404media.co/google-calls-ice-agents-a-vulnerable-group-removes-ice-spotting-app-red-dot/">“vulnerable group.”</a> The undressing scandal is the same choice in relief.</p>
<p>Facilitating the unthinkable at the behest of <a href="https://www.usatoday.com/story/news/politics/2025/11/19/elon-musk-returns-white-house-trump-feud/87351192007/">administration allies</a> pays homage to power through obscenity. If they offend Musk…who knows what could happen? So maybe let it play out; let others take the heat. Surely <em>somebody</em> will do something. The internal monologue of the quisling scarcely needs exposition.</p>
<p>And so abuse at scale was amplified through their channels, against their own policies, for weeks.</p>
<h2 id="vertigo" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#vertigo">Vertigo</a></h2>
<p>The duopolist's justifications for monarchical app stores have always been bullshit, top to bottom, stem to stern.</p>
<p>App stores are not <em>sui generis</em>; they're just programs that install other programs, <a href="https://infrequently.org/2020/09/the-pursuit-of-appiness/">and &quot;apps&quot; are whatever the OS says they are.</a></p>
<p>As <a href="https://pluralistic.net/2023/11/13/this-is-for-everyone/#:~:text=Apps%20interact%20with%20law%20in%20precisely%20the%20way%20that%20web%2Dpages%20don%27t.%20%22An%20app%20is%20just%20a%20web%2Dpage%20wrapped%20in%20enough%20IP%20to%20make%20it%20a%20crime%20to%20defend%20yourself%20against%20corporate%20predation%22%3A">Cory Doctorow observed:</a></p>
<blockquote>
<p>Apps interact with law in precisely the way that web-pages don't. “An app is just a web-page wrapped in enough IP to make it a crime to defend yourself against corporate predation”</p>
</blockquote>
<p>It sure <em>looks</em> like Apple and Google failed to protect women and girls in order to preserve the rents they extract from the ecosystems these IP wrappers give them control over.</p>
<p>Gatekeepers like to point out that the wrapper comes with treats — business-critical capabilities and services that OS vendors lock behind proprietary APIs — but this is misdirection.</p>
<p>Web apps could provide safe, privacy-enhancing versions of every capability they currently reserve to native apps, and the duopolists know it. In an earlier era, open platforms chewed up proprietary features and spat out interoperable standards to cover the most useful 80% of that ground safely. Along the way, they published under open licences, dropping the price of commodity features to near-zero. This reduced lock-in for both developers and users which, in turn, forced incumbents to innovate.</p>
<p>Today's gatekeepers are desperate to keep that from happening again. It would upset the entire <em>rentier</em> model.</p>
<p>That's why Apple has worked furiously to keep APIs away from browsers through legal wrangling and <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/">subversion of standards.</a> Cryptography and lawyers have also been enlisted to keep other programs-that-install-programs out and a safe, powerful open web at bay. Without those shields, we'd see the deeper failures clearly.</p>
<p>Consider the justifications Apple and its <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">merry band of astroturfers</a> trot out like clockwork to delay browser choice. Cupertino argues it must exclusively control browsers and software distribution to:</p>
<ul>
<li>Ensure device security</li>
<li>Prevent frauds and scams</li>
<li>Provide a bulwark for privacy</li>
<li>Simplify software acquisition and distribution</li>
<li>Keep a lid on the most objectionable content</li>
</ul>
<p>Now we see clearly that protection on the last point comes not from the stores, but from civil society and governments. This provides a template: each justification is an admission; misdirection to cover culpability.</p>
<p>Let's take it from the top.</p>
<h3 id="the-security-argument" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#the-security-argument">The Security Argument</a></h3>
<p>Stores don't ensure security, runtimes do.</p>
<p>Operating systems and browsers — the platforms that sandbox code and mediate permissions — protect users to the extent they're designed to; app stores are just overwrought “beware of dog“ signs meant to scare off easily intimidated ne'er-do-wells. It's no surprise that whenever app stores are trusted with the role, a <a href="https://open-web-advocacy.org/blog/balancing-security-and-fair-competition/">trail of harrowing failure follows.</a></p>
<p>This unearths the lie behind the obfuscation: iOS and Android didn't create stores to deliver unheard of security — iOS 1.0 did that by forbidding unsafe native code, replacing it with a better web<sup class="footnote-ref"><a href="https://infrequently.org/2026/01/naked-power/#fn-cros-safety-2" id="fnref-cros-safety-2">2</a></sup> — the gatekeepers built app stores <em>because their OSes were and are insecure platforms for native apps.</em> <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/#:~:text=Web%20apps%20offer,as%20web%20apps.">When mobile apps were web apps,</a> the presumption of safety reigned. Alas.</p>
<p>Retreating from safety dovetailed with retreats from safe, open, interoperable computing in other ways. It's no coincidence that <a href="https://infrequently.org/2021/04/progress-delayed/">Apple backed away from adding capabilities to the web</a> at the same moment it realised it could tax native apps extortionately.</p>
<p>App stores are Marketing's answer to a brand-promise problem: what to do about a hole below the water line that Product and Engineering aren't just failing to patch, but are enthusiastically expanding instead?</p>
<p>The whole facade of the duopolist's power hinges on the false claim that stores create security. Without the need to paper over the disaster of <a href="https://www.npr.org/sections/thetwo-way/2017/08/29/547113818/uber-ends-its-controversial-post-ride-tracking-of-users-location">carelessly</a> dispensed power tools, none of the rest of the services the stores provide could be justified; certainly not at the ruinous prices they demand.</p>
<p><a href="https://security.apple.com/blog/memory-integrity-enforcement/">More recent, chest-thumping pronouncements</a> need to be evaluated in the same light. These aren't heroic explorers of new frontiers, they're embarrassed students bluffing book reports for tomes they didn't read.</p>
<p>Instead of protecting us, app stores reward platform vendors for security failure and foster centralising, anti-Open Source ecosystems. Open societies cannot abide closed platforms that assert ownership of this much of our lives, particularly not when claims of security are based on misrepresentations.</p>
<h3 id="frauds-and-scams" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#frauds-and-scams">Frauds and Scams</a></h3>
<p>In the narrow conception, the app stores are feckless. Taking a wider view, they're complicit. Enabling, even.</p>
<p>Under a strict definition of “fraud,&quot; the track record of app stores is abysmal. Take just one recent example: while <a href="https://www.apple.com/newsroom/2025/05/the-app-store-prevented-more-than-9-billion-usd-in-fraudulent-transactions/">loudly proclaiming to protect users from scams</a>, Apple <a href="https://9to5mac.com/2025/10/04/sora-2-clones-start-flooding-the-app-store-worldwide/">simultaneously facilitated wide-scale app impersonation at the launch of Sora.</a> This failure isn't a one-off, either. <a href="https://www.infosecurity-magazine.com/news/consumers-fake-mobile-banking-apps/">Bald-faced imposters are a long-running problem</a> for stores that pretend to both users and developers that they protect from <em>exactly</em> these sorts of scams.</p>
<p>For its part, Google <a href="https://news.drweb.com/show/review/?lng=en&amp;i=13118">routinely</a> facilitates <a href="https://thehackernews.com/2025/09/slopads-fraud-ring-exploits-224-android.html">shocking amounts of ad fraud</a> via Play. Stores also failed to catch <a href="https://appleinsider.com/articles/24/02/12/how-russian-banks-use-trojan-horse-apps-to-stay-in-apples-app-store">clearly fraudulent fronts for sanctioned Russian banks.</a> This is just the tip of the proverbial <a href="https://open-web-advocacy.org/blog/balancing-security-and-fair-competition/#apple's-decade-long-app-review-woes">iceberg.</a></p>
<p>If we widen the aperture to let in adjacent classes of user abuse, the situation looks immeasurably worse.</p>
<p>Apple's policies <a href="https://developer.apple.com/app-store/review/guidelines/#5.3.3">purport to disallow use of the ultra-low-friction <abbr title="In-App Purchase">IAP</abbr> systems for gambling:</a></p>
<blockquote>
<p>5.3.3 Apps may not use in-app purchase to purchase credit or currency for use in conjunction with real money gaming of any kind.</p>
</blockquote>
<p>This text is lawyered to sound like a curb on gambling addiction's worst effects. In reality, it's designed to facilitate the predatory “gambling lite” systems Apple and Google gleefully promote.</p>
<p>For most of the mobile duopoly's existence, <a href="https://www.revenuecat.com/blog/growth/consumer-apps-revenue-surpass-gaming-2025/">the primary revenue driver</a> has been the problematic, gambling-adjacent behaviour of <a href="https://stratechery.com/2014/dependent-digital-whales/">“digital whales”</a> in <a href="https://www.blog.udonis.co/mobile-marketing/mobile-games/mobile-games-whales">so-called “casual games.”</a></p>
<p>And don't imagine the <a href="https://revealnews.org/article/facebook-knowingly-duped-game-playing-kids-and-their-parents-out-of-money/">wilfully predatory behaviour is limited to adults.</a> By <a href="https://www.nytimes.com/2019/02/06/technology/personaltech/children-charges-mobile-games.html?unlocked_article_code=1.F1A.RNCo.krgLUJ5kBPcj&amp;smid=url-share">allowing “bait apps” — even after previous FTC settlements that should have forbidden them</a> — the app stores have shown us the duopolist's true colours. Serial disregard for the financial health of users is literally baked into their model.</p>
<p>This is the rotten core of mobile app stores. Understood in <abbr title="the Purpose Of the System Is What It Does">POSIWID</abbr> terms, they exist to tax casinos that exploit gambling addictions of vulnerable users.</p>
<h3 id="privacy" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#privacy">Privacy</a></h3>
<p>App stores safeguard privacy the way packs of wolves safeguard flocks of sheep.</p>
<p>The only appropriate response to the two-faced, duplicitous claims by Apple and Google towards privacy in recent years is incandescent rage.</p>
<p>I've covered before how <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">Apple's posturing against Facebook is nothing but kayfabe</a> and how Cupertino's privacy arguments regarding alternative browsers are <a href="https://infrequently.org/2024/07/misfire/#fn-a-truly-private-browser-4">steaming piles of illogical nonsense.</a></p>
<p>In reality, our privacy problems <a href="https://www.nytimes.com/2018/10/30/style/kids-study-apps-advertising.html?unlocked_article_code=1.F1A.HeHW.k4gdqf_xYS01&amp;smid=url-share">have been multiplied</a> <em>by Apple and Google</em>.</p>
<p>It was the duopolists that created APIs for persistent background access to your contacts, calendar, location, radios, battery levels, and much else besides. It was the duopolists that then turned around and claimed credit for incrementally curbing the worst abuses of the APIs they themselves handed out like candy. Remember, they added these easily-tracked features knowing full well they would be abused.</p>
<p>How do we know they knew better? Both exposed shocking amounts of information about users to all comers <em>after</em> building browsers that protected from these very risks. Both had past form building web APIs that expanded platform power <a href="https://www.chromium.org/teams/web-capabilities-fugu/">more thoughtfully.</a> Caution was thrown to the wind by the very folks that now demand credit for remediating tiny patches of the superfund sites <em>they</em> created.</p>
<p>It was the duopolists who handed those APIs to native apps from shady publishers like Facebook with less-than-thoughtful controls. And it was these very companies that <a href="https://www.nytimes.com/interactive/2018/09/12/technology/kids-apps-data-privacy-google-twitter.html">failed to police even their mildest policies.</a></p>
<p>And these same trillion-dollar market-cap firms simultaneously declined to do the one thing that had a chance to dramatically improve privacy: using their incredible lobbying capacity to forcefully call for privacy regulations worth a damn. Instead, they prefer a market structure where they can posture against each other over problems they jointly exacerbate.</p>
<p>And they have got away with it. Their press and product shops are keenly aware reporters don't understand privacy deeply enough to call their bluff, and that so-called privacy experts will clap as loudly for symbolic gestures as for fundamental change.</p>
<p>Humiliatingly for the fourth estate, Cupertino and Mountain View's self-issued privacy participation prizes were never questioned. Indeed, credulous journalists <em>continue</em> to shower them with praise for steps away from the very worst excesses best measured in angstroms.</p>
<p>Recently, Apple have been allowed to take credit for <a href="https://www.apple.com/privacy/labels/">foisting responsibility onto users</a> while Google has faced no sustained questioning for <a href="https://privacysandbox.google.com/">just giving up,</a> having <a href="https://privacysandbox.google.com/overview/android">never launched anything <em>at all</em> to structurally curb Android abuses.</a></p>
<p>Cynics might be inclined to think this was very much the point.</p>
<p>These monopolies on apps-that-install-apps exist to squash competition, not to preserve privacy. Apple's not working furiously to deny iOS users alternative browsers because they might track users, they're misleading anyone who will listen because the web might provide an alternative that doesn't.</p>
<h3 id="software-acquisition-and-distribution" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#software-acquisition-and-distribution">Software acquisition and distribution</a></h3>
<p>You know what the easiest way to get an app is? Clicking a link.</p>
<p>Apple literally pioneered this model with iOS 1.0, only to walk away from it a year later when it chose to carelessly expose overpowered, unsafe-by-default APIs with the hurried introduction of native apps. Throwing away privacy and security made software harder to build and distribute, too, but deposited power over developers with OS gatekeepers. Over time, the power to tax those developers became addictive.</p>
<p>A more secure and privacy preserving model is still possible but the duopolists continue to suppress it. I can't speak out of school about all the ways Android and Play mirrored Apple's underhanded tactics to suppress <abbr title="Progressive Web Apps">PWAs</abbr>, but suffice to say it was <em>a lot.</em></p>
<p>Industrial-scale suppression of safe, privacy-respecting platforms has been packaged up in florid terms as an advantage for developers. Except developers <a href="https://en.wikipedia.org/wiki/Epic_Games_v._Apple"><em>hate</em> mobile app stores.</a> But <a href="https://www.macrumors.com/2021/03/22/apple-surprised-developer-concerns-app-review/">you don't have to take my word for it.</a></p>
<p>Given the choice, developers would do exactly what the gatekeepers do when constructing billing, distribution, and marketing systems: shop around in an open market, based on standards-oriented technologies, and select the best fit for their needs.</p>
<p>This is exactly the model that gave rise to the web and to web search. Discovery for web apps isn't impossible without omnipotent app stores; it isn't even hard. If we can build search engines for web pages, we can also highlight sites that are installable. None of this is magic, and none of it requires a 30% take from the developer's budget.</p>
<h3 id="content-moderation" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#content-moderation">Content Moderation</a></h3>
<p>For the sake of completeness, we should stipulate that an end to app stores would not meaningfully change the content moderation landscape.</p>
<p>We now have a powerful example of this counterfactual thanks to the Twitter/Grok episode. There is no safety to be lost when we replace the gatekeeper's stores with a powerful, open, interoperable web. Mobile app store <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/">proprietors stand for nothing but profit and can be counted on only to defend their take.</a> Good riddance.</p>
<h2 id="who-should-rule" tabindex="-1"><a class="permalink" href="https://infrequently.org/2026/01/naked-power/#who-should-rule">The Rot of “Who Should Rule?”</a></h2>
<p>Before the 2024 US elections, tech titans were well-enough advised to know which way the winds were blowing. But that did not stir them to defend truth, the rule-of-law, or even the employees that enabled their success. Instead, they hurried to capitulate. Today they <a href="https://projects.propublica.org/fortune-500-company-election-deniers-jan-6/?company=alphabet">sponsor coup-excusers,</a> <a href="https://www.axios.com/2025/01/03/tim-cook-apple-donate-1-million-trump-inauguration">pay vigs,</a> <a href="https://www.anildash.com/2025/09/09/how-tim-cook-sold-out-steve-jobs/">grovel to people they surely loathe,</a> and <a href="https://fortune.com/2025/10/26/37-white-house-ballroom-donors-funding-300-million-build-tech-ceos-trump/">fund the literal destruction of America's institutions.</a></p>
<p>This month's failure to stand up for basic decency is just another link in that chain.</p>
<p>Having narrowed the running to two choices, mobile's masters always ask us to consider governing our phones through the authoritarian frame of <a href="https://archive.org/details/in.ernet.dli.2015.59272/page/n135/mode/1up"><em>&quot;who should rule?&quot;</em></a></p>
<p>But these aren't our only choices. As <a href="https://archive.org/details/in.ernet.dli.2015.59272/page/n135/mode/1up">Popper retorts,</a> the better question is <em>&quot;How can we so organize political institutions that bad or incompetent rulers can be prevented from doing too much damage?&quot;</em></p>
<p>This isn't purely a political question, but <a href="https://www.samuelbagg.com/book">applies to all of society's power structures.</a> The callous indifference of the app store's billionaire managers (<a href="https://www.forbes.com/profile/tim-cook/">1,</a> <a href="https://www.forbes.com/profile/sundar-pichai/">2</a>) when faced with an even moderately difficult call tells us that they cannot be trusted; this was the test, and the mobile overlords failed by their own terms.<sup class="footnote-ref"><a href="https://infrequently.org/2026/01/naked-power/#fn-whats-the-point-of-you-3" id="fnref-whats-the-point-of-you-3">3</a></sup></p>
<p>What's left for the rest of us to take on is how we dismantle the mechanisms our misplaced trust helped them build. This will not be easy, and an insightful commenter at The Verge restates the core problem:</p>
<blockquote>
<p>This is true and fantastic reporting and why we need to pay for The Verge.</p>
<p>But, it begs the question, what do we do?</p>
<p>Do we opt out of the tech of the modern world to protest? Commitment to values isn’t what we talk about, it’s what we are willing to give up. A key problem is that we don’t have any real competition vs Apple or Google as platforms if we want to exist in the modern world or even have this conversation.</p>
<p>You can’t (easily) read this or participate from a Kobo or Lightphone. Anyone have any suggestions?</p>
<p>I dropped off Twitter and Meta, but I’m running out of options.</p>
<p><span class="credit">        <a href="https://www.theverge.com/policy/859902/apple-google-run-by-cowards?commentID=9239b6b0-3791-4772-bcd4-ad038f99ac29" taget="_blank">— Anonymous commenter,<br />&quot;Tim Cook and Sundar Pichai are cowards, The Verge, Comments&quot;</a>      </span>    </p></blockquote><p></p>
<p>We aren't going to get anywhere by throwing our iPhones and Androids into the sea.</p>
<p>Credible, incremental steps that remove power from the gatekeepers are now demanded, and as I have previewed throughout this piece, the open web is that next step. It has all the properties we need to attenuate misgiven power: no single vendor control, based in standards, multiple <abbr title="Open Source Software">OSS</abbr> implementations, and most of all, portability.</p>
<p>The web is an abstraction that holds the power to liberate our computing in-situ, removing superfluous gatekeepers from the loop an increasing fraction of the time. As use of the web grows, so do the prospects for alternatives OSes and hardware ecosystems. They know this, and that's why they're trying to keep the web from winning.</p>
<p>Moving our computing to browsers and web apps won't protect us from Musk, but neither will Apple or Google.<sup class="footnote-ref"><a href="https://infrequently.org/2026/01/naked-power/#fn-dumbasses-4" id="fnref-dumbasses-4">4</a></sup> Now that we know that, we can at least start to claw back at the corrosive power of monopolists in our pockets by building for a future that doesn't depend exclusively on them.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-the-rich-and-the-rest-1" class="footnote-item"><p>Some folks like to continue to pretend that the mobile duopoly still includes any serious competition for either player. I assume those people are paid to review phones for a living.</p>
<p>As I outlined in <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#average-selling-prices">this year's instalment of the Performance Inequality Gap series</a>, the mobile market is actually two distinct markets: iOS for the rich, and Android for the rest. The average price for iPhones is hovering nearly $1K, while the average Android costs $300 new, unlocked. There is no functional competition between these ecosystems, and though they'll never admit it, that's a situation the duopolists are more than comfortable in, even if they don't particularly love it. <a href="https://infrequently.org/2026/01/naked-power/#fnref-the-rich-and-the-rest-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-cros-safety-2" class="footnote-item"><p>ChromeOS introduced the same safe-by-default model to desktop computing several years later. In both cases it was necessary to aggressively expand the web platform's capabilities to support the sorts of applications that users and developers needed, and in both cases that effort was successful. But both Apple (and to a lesser extent, Google) backed away from that strategy when it became clear that fundamentally unsafe, wickedly overpowered platforms were a hit with developers of viral apps. What followed has been 15+ years of papering over the inherent flaws in the model and shifting blame for the mobile platform maker's own predictable (and predicted) failure to keep users safe. <a href="https://infrequently.org/2026/01/naked-power/#fnref-cros-safety-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-whats-the-point-of-you-3" class="footnote-item"><p>If it always falls to civil society and regulators to protect women and girls from Elon Musk and his Trumpian alliance, what is the point of Tim and Sundar? Of Play and the App Store?</p>
<p>And if their policies are just fig leaves to justify rent extraction, why should any regulator listen to anything they say?</p>
<p>These questions should be hair-on-fire in the capitols of still-functioning democracies. <a href="https://infrequently.org/2026/01/naked-power/#fnref-whats-the-point-of-you-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-dumbasses-4" class="footnote-item"><p>It is not the most offensive thing about this episode by a country mile, but I am driven to distraction by <em>how unbelievably stupid</em> Apple and Google have become.</p>
<p>Did Tim and Sundar <em>really</em> think that, having sniffed weakness once, Trumpist shake downs would pass them over the next time a <em>pro quo</em> could be extracted for the <em>quid</em>?</p>
<p>Did they not understand that by participating in oligarchy they signed on to authoritarianism?</p>
<p>Did they <em>really</em> fail to calculate that capitulation didn't lower their risks, only centralised them?</p>
<p>This was all predictable. You don't have to look as far as <a href="https://en.wikipedia.org/wiki/Mikhail_Khodorkovsky">Russia</a> to understand that autocrats grant temporary loans of state power towards undemocratic ends to create leverage for themselves, not the borrower. And whatever the price, autocrats never stay bought.</p>
<p>Everyone but the smartest people in the room knew that <a href="https://en.wikipedia.org/wiki/Suspicious_Russia-related_deaths_since_2022">domination is a ladder,</a> and now we're all paying the price. <a href="https://infrequently.org/2026/01/naked-power/#fnref-dumbasses-4" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>The Performance Inequality Gap, 2026</title>
    <link href="https://infrequently.org/2025/11/performance-inequality-gap-2026/"/>
    <updated>2025-11-24T00:00:00Z</updated>
    <id>https://infrequently.org/2025/11/performance-inequality-gap-2026/</id>
    <content type="html"><![CDATA[
      <h2 id="the-budget" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-budget">The Budget, 2026 Edition</a></h2>
<p>Let's cut to the chase, shall we? Updated network test parameters for 2026 are:</p>
<ul>
<li>9 Mbps downlink</li>
<li>3 mbps uplink</li>
<li>100 millisecond <a href="https://en.wikipedia.org/wiki/Round-trip_delay"><abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr></a></li>
</ul>
<p>Regarding <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#test-devices">devices,</a> my updated recommendations are the <a href="https://www.gsmarena.com/samsung_galaxy_a24_4g-12176.php">Samsung Galaxy A24 4G</a> (or equivalent) and the <a href="https://www.microcenter.com/product/693646/hp-14-dq3500nr-14-laptop-computer-natural-silver">HP 14</a>. The goal of these recommendations is to emulate a <a href="https://www.debugbear.com/docs/rum/percentiles">75th percentile</a> user experience, meaning a full quarter of devices and networks will perform <em>worse</em> than this baseline.</p>
<p>Plugging these parameters into the <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart/index.html">updated budget calculator</a>, we can derive critical-path resource thresholds for three and five second page load targets. Per usual, we consider pages built in two styles: <abbr title="JavaScript">JS</abbr>-light, where only 15% of critical-path bytes are JavaScript, and <abbr title="JavaScript">JS</abbr>-heavy, comprised of 50% JavaScript:</p>
<table class="summary" id="budgets">  
  <thead>
    <tr>
      <th rowspan="2">Time</th>
      <th colspan="3">JS-light (MiB)</th>
      <th colspan="3">JS-heavy</th>
    </tr>
    <tr>
      <th>Total</th>
      <th>JS</th>
      <th>Other</th>
      <th>Total</th>
      <th>JS</th>
      <th>Other</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>3 sec</td>
      <td style="font-weight: bold;">2.0</td>
      <td>0.3</td>
      <td>1.7</td>
      <td style="font-weight: bold;">1.2</td>
      <td>0.62</td>
      <td>0.62</td>
    </tr>
    <tr>
      <td>5 sec</td>
      <td style="font-weight: bold;">3.7</td>
      <td>0.57</td>
      <td>3.2</td>
      <td style="font-weight: bold;">2.3</td>
      <td>1.15</td>
      <td>1.15</td>
    </tr>
  </tbody>
</table>
<br />
<blockquote>
<p><strong>Note:</strong> Budgets account for two <abbr title="Transport Layer Security">TLS</abbr> connections.</p>
<p>Many sites initiate more early connections, reducing time available to download resources. Using four connections cuts the three-second budget by 350 <abbr title="Kibibyte, 1024 Bytes">KiB</abbr>, to 1.5 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr> / 935 <abbr title="Kibibyte, 1024 Bytes">KiB</abbr>. The five-second budget loses nearly half a megabyte, dropping to 3.2 / 1.9 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr>.</p>
<p>It pays to adopt <a href="https://hpbn.co/http2/">H/2 or H/3</a> and consolidate connections.</p>
</blockquote>
<p>These budgets are <em>extremely</em> generous. Even the target of three seconds is lavish; most sites should be able to put up interactive content much sooner for nearly all users.</p>
<p>Meanwhile, <a href="https://httparchive.org/reports/page-weight">sites are ballooning.</a> The median mobile page is now 2.6 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr>, blowing past the size of DOOM (2.48 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr>) in April. The 75th percentile site is now larger than <em>two</em> copies of DOOM. P90+ sites are more than 4.5x larger, and sizes at each point have doubled over the past decade. Put another way, the median mobile page is now 70 times larger than <a href="https://en.wikipedia.org/wiki/Apollo_Guidance_Computer">the total storage of the computer that landed men on the moon.</a></p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/page-weight#bytesTotal" alt="Median page weights are more than 2.5x larger for mobile sites than a decade ago, and sites at the 75th percentile are now 4x their 2015 weight." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/httparchive-total-bytes-2015-2025.avif" alt="Median page weights are more than 2.5x larger for mobile sites than a decade ago, and sites at the 75th percentile are now 4x their 2015 weight." style="aspect-ratio: 1557 / 918" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>Median page weights are more than 2.5x larger for mobile sites than a decade ago, and sites at the 75th percentile are now 4x their 2015 weight.</figcaption>      </figure><p></p>
<p>An outsized contributor to this bloat comes from growth in JavaScript. Mobile JavaScript payloads have more than doubled since 2015, reaching 680 <abbr title="Kibibyte, 1024 Bytes">KiB</abbr> and 1.3 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr> at P50 and <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> (respectively). This compositional shift exacerbates latent inequality and hurts businesses trying to grow.</p>
<p>When JavaScript grows as a proportion of critical-path resources, the impact of higher <abbr title="Central Processing Unit">CPU</abbr> cost per byte reduces budgets. This <a href="https://en.wikipedia.org/wiki/Coffin_corner_(aerodynamics)">coffin corner effect</a> explains why image and <abbr title="Cascading Style Sheets">CSS</abbr>-heavy experiences perform better byte-for-byte than sites built with the <a href="https://infrequently.org/2024/11/if-not-react-then-what/">failed tools</a> of frontend's <a href="https://infrequently.org/2023/02/the-market-for-lemons/">lost decade.</a></p>
<p>Indeed, the latest <a href="https://developer.chrome.com/docs/crux"><abbr title="Chrome User Experience Report">CrUX</abbr> data</a> shows not even half of origins have passing Core Web Vitals scores for mobile users. More than 40% of sites still perform poorly for desktop users, and progress in both cohorts is plateauing:</p>
<div id="cwv-pass-rates" class="chart-container">
<h4 id="cwv-pass-rate" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#cwv-pass-rate">Core Web Vitals Pass Rate (%)</a></h4>
<p><em>Source: the <a href="https://developer.chrome.com/docs/crux">Chrome User Experience Report</a> via BigQuery.</em></p>
</div>
<p>This is a technical and business challenge, but also an ethical crisis. Anyone who cares to look can see <a href="https://infrequently.org/series/reckoning/">the tragic consequences for those who most need the help technology can offer.</a> Meanwhile, the lies, half-truths, and excuses made by frontend's influencer class are in defence of these approaches are, if anything, <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/">getting worse.</a></p>
<p>Through no action of their own, frontend developers have been blessed with more compute and bandwidth every year. Instead of converting that bounty into delightful experiences and positive business results, the dominant culture of frontend has leant into <a href="https://www.jonoalderson.com/conjecture/javascript-broke-the-web-and-called-it-progress/">self-aggrandising narratives that venerate failure as success.</a> The result is a web that increasingly punishes the poor for their bad luck while paying developers huge salaries to deliver business-undermining results.</p>
<p>Nobody comes to work wanting to do a bad job, but low-quality results are now the norm. This is a classic case of under-priced externalities created by <a href="https://en.wikipedia.org/wiki/Induced_demand">induced demand</a> from developers and PMs living in a privilege bubble.</p>
<p></p><figure><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart/index.html" alt="The interactive budget calculator has been updated and revised for 2026, allowing you to see the impact of networks, devices, connections, and JavaScript on site performance." target="_blank"><picture style="--lqip: 174298" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/2026-budget-calculator.avif" alt="The interactive budget calculator has been updated and revised for 2026, allowing you to see the impact of networks, devices, connections, and JavaScript on site performance." style="aspect-ratio: 1551 / 955" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>The interactive budget calculator has been updated and revised for 2026, allowing you to see the impact of networks, devices, connections, and JavaScript on site performance.</figcaption>      </figure><p></p>
<p>Embedded in this year's estimates is hopeful news about the trajectory of devices and networks. Compared with early 2024's estimates, we're seeing budget growth of 600+<abbr title="Kibibyte, 1024 Bytes">KiB</abbr> for three seconds, and a full megabyte of extra headroom at five seconds.<sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-p90-plus-is-grim-1" id="fnref-p90-plus-is-grim-1">1</a></sup></p>
<p>While this is not enough to overcome <a href="https://httparchive.org/reports/page-weight">continued growth in payloads</a>, budgets are now an <a href="https://infrequently.org/2017/10/can-you-afford-it-real-world-web-performance-budgets/">order of magnitude more generous than those first sketched in 2017.</a> It has never been easier to deliver pages quickly, but we are not collectively hitting the mark.</p>
<p>To get back to a healthy, competitive web, developers will need to apply considerably more restraint. If past is prologue, moderation is unlikely to arise organically. It's also unhelpful to conceive of ecosystem-level failures as personal failings. Yes, today's frontend culture is broken, but we should not expect better while incentives remain misaligned.</p>
<p>Browsers, search engines, and developer tools will need to provide stronger nudges, steering users away from bloated sites where possible, and communicating the problem to decision-makers. This will be unpopular, but it is necessary for the web to thrive.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-budget">The Budget, 2026 Edition</a><ul><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#test-devices">Recommended Test Devices and Settings</a></li></ul></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-big-story-is-still-low-end-android">The Big Story Is Still Low-End Android</a></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-landscape">The Landscape</a><ul><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#mobile">Mobile</a></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#desktop">Desktop</a></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#networks">Networks</a></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#looking-forward">Looking Forward</a></li></ul></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#content-trends">Content Trends</a><ul><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#are-spas-working%3F">Are SPAs Working?</a></li></ul></li><li><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#analysis-and-conclusions">Analysis and Conclusions</a></li></ul></nav>
<h3 id="test-devices" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#test-devices">Recommended Test Devices and Settings</a></h3>
<p>This series has continually stressed that <a href="https://infrequently.org/2021/03/the-performance-inequality-gap/#hardware-destiny">today's <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device is yesterday's mid-market Android,</a> and that trend continues.</p>
<p>The explosive smartphone market growth of the mid 2010s is squarely in the rear-view mirror, and so historical Average Selling Prices (<abbr title="Average Selling Prices">ASPs</abbr>) and replacement dynamics now dominate any discussion of fleet performance.</p>
<p>Hardware upgrade timelines are <a href="https://www.sciencedirect.com/science/article/pii/S0308596125001193">elongating.</a> Previous estimates of 18 months for replacement on average is now too rosy, with the median smartphone now living longer than two years. <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> devices may be nearly 3 years old, and <a href="https://www.techinsights.com/blog/global-smartphone-replacement-rate-cycle-forecast-88-countries-2008-2029">TechInsights estimates a 23.7% annual replacement rate.</a></p>
<p>With all of this in mind, we update our target test device to the <a href="https://www.gsmarena.com/samsung_galaxy_a24_4g-12176.php">Samsung Galaxy A24 4G</a>, a mid-2023 release featuring an <a href="https://www.mediatek.com/products/smartphones/mediatek-helio-g99"><abbr title="System-on-a-Chip">SoC</abbr> fabbed on a 6 nm process;</a> a notable improvement over <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#test-device-recommendations">previous benchmark devices.</a></p>
<p></p><figure class="seventy_wide"><a href="https://www.gsmarena.com/samsung_galaxy_a24_4g-12176.php" alt="Readers of this blog are unlikely to have used a phone as slow as the A24 in at least a decade." target="_blank"><picture style="--lqip: -375317" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/samsung-galaxy-a24.webp" alt="Readers of this blog are unlikely to have used a phone as slow as the A24 in at least a decade." style="aspect-ratio: 800 / 1000" class="seventy_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Readers of this blog are unlikely to have used a phone as slow as the A24 in at least a decade.</figcaption>      </figure><p></p>
<p>The A24 sold for less than the global Average Selling Price for smartphones at launch ($250 vs. $353). Because that specific model may be hard to acquire for testing, anything based on the <a href="https://www.notebookcheck.net/Mediatek-Helio-G99-Processor-Benchmarks-and-Specs.669976.0.html">MediaTek Helio G99</a> or <a href="https://www.notebookcheck.net/Samsung-Exynos-1330-Processor-Benchmarks-and-Specs.945355.0.html">Samsung Exynos 1330</a> will do; e.g.:</p>
<ul>
<li>
<p><a href="https://www.gsmarena.com/samsung_galaxy_a16-13383.php">Samsung Galaxy A16 4G</a></p>
</li>
<li>
<p><a href="https://www.gsmarena.com/samsung_galaxy_a07-14066.php">Samsung Galaxy A07 4G</a></p>
</li>
<li>
<p><a href="https://www.gsmarena.com/xiaomi_redmi_note_13_pro_4g-12749.php">Xiaomi Redmi Note 13 Pro 4G</a></p>
</li>
</ul>
<p>Teams that are serious about performance should track the low-end cohort instead, sticking with <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#test-device-recommendations">previously acquired</a> <a href="https://www.gsmarena.com/samsung_galaxy_a51-9963.php">Samsung Galaxy A51's,</a> or any <a href="https://www.gsmarena.com/motorola_moto_e15-13574.php">late-model device from the Moto E range.</a><sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-new-year-low-tier-2" id="fnref-new-year-low-tier-2">2</a></sup></p>
<p>For link-accurate network throttling, I recommend spending $3 for <a href="https://play.google.com/store/apps/details?id=me.twocities.throttly.paid&amp;hl=en_US">Throttly</a> for Android. It supports custom network profiles, allowing you to straightforwardly emulate a <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-budget">9/3/100 network.</a> DevTools throttling will always be inaccurate, and this is the best low-effort way to correctly condition links on your primary test device.</p>
<p>Desktops are not currently the limiting factor in the ecosystem, but it's still helpful to have physical test devices. Do not spend more than $250 (new) on a low-end test laptop. It should have a Celeron processor, eMMC storage, and run Windows. The last point is not an effort to sell more licences, but rather to represent the nasty effects of defender, NTFS, and parasitic background services on system performance. Something like <a href="https://www.microcenter.com/product/693646/hp-14-dq3500nr-14-laptop-computer-natural-silver">the HP 14 dq3500nr.</a></p>
<p></p><figure class="seventy_wide"><a href="https://www.microcenter.com/product/693646/hp-14-dq3500nr-14-laptop-computer-natural-silver" alt="Behold, the HP 14! A Celeron N4500 laptop, sporting a 4-core chip first released in 2021. This CPU packs less than a quarter the cache of a late-model iPhone." target="_blank"><picture style="--lqip: -390429" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/hp14.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/hp14.webp" alt="Behold, the HP 14! A Celeron N4500 laptop, sporting a 4-core chip first released in 2021. This CPU packs less than a quarter the cache of a late-model iPhone." style="aspect-ratio: 1000 / 800" class="seventy_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Behold, the HP 14! A Celeron N4500 laptop, sporting a 4-core chip first released in 2021. This <abbr title="Central Processing Unit">CPU</abbr> packs less than a quarter the cache of a late-model iPhone.</figcaption>      </figure><p></p>
<p>Desktop network throttling remains fraught, and the best solutions are still those from <a href="https://calendar.perfplanet.com/2016/testing-with-realistic-networking-conditions/">Pat Meenan's 2016 article announcing winShaper.</a></p>
<h2 id="the-big-story-is-still-low-end-android" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-big-story-is-still-low-end-android">The Big Story Is Still Low-End Android</a></h2>
<p>What we see in our recommended test setups is an echo of the greatest influence of the past decade on smartphone performance: the <a href="https://omdia.tech.informa.com/pr/2024/jun/omdia-reports-booming-demand-for-low-end-smartphones-priced-under-150-dollars">spread of slow, ever-cheaper Androids</a> with ageing chipsets, riding the cost curve downward, year-on-year.</p>
<p>The explosive growth of this segment drove nearly all market growth between 2011 and 2017. Now that smartphones have reached global saturation, flat sales volumes mirror the long-term trends in desktop device ownership:</p>
<div id="simple-volume" class="chart-container">
<h4 id="smartphone-volumes" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#smartphone-volumes">Smartphone Volumes</a></h4>
<h5 id="millions-of-units-per-year." tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#millions-of-units-per-year.">Millions of units per year.</a></h5>
<p><em>Source: <a href="https://www.idc.com/">IDC,</a> <a href="https://www.statista.com/">Statista,</a> and <a href="https://counterpointresearch.com/">Counterpoint Research.</a></em></p>
</div>
<p>At no point in the past dozen years has iOS accounted for more than 20% of new-device shipments. Quarterly fluctuations have pushed that number as high as 25% when new models are released, but the effect never lasts.</p>
<p>Most phones — indeed, most <em>computers</em> — are 24+ month old Androids. This is the result of a price segmented market: a preponderance of smartphones sold for more than $600USD (new, unlocked) are iPhones, and the overwhelming majority of devices sold for less than that are slow Androids.</p>
<div id="simple-asps" class="chart-container">
<h4 id="average-selling-prices" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#average-selling-prices">Average Selling Prices</a></h4>
<h5 id="new%2C-unlocked%2C-worldwide%2C-in-nominal-dollars." tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#new%2C-unlocked%2C-worldwide%2C-in-nominal-dollars.">New, unlocked, worldwide, in nominal dollars.</a></h5>
<p><em>Source: <a href="https://www.idc.com/">IDC,</a> <a href="https://www.statista.com/">Statista,</a> and <a href="https://counterpointresearch.com/">Counterpoint Research.</a></em><br />Not adjusted for inflation. Full year 2025 <abbr title="Average Selling Price">ASP</abbr> is extrapolated from the first several quarters and may be revised upward.</p>
</div>
<p><em>The “i” in “iPhone” stands for “inequality.”</em></p>
<p>Global <abbr title="Average Selling Prices">ASPs</abbr> show the low-end isn't just alive-and-well, it's many multiples of high-end device volume. To maintain a global <abbr title="Average Selling Price">ASP</abbr> near $370, an outsized number of cheaper Androids must be sold for every $1K (average) iOS device.</p>
<h2 id="the-landscape" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-landscape">The Landscape</a></h2>
<p>To understand how the payload budget estimate is derived, we need to peer deeper into the device and network situation. Despite huge, unpredictable shocks in the market (positive: Reliance Jio; negative: a pandemic), the market trends this series tracks have allowed us to forecast accurately.</p>
<p>75th+ percentile users are almost always on older devices, meaning we don't need to divine what will happen, just remember the recent past.</p>
<h3 id="mobile" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#mobile">Mobile</a></h3>
<p>The properties of today's mobile devices define how our sites run in practice. From the continued prevalence of 4G radios, to the shocking gaps in <abbr title="Central Processing Unit">CPU</abbr> performance, the reality of the modern web is best experienced through real devices. The next best way to understand it is through data.</p>
<p>Per usual, single and multicore <abbr title="Central Processing Unit">CPU</abbr> performance charts track four market segments:</p>
<ul>
<li>Fastest iOS device</li>
<li>Fastest Android</li>
<li>Mid-range Android ($300-350)</li>
<li>Low-end Android ($100-150)</li>
</ul>
<p>The last two cohorts account for more than 2/3 of new device sales:</p>
<div id="simple-sc" class="chart-container">
<h4 id="sc" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#sc">Geekbench 6 Single-Core scores</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://browser.geekbench.com/">Geekbench.</a></em></p>
</div>
<p>The performance of JavaScript-based web experiences is heavily correlated with single-core speed, meaning that the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device places a hard cap on the amount of JavaScript that is reasonable for any website to rely on.</p>
<p>Depressingly, budget device CPUs have not meaningfully improved since 2022. But the nearly-identical <abbr title="System-on-a-Chip">SoCs</abbr> in each year's device <em>are</em> getting cheaper. Reduced bill-of-materials costs mean declining retail prices for low-spec phones.</p>
<p>Meanwhile, the high end continues to pull away. As <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#:~:text=Looking%20forward%2C%20we,will%20not%20close.">previewed in prior instalments of this series,</a> top-end Androids are beginning to close the massive performance lead that Apple's A-series chips have opened up over the past decade. This is largely thanks to Qualcomm and MediaTek <em>finally</em> starting to address the cache-gap I have harped on since 2016:</p>
<div id="cache" class="chart-container">
<h4 id="total-cache" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#total-cache">Total <abbr title="System-on-a-Chip">SoC</abbr> Cache (<abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr>)</a></h4>
<h5 id="l1-%2B-l2-%2B-l3-%2B-system-level-caches" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#l1-%2B-l2-%2B-l3-%2B-system-level-caches">L1 + L2 + L3 + System-level Caches</a></h5>
<p><em>Source: <a href="https://www.wikipedia.org/">Wikipedia,</a> vendor documentation, and author's calculations.</em></p>
</div>
<p>Some cache sizings are estimates, particularly in the Android ecosystem, where vendor documentation is lacking. Android <abbr title="System-on-a-Chip">SoC</abbr> vendors have a habit of implementing the smallest values ARM allows for a licensed core design.</p>
<p>The latest iPhone chip (A19 Pro) features truly astonishing amounts of cache. For a sense of scale, the roughly 50 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr> of L1, L2, and L3 cache in an iPhone 17 Pro provides 8.3 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr> of cache per core. This is more than double the per core cache of Intel's latest high-end desktop part, the 285K, which provides a comparatively skimpy 3.3 <abbr title="Mebibyte, or 1024 Kibibytes">MiB</abbr> combined cache per core.</p>
<p>The gobsmacking caches of A-series parts allow Apple to keep the beast fed, leading to fewer stalls and more efficient use of <abbr title="Central Processing Unit">CPU</abbr> time. This advantage redounds to better battery life because well-fed CPUs can retire work faster, returning to lower-power states sooner.</p>
<p>That it has taken this long for even the top end of the Android ecosystem to begin to respond is a scandal.</p>
<div id="simple-scpd" class="chart-container">
<h4 id="sc-ppd" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#sc-ppd">Single-Core performance per $</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://browser.geekbench.com/">Geekbench,</a> and vendor documentation.</em><br />Geekbench 6 points per dollar at each price point over time. Prices are <abbr title="Manufacturer Suggested Retail Price">MSRP</abbr> at date of launch.</p>
</div>
<p>If there's good news for buyers of low-end devices, it's that performance per dollar continues to improve across the board.</p>
<p>Frustratingly, though, low-end single core performance is still 9x slower than contemporary iPhones, and mid-tier devices remain more than 3.5x slower:</p>
<div id="simple-sc-ratios" class="chart-container">
<h4 id="sc-pr" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#sc-pr">Single-Core Performance Ratios</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://browser.geekbench.com/">Geekbench.</a></em></p>
</div>
<p>Multicore performance tells a similar tale. As a reminder, this metric is less correlated with web application performance than single-core throughput:</p>
<div id="simple-mc" class="chart-container">
<h4 id="mc" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#mc">Geekbench 6 Multi-Core scores</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://browser.geekbench.com/">Geekbench.</a></em><br />When Geekbench reports multiple scores for an <abbr title="System-on-a-Chip">SoC</abbr>, recent non-outlier values are selected.</p>
</div>
<p>Performance per dollar looks compelling for the lower tier parts, but recall that they are 1/3 to 1/5 the performance:</p>
<div id="simple-mcpd" class="chart-container">
<h4 id="mc-ppd" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#mc-ppd">Multi-Core performance per $</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://browser.geekbench.com/">Geekbench,</a> and vendor documentation.</em></p>
</div>
<h4 id="market-trends" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#market-trends">Market Trends</a></h4>
<p>What makes iPhones so bloody fast, while Androids have languished? Several related factors in Apple's chip design and development strategy provided a commanding lead over the past decade:</p>
<ul>
<li>
<p>In-house tuning of all ARM-designed cores, thanks to a long-ago negotiated Architecture licence, leading to aggressive cache sizings.</p>
</li>
<li>
<p>Concentration in fewer <a href="https://en.wikipedia.org/wiki/System_on_a_chip"><abbr title="System-on-a-Chip">SoC</abbr></a> <abbr title="Stock Keeping Units">SKUs</abbr> enabled focused yield optimisation.</p>
</li>
<li>
<p>Large, early orders with <a href="https://en.wikipedia.org/wiki/TSMC">TSMC</a> secured exclusive access to the latest fabrication nodes.</p>
</li>
</ul>
<p>Android vendors, meanwhile, have spread their <abbr title="System-on-a-Chip">SoC</abbr> development budgets in penny-wise, pound-foolish fashion. Even Google and Samsung's in-house efforts have failed to replicate the virtuous effects of Apple's disciplined <abbr title="Central Processing Unit">CPU</abbr> designs.</p>
<div id="node" class="chart-container">
<h4 id="process-node" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#process-node">Process Node (nm)</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://www.wikipedia.org/">Wikipedia,</a> and vendor documentation.</em></p>
</div>
<p>Feature sizes are a fudge below 10 nanometres, but marketing names usually reflect real increases in transistor density and frequencies, along with reductions in power use. High-end Android and iOS parts have generally been produced on comparable nodes, with Apple's lead lasting less than a year. But that's less than half the story. Android <abbr title="System-on-a-Chip">SoC</abbr> vendors have avoided adding competitively sized caches, dedicating the same mm^2 on die to higher core counts and on-die radios. From a performance perspective, this has been catastrophic:</p>
<div id="cores" class="chart-container">
<h4 id="cores" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#cores">Core Counts</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://www.wikipedia.org/">Wikipedia,</a> and vendor documentation.</em></p>
</div>
<p>Core counts are a headline fixture of device marketing, but even the cheapest phones have featured eight (slow, memory-starved) cores since 2019. Speed comes from other properties; namely appropriate cache sizing, memory latency, frequency scaling, and chip architecture. Apple's core-count restraint and focus on other aspects should have been a lesson to the entire industry long before 2024.</p>
<p>Smaller transistors also allow for higher peak frequencies, giving Apple a perennial advantage thanks to early access to TSMC's latest, smallest, power-sipping processes:</p>
<div id="simple-freq" class="chart-container">
<h4 id="max-freq" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#max-freq">Maximum <abbr title="Central Processing Unit">CPU</abbr> Frequency (gHZ)</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://www.wikipedia.org/">Wikipedia,</a> and vendor documentation.</em><br />Maximum advertised frequency of the fastest on-package core.</p>
</div>
<p>These trade-offs have allowed Apple to charge a premium for devices which no other vendor can justify:</p>
<div id="simple-pvsasp" class="chart-container">
<h4 id="p-v-asp" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#p-v-asp">Prices vs. Average Selling Price (<abbr title="Average Selling Price">ASP</abbr>)</a></h4>
<p><em>Source: <a href="https://www.gsmarena.com/">GSMArena,</a> <a href="https://www.idc.com/">IDC,</a> <a href="https://www.statista.com/">Statista,</a> and <a href="https://counterpointresearch.com/">Counterpoint Research.</a></em><br />Prices are new, unlocked <abbr title="Manufacturer Suggested Retail Price">MSRP</abbr> at launch.</p>
</div>
<p>Global <abbr title="Average Selling Prices">ASPs</abbr> are conservative estimates; some research groups estimate values 10-15% higher, but the trends are consistent. The premium end continues to pull away in both price and performance, dragging <abbr title="Average Selling Prices">ASPs</abbr> slightly upward. Meanwhile, high-end devices continue to be outsold more than 3:1 by low-end phones that aren't getting faster. Those slow devices are, however, getting increasingly inexpensive, dropping below $100 in the last two years. That's 1/10th the price of the cheapest iPhone with Apple's fastest chip.</p>
<h4 id="rise-of-the-refurbs" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#rise-of-the-refurbs">Rise of the Refurbs</a></h4>
<p>Thanks to market trends, the recent-spec iPhones many web developers carry don't even represent the experience of most iOS users.</p>
<p>It may seem incongruous that the <abbr title="Average Selling Price">ASP</abbr> of iOS devices is bumping up against the $1K mark while most developed countries experience bouts of slow growth post-pandemic, along with well-documented cost-of-living crises among middle-class buyers.</p>
<p>One possible solution to this riddle is that Android sales remain strong, as Apple is cordoned into the segment of the market it can justify to shareholders with a 30% net margin. Another is <a href="https://counterpointresearch.com/en/insights/global-pre-owned-smartphone-landscape-in-transition">growth in the resale market, particularly for iOS devices.</a> Thanks to premium components and better-than-Android software support lifetimes, the longevity of iPhones has <a href="https://www.mordorintelligence.com/industry-reports/used-and-refurbished-smartphone-market">created a vibrant and growing market below the $400 price point.</a></p>
<p>This also helps to explain the flat-to-slightly-declining market for new smartphones, as refurbished devices <a href="https://www.marketresearchfuture.com/reports/used-smartphone-market-24446">accelerate past $40BN/yr in sales.</a></p>
<p>What does this mean? We should expect, and see, higher-than-first-sale volumes of iOS use in various aggregate statistics. Wealth effects have historically explained much of this, but the scale is growing. Refurbishment and resale are now likely to be driving growing discontinuity in the data:</p>
<p></p><figure class="full_wide"><a href="https://analytics.wikimedia.org/dashboards/browsers/#mobile-site-by-os/os-family-timeseries" alt="Wikimedia reports more than 40% of mobile site visits come from iOS devices over the past decade, despite global sales ratios never breeching 20% annually." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/wikimedia-mobile-traffic-by-mobile-os-2015-2025.avif" alt="Wikimedia reports more than 40% of mobile site visits come from iOS devices over the past decade, despite global sales ratios never breeching 20% annually." style="aspect-ratio: 1465 / 768" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Wikimedia reports more than 40% of mobile site visits come from iOS devices over the past decade, despite global sales ratios never breeching 20% annually.</figcaption>      </figure><p></p>
<p>Not only is an iPhone 17 Pro not real life in the overall market, it isn't even real life in the <em>iOS</em> market any more.</p>
<h3 id="desktop" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#desktop">Desktop</a></h3>
<p>The situation on desktop is one of overwhelming stasis, modulo the Windows 11 upgrade cycle resulting from <a href="https://support.microsoft.com/en-us/windows/windows-10-support-has-ended-on-october-14-2025-2ca8b313-1946-43d3-b55c-2b95b107f281">Windows 10's <abbr title="End of Life">EOL</abbr> at the end of 2025.</a> That has <a href="https://my.idc.com/getdoc.jsp?containerId=prUS53855725">driven an unusually strong one-off cycle of upgrades</a> that will reverberate through the data in coming years.</p>
<p></p><figure class="full_wide"><a href="https://www.idc.com/promo/pcdforecast/" alt="IDC's recent sales analysis shows that only 20% of 'desktop' devices are fully wired, with performance of the vast majority subject to power and thermal limits arising from battery power." target="_blank"><picture style="--lqip: 107997" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/idc-2025Q2-PCD-Historical-Promo-Chart.avif" alt="IDC's recent sales analysis shows that only 20% of 'desktop' devices are fully wired, with performance of the vast majority subject to power and thermal limits arising from battery power." style="background: white; padding: 0.5em 0px; aspect-ratio: 1262 / 672" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>IDC's recent sales analysis shows that only 20% of 'desktop' devices are fully wired, with performance of the vast majority subject to power and thermal limits arising from battery power.</figcaption>      </figure><p></p>
<p>This impetus to upgrade is cross-pressured by pricing headwinds. Economic uncertainty, tariffs, scrambled component pricing from AI demand for silicon of all sorts, and ever-longer device replacement cycles all mean that new PCs may not provide more than incremental performance gains. As a result, an increase in recent worldwide PC Average Selling Prices from ~$650 in our previous estimate to ~$750 in 2025 (per IDC) may not indicate premiumisation. In a globally connected economy, inflation comes for us all.</p>
<p>Overall, the composition and trajectory of the desktop market remains stable. Despite 2025's device replacement boomlet, IDC <a href="https://www.idc.com/promo/pcdforecast/#:~:text=Market%20Share%E2%80%9D%20chart-,Forecast%20PCD%20Market%20Share,-Year">predicts stasis in “personal computing device” volumes,</a> with growth bumping along at ±1-2% a year for the next 5 years, and landing just about where things are today. The now-stable baseline of ~410MM devices per year is predicted to be entirely flat into 2030.</p>
<!-- TODO: re-build IDC chart here to overlay Counterpoint data? -->
<p>Top-line things to remember about desktops are:</p>
<ul>
<li>
<p>80% of “desktop” devices are laptops, tablets, and other battery-powered form-factors. The performance impact of thermal and power envelopes for these devices is drastic; many cores are spun down to low power states most of the time; symmetric multiprocessing is now a datacentre curio.</p>
</li>
<li>
<p>Flaky Wi-Fi, rather than wired Ethernet, is now the last mile to <em>most</em> desktops.</p>
</li>
<li>
<p>Desktops (including laptops) are only 15-18% of web-capable device sales; a pattern that has been stable for a decade.</p>
</li>
</ul>
<p>Put another way: if you spend a majority of your time in front of a computer looking at a screen that's larger than 10&quot;, you live in a privilege bubble.</p>
<h4 id="evidence-from-the-edge-user-base" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#evidence-from-the-edge-user-base">Evidence From the Edge User Base</a></h4>
<p>Per <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#device-performance-1">previous instalments</a>, we can use Edge's population-level data to understand the evolution of the ecosystem. As of late 2025, the rough breakdown looks like:</p>
<table class="summary" style="margin: auto; min-width: 75%;">
  <thead>
    <tr>
      <td>Device Tier</td>
      <td>Fleet %</td>
      <td style="text-align: center;">Definition</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Low-end</td>
      <td>30%</td>
      <td style="width: 50%;">Either:<br />&lt;= 4 cores, or<br />&lt;= 4GB RAM</td>
    </tr>
    <tr>
      <td>Medium</td>
      <td>60%</td>
      <td>HDD (not SSD), or<br />4-16 GB RAM, or<br />4-8 cores</td>
    </tr>
    <tr>
      <td>High</td>
      <td>10%</td>
      <td style="width: 50%;">SSD +<br />&gt; 8 cores +<br />&gt; 16GB RAM</td>
    </tr>
  </tbody>
</table>
<p>Compared with the data from early 2024, we see some important shifts:</p>
<ul>
<li>
<p>Low-end devices have fallen from ~45% to ~30% of the fleet.</p>
</li>
<li>
<p>Most growth is in the middle tier, growing from 48% to 60%.</p>
</li>
<li>
<p>The high-end is growing slowly.</p>
</li>
</ul>
<p>Because the user base is also growing, it's worth mentioning that the apparent drop in the low-end is a <em>relative</em> change. In absolute terms, the ecosystem is seeing a slower absolute removal of low-spec machines. This matches what we should intuitively expect from incremental growth of the Edge user base, which is heavily skewed to Windows 11.</p>
<p>Older and slower devices likely constitute an even larger fraction of the total market, but may be invisible to us. Indeed, computers with spinning rust <abbr title="Hard Drives">HDDs</abbr>, &lt;= 4GB of <abbr title="Random Access Memory">RAM</abbr>, and &lt;= 2 cores still represent millions of active devices in our data. Alarmingly, they have dropped by less than 20% in absolute terms over the past six months. And remember, this isn't even the low end of the low end, as our stats don't include Chromebooks.</p>
<p>Building to the limits of <em>”feels fine on my MacBook Pro”</em> has never been realistic, but in 2025 it's active malpractice.</p>
<h3 id="networks" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#networks">Networks</a></h3>
<p>The <em><abbr title="&quot;Too long; didn't read&quot;; a summary of a post">TL;DR</abbr></em> for networks for 2026 is that the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> connection provides <strong>9Mbps of downlink bandwidth, 3Mbps upload, with 100ms of <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr> latency.</strong></p>
<p>This 9Mbps down, 3Mbps up configuration represents sizeable uplift from the 2024/2025 guidance of 7.2Mbps down, 1.4Mbps up, with 94ms <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr>, but also a correction. 2024's estimate for latency was <a href="https://radar.cloudflare.com/explorer?dataSet=quality.iqi&amp;metric=latency&amp;loc=&amp;dt=2024-01-01_2025-01-01">probably off by ~15%, and should have been set closer to 110ms.</a></p>
<p>Global or ambitious firms should target networks even slower than <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#the-budget">9/3/100</a> in their design parameters; the previous 5/1/28 “cable” network configuration is still worth building for, but with an upward adjustment to latency (think 5/1/100). Uneven service has the power to negatively define brands, and the way to remain in user's good graces digitally is to build for the P95+ user. Smaller, faster sites that serve this cohort well will stand out as being exceptional, even on the fastest networks and devices.</p>
<p>Looking forward into 2026 and 2027, the hard reality is that networks remain slower than developers expect and will not improve quickly.</p>
<p>Upload speeds, in particular, remain frustratingly slow, as wider upload channels correlate with faster early-session downloads. Only users on the fastest 10% of networks see downlink:uplink bandwidth rising above 2.5:1 ratios, even under ideal conditions.<sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-down-up-ratios-3" id="fnref-down-up-ratios-3">3</a></sup></p>
<p>Owing to physics, device replacement rates, CAPEX budgets of mobile carriers, inherent variability in mobile networks (vs. fixed-line broadband), and worldwide regulatory divergence, we should expect experiences to be heavily bottlenecked by networks for the foreseeable future.</p>
<p>Previous posts in this series have documented improvements, but <a href="https://infrequently.org/2021/03/the-performance-inequality-gap/#oh-em-gee">as we have been saying since 2021,</a> <strong>4G is a miracle, and 5G is a mirage.</strong></p>
<p></p><figure class="full_wide"><a href="https://www.gsma.com/somic/wp-content/uploads/2025/09/The-State-of-Mobile-Internet-Connectivity-2025-Network-Coverage-and-Infrastructure.pdf" alt="According to the GSMA's 2025 State of Mobile Internet Connectivity report, nominal 5G penetration coverage just crossed the 50% mark in 2025, and the rate of progress is predicted to slow as the attractive economics of dense rural areas give way to rural build outs. But coverage is not the same as service; many users will need newer, more expensive devices to unlock 5G speeds." target="_blank"><picture style="--lqip: 524212" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/gsma_coverage_by_network_type.avif" alt="According to the GSMA's 2025 State of Mobile Internet Connectivity report, nominal 5G penetration coverage just crossed the 50% mark in 2025, and the rate of progress is predicted to slow as the attractive economics of dense rural areas give way to rural build outs. But coverage is not the same as service; many users will need newer, more expensive devices to unlock 5G speeds." style="aspect-ratio: 1466 / 856" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>According to the <abbr title="The GSM Association">GSMA</abbr>'s 2025 State of Mobile Internet Connectivity report, nominal 5G penetration coverage just crossed the 50% mark in 2025, and the rate of progress is predicted to slow as the attractive economics of dense rural areas give way to rural build outs. But coverage is not the same as service; many users will need newer, more expensive devices to unlock 5G speeds.</figcaption>      </figure><p></p>
<p>This will remain true for at least another three years, with bandwidth and latency improving only incrementally. Sites that want to reach their full potential, if only to beat the competition, must build to budgets that are inclusive for folks on the margins. When it comes to web performance, <a href="https://wpostats.com/">doing well is the same as doing good.</a></p>
<h4 id="bandwidth" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#bandwidth">Bandwidth</a></h4>
<p>Bandwidth numbers are derived from Cloudflare's incredible <a href="https://radar.cloudflare.com/">Radar dataset.</a><sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-why-cf-4" id="fnref-why-cf-4">4</a></sup> Looking at (downlink) bandwidth trends over the past year, we see stasis:</p>
<p></p><figure class="full_wide"><a href="https://radar.cloudflare.com/explorer?dataSet=quality.iqi&metric=bandwidth&loc=&dt=2024-11-14_2025-11-14" alt="November 2024-November 2025 downlink bandwidth. Note that percentiles are inverted in this chart (we take their P25 as our P75 and vice versa). The trend line is remarkably stable; median and slower connections have not improved over the past year." target="_blank"><picture style="--lqip: 43747" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/cloudflare-radar_data-explorer-visualizer_bandwidth_nov_24_to_nov_25.avif" alt="November 2024-November 2025 downlink bandwidth. Note that percentiles are inverted in this chart (we take their P25 as our P75 and vice versa). The trend line is remarkably stable; median and slower connections have not improved over the past year." style="aspect-ratio: 1600 / 1156" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>November 2024-November 2025 downlink bandwidth. Note that percentiles are inverted in this chart (we take their P25 as our <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> and vice versa). The trend line is remarkably stable; median and slower connections have not improved over the past year.</figcaption>      </figure><p></p>
<p>So where does the improvement in our estimate come from? Looking back to 2024, we see (predicted) gains emerge, but note their small absolute size:</p>
<p></p><figure class="full_wide"><a href="https://radar.cloudflare.com/explorer?dataSet=quality.iqi&metric=bandwidth&loc=&dt=2023-11-14_2024-11-14" alt="November 2023-November 2024 downlink bandwidth. Connections representing the slowest quartile improved from ~6 to ~9 Mbps over the year, while median downlinks improved from ~12 to ~17 Mbps. They have not moved since." target="_blank"><picture style="--lqip: 42723" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/cloudflare-radar_data-explorer-visualizer_bandwidth_nov_23_to_nov_24.avif" alt="November 2023-November 2024 downlink bandwidth. Connections representing the slowest quartile improved from ~6 to ~9 Mbps over the year, while median downlinks improved from ~12 to ~17 Mbps. They have not moved since." style="aspect-ratio: 1600 / 1156" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>November 2023-November 2024 downlink bandwidth. Connections representing the slowest quartile improved from ~6 to ~9 Mbps over the year, while median downlinks improved from ~12 to ~17 Mbps. They have not moved since.</figcaption>      </figure><p></p>
<p>The gap between P25 and <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> downlinks was 15 Mbps at the start of 2024 and has grown to 21 Mbps at the end of 2025; an increase of 40%. Meanwhile, bottom quartile are only 28% faster, improving from ~7 to 9 Mbps. In absolute terms, wealthier users saw 3x as much absolute gain.</p>
<p>The performance inequality gap is growing at the network layer too.</p>
<h4 id="latency" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#latency">Latency</a></h4>
<p>Latency across networks (<a href="https://en.wikipedia.org/wiki/Round-trip_delay">RTTs</a>) is improving somewhat, with a nearly 10% decrease at <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> over the past year, from ~110ms to ~100ms. Small improvements on faster links (P50, P25) look to be in the 5% range:</p>
<p></p><figure class="full_wide"><a href="https://radar.cloudflare.com/explorer?dataSet=quality.iqi&metric=latency&loc=&dt=2023-11-14_2024-11-14" alt="November 2024-November 2025 RTT. Percentiles align with our usual intuition, with P75 representing the value at which 25% of connections are slower." target="_blank"><picture style="--lqip: 524130" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/cloudflare-radar_data-explorer-visualizer_rtt_nov_24_to_nov_25.avif" alt="November 2024-November 2025 RTT. Percentiles align with our usual intuition, with P75 representing the value at which 25% of connections are slower." style="aspect-ratio: 1600 / 1156" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>November 2024-November 2025 <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr>. Percentiles align with our usual intuition, with <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> representing the value at which 25% of connections are slower.</figcaption>      </figure><p></p>
<p>Given the variability at higher percentiles, we'll stick with a 100ms target for the 2026 calendar year, although we should expect slight gains.</p>
<p>Underlying these improvements are datacentre build outs in traditionally underserved regions, <a href="https://www.submarinecablemap.com/ready-for-service/2026">undersea cable completions,</a> and cellular backhaul improvements from the 5G build out. Faster client CPUs and radios will also contribute meaningfully and predictably.<sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-compute-impacts-network-speed-5" id="fnref-compute-impacts-network-speed-5">5</a></sup></p>
<p>All of these factors will continue to incrementally improve, and we predict another ~5% improvement (to 95ms) at <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> for 2027.</p>
<h3 id="looking-forward" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#looking-forward">Looking Forward</a></h3>
<p>Gains will be modest for both bandwidth and latency over the next few years. <a href="https://rumarchive.com/insights/#device-marketshare">The lion's share of web traffic is now carried across mobile networks,</a> meaning that high percentiles represent users feeling the confounding effects of cellular radios, uneven backhaul, coverage gaps, and interference from the built environment. Those factors are hardest and slowest to change, involving the largest number of potential long tent poles.</p>
<p>As <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#market-factors">discussed in previous instalments,</a> the world's densest emerging markets reached the smartphone tipping point by 2020, displacing feature phones for most adults. More recently, we have approached saturation; the moment at which smartphone sales are dominated by replacements, rather than first-time sales in those markets. Affordability and literacy remain large challenges to get the residually unconnected online. The <a href="https://www.gsma.com/somic/overview-report/">2025 <abbr title="The GSM Association">GSMA</abbr> State of Mobile Internet Connectivity report</a> has a <a href="https://www.gsma.com/somic/wp-content/uploads/2025/11/The-State-of-Mobile-Internet-Connectivity-2025-Barriers-to-Mobile-Internet-Adoption-and-Use.pdf">full chapter on these challenges (PDF)</a>, complete with rich survey data.</p>
<p>What we see in now-stable smartphone shipment volumes primes the pump for improvements in device performance. First-time smartphone users invest less in their devices (relative to income) as the value may be unclear; users shopping for a second phone have clearer expectations and hopes. Having lived the frustration of slow sites and apps, an incrementally larger set of folks will be willing to pay a bit more to add 5G modems to their next phone.</p>
<p>This effect is working its way down the price curve from the <a href="https://www.gsmarena.com/apple_iphone_12-10509.php">ultra-high-end in 2020</a> to the <a href="https://www.gsmarena.com/samsung_galaxy_a25-12555.php">mid-tier in 2024</a>, but it has yet to reach the low end. Our latest low-end specimen — <a href="https://www.gsmarena.com/motorola_moto_e15-13574.php">2025's Moto E15</a> — still features a 4G radio. Because of the additional compute requirements that 5G places on <abbr title="System-on-a-Chip">SoCs</abbr>, we will expect to see process node and <abbr title="Central Processing Unit">CPU</abbr> performance increases as 5G costs fall far enough to impact the low-price band.</p>
<p>Today, devices with otherwise similar specs and a 5G radio still command a considerable premium. The <a href="https://www.pcmag.com/reviews/samsung-galaxy-a16-5g">Galaxy A16 5G</a> was introduced <a href="https://m.gsmarena.com/samsung_galaxy_a16_5g_and_a16_4g_prices_leak-news-64740.php">at a 20% premium over the 4G version,</a> mirroring the mid-market dynamic from 2022 and 2023 where devices were offered in “regular” and (pricier) 5G versions. It will take a transition down the fab node scale like we saw for mid-market <abbr title="System-on-a-Chip">SoCs</abbr> in 2022 and 2024 to make 5G a low-end table-stakes feature. I'm not holding my breath.</p>
<p>Given the current market for chips of all types, we may be seeing low-spec <abbr title="System-on-a-Chip">SoCs</abbr> produced at 12 nanometres for several more years, reprising the long-term haunting of Android by huge volumes of <a href="https://en.wikipedia.org/wiki/ARM_Cortex-A53">A53 cores</a> produced at 28 nm <a href="https://en.wikichip.org/wiki/28_nm_lithography_process">from 2012</a> to 2019.</p>
<h2 id="content-trends" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#content-trends">Content Trends</a></h2>
<p>The budget estimates generated in this series may seem less relevant now that tools like <a href="https://web.dev/explore/learn-core-web-vitals">Core Web Vitals</a> provide nuanced, audience-specific metrics that allow us to characterise important <abbr title="User Experience">UX</abbr> attributes. But this assumption is flawed thanks to the <a href="https://en.wikipedia.org/wiki/Deadweight_loss">effects of deadweight losses</a> and the biases inherent in those metrics.</p>
<p>Case-in-point: last year <abbr title="Core Web Vitals, a Google-led effort to define user-relevant performance metrics for the web.">CWV</abbr> deprecated <abbr title="First Input Delay, as defined by Core Web Vitals">FID</abbr> and replaced it with the (better calibrated) <abbr title="Interaction-to-Next Paint, as defined by Core Web Vitals">INP</abbr> metric. This predictably dropped the <abbr title="Core Web Vitals, a Google-led effort to define user-relevant performance metrics for the web.">CWV</abbr> pass rates of sites built on desktop-era JavaScript frameworks like React, Angular, and Ember:</p>
<p></p><figure class="full_wide"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/frontend_sadness_index.avif" alt="2024's Frontend Sadness Index shows that CWV scores for sites based on legacy JS frameworks like React and Angular not only started off in trouble, but dropped more as INP replaced FID." style="aspect-ratio: 1221 / 718" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>2024's Frontend Sadness Index shows that <abbr title="Core Web Vitals, a Google-led effort to define user-relevant performance metrics for the web.">CWV</abbr> scores for sites based on legacy <abbr title="JavaScript">JS</abbr> frameworks like React and Angular not only started off in trouble, but dropped more as <abbr title="Interaction-to-Next Paint, as defined by Core Web Vitals">INP</abbr> replaced <abbr title="First Input Delay, as defined by Core Web Vitals">FID</abbr>.</figcaption>      </figure><p></p>
<p>RUM data, in isolation, undercounts the opportunity costs of slow and bloated experiences. Users have choices, and lost users do not show up in usage-based statistics.</p>
<p>A team I worked with this year saw these effects play out directly in their <a href="https://cruxvis.withgoogle.com/"><abbr title="Chrome User Experience Report">CrUX</abbr> data</a>:</p>
<p></p><figure class="full_wide"><picture style="--lqip: 523555" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/cruxvis-cautionary-tale.avif" alt="Form-factor ratios can show what use statistics for high-growth sites obscure." style="aspect-ratio: 1202 / 574" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Form-factor ratios can show what use statistics for high-growth sites obscure.</figcaption>      </figure><p></p>
<p>This high-profile, fast-growing site added nearly 100 <abbr title="Kibibyte, 1024 Bytes">KiB</abbr> of critical-path JavaScript per month from January to June. The result? A growing share of visits from desktop devices, and proportionally fewer mobile users every month. Once we began to fumigate for dead code and overeager preloading, mobile users returned.</p>
<p>These effects can easily overcome other factors, particularly in the current era of JavaScript bundle hyper-growth:</p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/page-weight#bytesTotal" alt="Median page weights are more than 2.5x larger for mobile sites than a decade ago, and 4x larger at the 75th percentile." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/httparchive-total-bytes-2015-2025.avif" alt="Median page weights are more than 2.5x larger for mobile sites than a decade ago, and 4x larger at the 75th percentile." style="aspect-ratio: 1557 / 918" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Median page weights are more than 2.5x larger for mobile sites than a decade ago, and 4x larger at the 75th percentile.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/page-weight#bytesJs" alt="Growth in JavaScript bytes over the wire mirrors that of overall content despite the continuing Performance Inequality Gap crisis." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/httparchive-js-bytes-2015-2025.avif" alt="Growth in JavaScript bytes over the wire mirrors that of overall content despite the continuing Performance Inequality Gap crisis." style="aspect-ratio: 1557 / 918" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Growth in JavaScript bytes over the wire mirrors that of overall content despite the continuing Performance Inequality Gap crisis.</figcaption>      </figure><p></p>
<h3 id="are-spas-working%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#are-spas-working%3F">Are <abbr title="Single Page Apps">SPAs</abbr> Working?</a></h3>
<p>Perhaps the most important insight I spotted while re-immersing myself in the data for this post were the implications of <a href="https://rumarchive.com/insights/#spa-aspect">these charts</a> from the <a href="https://rumarchive.com/">RUM Archive:</a></p>
<p></p><figure class="up two">          <picture style="--lqip: 173804" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/mpa-vs-spa-desktop.png" alt="" style="aspect-ratio: 1200 / 800" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174828" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/mpa-vs-spa-mobile.png" alt="" style="aspect-ratio: 1200 / 800" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          The <a href="https://rumarchive.com/insights/#spa-aspect">RUM Archive reports</a> that <abbr title="Single Page Apps">SPAs</abbr> are, on average, only generating a one (1) soft navigation per hard navigation, undermining the case for <abbr title="Single Page Apps">SPAs</abbr>.          </figcaption>        </figure><p></p>
<p>The top-line takeaway is chilling: sites that are <em>explicitly designed</em> as <abbr title="Single Page Apps">SPAs</abbr>, and which have <em>intentionally opted in</em> to metrics measurement around soft-navigations are seeing <strong>one</strong> (1) soft-navigation for every full page load on average.</p>
<p>The <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-rubrics-9">rinky-dink model</a> we discussed last year for the appropriateness of investing in <abbr title="Single Page App">SPA</abbr>-based stacks is a harsh master, defining average session performance as the sum of interaction latencies, including initial navigation, divided by the total number of interactions (excluding scrolling):</p>
<math display="block">
  <msub>
    <mi>L</mi>
    <mi>avg</mi>
  </msub>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <mi>latency</mi>
      <mo>(</mo>
      <mi>navigation</mi>
      <mo>)</mo>
      <mo>+</mo>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>i</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mi>I</mi>
      </munderover>
      <mi>latency</mi>
      <mo>(</mo>
      <mi>i</mi>
      <mo>)</mo>
    </mrow>
    <mi>N</mi>
  </mfrac>
</math>
<p>If the RUM Archive's data is directionally correct, at an ecosystem level, <math><mi>N</mi><mo>=~2</mo></math> for both mobile and desktop. Sessions this shallow make a mockery of the idea that we can justify more up-front JavaScript to deliver <abbr title="Single Page App">SPA</abbr> technology, <em>even on sites with reason to believe it would help</em>.</p>
<p>In private correspondence, <a href="https://bsky.app/profile/mmocny.com">Michal Mocny</a> shared an early analysis from data collected via the <a href="https://developer.chrome.com/blog/new-soft-navigations-origin-trial">Soft Navigations API Origin Trial.</a> Unlike the <a href="https://www.akamai.com/products/mpulse-real-user-monitoring">Akamai mPulse</a> data that feeds the RUM Archive, Chromium's data tracks interactions from all sites, not only those that have explicitly <a href="https://developer.chrome.com/origintrials/#/view_trial/21392098230009857">opted-in</a> to track soft navigations, providing a much wider aperture. On top-10K origins, Chrome is currently observing values for <math><mi>N</mi></math> between 1.6 and 2.2, depending on how the analysis is run, or 0.8-1.1 additional soft navigations per initial page load.</p>
<p>It's difficult to convey the earth-shattering magnitude of these congruent findings. Under these conditions, the amount of JavaScript a developer can justify up-front to support follow-on in-page navigations is <em>de minimis</em>.<sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-little-data-big-questions-6" id="fnref-little-data-big-questions-6">6</a></sup></p>
<p>This should shake our industry to the bone, driving rapid reductions in emitted JavaScript. And yet:</p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/page-weight#bytesJs" alt="Growth in JavaScript bytes is driving growth in overall payloads." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/11/performance-inequality-gap-2026/httparchive-js-bytes-2015-2025.avif" alt="Growth in JavaScript bytes is driving growth in overall payloads." style="aspect-ratio: 1557 / 918" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Growth in JavaScript bytes is driving growth in overall payloads.</figcaption>      </figure><p></p>
<h2 id="analysis-and-conclusions" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#analysis-and-conclusions">Analysis and Conclusions</a></h2>
<p>This series has three main goals:</p>
<ol>
<li>
<p>Provide a concrete set of page-weight targets for working web developers.</p>
</li>
<li>
<p>Arm teams with an understanding of how the client-side computing landscape is evolving.</p>
</li>
<li>
<p>Show how budgets are constructed, giving teams tools to construct their own estimates from their own RUM and market data.</p>
</li>
</ol>
<p>This is not altruism. I want the web to win. <a href="https://www.youtube.com/watch?v=4bZvq3nodf4">I began to raise the alarm about the problems created by a lack of adaptation to mobile's constraints in 2016,</a> and they <a href="https://vimeo.com/364402896">have played out</a> on the same trend-line I feared. The web is now <a href="https://youtu.be/0XwWVjQOmyg?si=NkMkRl6adpaT1PGE">decisively losing the battle for relevance.</a></p>
<p>To reverse this trend, I believe <a href="https://infrequently.org/2024/10/platforms-are-competitions/#win-condition">several (currently unmet) conditions must be fulfilled:</a></p>
<ul>
<li>
<p>Reaching users via the web must be cost-competitive with other digital channels, meaning that re-engagement features like being on the home screen and in the notification tray must work correctly.</p>
</li>
<li>
<p>The web must deliver the 80/20 set of critical capabilities for most of the important JTBDs in modern computing, but in a webby (safe, privacy-respecting by default) way.</p>
</li>
<li>
<p>Web experiences, on average, have to feel responsive enough that the idea of tapping a link doesn't inspire dread.</p>
</li>
</ul>
<p>But the web is not winning mobile. Apple, Google, and Facebook <a href="https://infrequently.org/series/browser-choice-must-matter/">nearly extinguished the web's potential to disrupt their cosy arrangement</a>. Preventing the web from breaking out — from meaningfully delivering app-like experiences outside an app store — is essential to maintaining dominance. <a href="https://open-web-advocacy.org/">But some are fighting back</a>, and against the odds, it's working.</p>
<p>What's left, then, is the subject of this series. Even if browser competition comes to iOS and competitors deliver the features needed to make the web a plausible contender, the structure of today's sites is an impediment to a future in which users prefer the web.</p>
<p>Most of the world's computing happens on devices that are older and slower than anything on a developer's desk, and connected via networks that contemporary “full-stack” developers don't emulate. Web developers almost never personally experience these constraints, and over <a href="https://infrequently.org/2023/02/the-market-for-lemons/">frontend's Lost Decade</a>, this has created an out-of-touch privilege bubble that <a href="https://infrequently.org/series/reckoning/">poisons the products</a> of the teams that follow the herd, as well as the broader ecosystem.</p>
<p>That's bleak, but the reason I devote weeks to this research each year isn't to scold. The hope is that actionable targets can help shape choices, and that by continuing to stay engaged with the evolution of the landscape, we can see green shoots sprout.</p>
<p>If we can hold down the rate of increase in critical-path resource growth it will give hardware progress time to overtake our excesses. If we make enough progress in that direction, we might even get back to a place where the web is a contender in the minds of users.</p>
<p>And that's a future worth working for.</p>
<aside class="thanks">
<p>I'm indebted to <a href="https://timkadlec.com/">Tim Kadlec</a> and <a href="https://radar.cloudflare.com/">Cloudflare's Radar dataset.</a> I'm not aware of any other repository of high-quality data describing worldwide end-user connection conditions with public reporting.<sup class="footnote-ref"><a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fn-why-cf-4" id="fnref-why-cf-4:1">4:1</a></sup> The analysis in this post would have been informed guesswork (at best) without it.</p>
<p>Deep thanks also to Akamai for continuing to support Robin Marx and Nic Jansma's work on the <a href="https://rumarchive.com/">RUM Archive</a>. The insights I've been able to glean from this data continues to shape my view of trends and grounds every other analysis.</p>
<p>Likewise, <a href="https://bsky.app/profile/mmocny.com">Michal Mocny's</a> generous analysis added heft to a surprising and tentative conclusion, and I am in his debt.</p>
<p>Thanks also to <a href="https://www.linkedin.com/in/mishra-amrita/">Amrita Mishra</a>, <a href="https://www.linkedin.com/in/amiya-gupta/">Amiya Gupta</a>, and <a href="https://danluu.com/">Dan Luu</a>, and <a href="https://bsky.app/profile/henrihelvetica.bsky.social">Henri Helvetica</a> for insightful feedback on drafts of this post, and to <a href="https://goodfeeds.net/@caleb">Caleb LaVergne</a> for spotting many more typos post-publication. Remaining errors are in spite of their best efforts.</p>
</aside>
<!-- ####################################################################### -->
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- Footnotes -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-p90-plus-is-grim-1" class="footnote-item"><p>I really do try to avoid being an unremitting downer, but the latest device in our low-cost cohort — <a href="https://www.gsmarena.com/motorola_moto_e15-13574.php">the Motorola E15</a> — is not an improvement in <abbr title="Central Processing Unit">CPU</abbr> benchmarks from last year.</p>
<p>More worrying, no device in that part of the market has delivered meaningful <abbr title="Central Processing Unit">CPU</abbr> gains since 2020. That's five years of stasis, and a return to a situation where new low-end devices are half as fast as their mid-tier contemporaries. Even as process node improvements trickle down to the $300-350 price bracket, the low end is left further and further behind.</p>
<p>As the wider Android ecosystem experienced from 2015-2020, devices with the same specs are getting cheaper, but not better. This allows them to open new markets and sell in massive numbers, helping to prop up overall annual device sales, even as devices last longer and former growth markets (India, Indonesia, etc.) hit smartphone saturation. This is reflected in the low-end models finally sinking below $100USD new, unlocked, at retail. But to hit this price-point, they deliver performance on par with 2019's mid-tier <a href="https://www.gsmarena.com/samsung_galaxy_a50-9554.php">Galaxy A50</a>; a phone whose <abbr title="Central Processing Unit">CPU</abbr> was fabbed on a smaller process node than today's latest low-end phones.</p>
<p>Services trying to scale, and anyone trying to build for emerging markets, should be anchoring P90 or P95, not <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr>. For serious shops, the target has not moved much at all since 2019.</p>
<p>This reality alone is enough to justify <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/">rejection of frameworkist hype-shilling,</a> without even discussing the negative impacts of <abbr title="JavaScript">JS</abbr>-first stacks on middle-distance team velocity and site maintenance costs. <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-p90-plus-is-grim-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-new-year-low-tier-2" class="footnote-item"><p>Because low-end and medium-tier devices were so similar until very recently, this differentiation wasn't necessary. But progress in process nodes does eventually trickle down. The mid-tier began to see improvement away from the (utterly blighted) 28 nm node in 2017, a mere 4 years after the high-end decamped for greener pastures. The low-end, meanwhile, was trapped in that register until 2020, nearly a decade after 28nm was first introduced. Since then, the mid tier has tracked process node scaling with a 2-3 year delay, while the low end has gotten stuck since 2021 at 12 nm.</p>
<p>The failure to include meaningful amounts of cache in Android <abbr title="System-on-a-Chip">SoCs</abbr> levelled out low-end and medium tier performance until 2023, but transistor shrinkage and architecture improvements at ~$350 are now decoupling the performance of these tiers once again, and we should expect to see them grow further apart in coming years, creating a worrying gap between P90+ and <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> devices. <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-new-year-low-tier-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-down-up-ratios-3" class="footnote-item"><p>Cloudflare's <a href="https://radar.cloudflare.com/explorer?dataSet=quality.iqi&amp;metric=bandwidth">worldwide bandwidth data</a> only provides downlink estimates, and so to understand the downlink:uplink bandwidth ratio, I turned instead to their API and <a href="https://api.cloudflare.com/client/v4/radar/quality/speed/histogram">queried CF's speed test data,</a> which provide fuller histograms.</p>
<p>These tests are explicitly run by users, meaning they occur under synthetic conditions and likely with a skew towards best-case network performance. They also report maximums over a session, rather than loaded network behaviour, which explains the divergence between the higher speed values reported there than the more realistic &quot;Internet Quality Index&quot; dataset we use for primary bandwidth and latency analysis.</p>
<p>The data we can derive from it is therefore much rosier, but it does give us a sense for downlink/uplink ratios (bitrates are in Mbps):</p>
<table>
<thead>
<tr>
<th style="text-align:left">%-ile</th>
<th style="text-align:right">Download</th>
<th style="text-align:right">Upload</th>
<th style="text-align:right">Ratio</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">20th</td>
<td style="text-align:right">15</td>
<td style="text-align:right">5</td>
<td style="text-align:right">3</td>
</tr>
<tr>
<td style="text-align:left">25th</td>
<td style="text-align:right">25</td>
<td style="text-align:right">10</td>
<td style="text-align:right">2.5</td>
</tr>
<tr>
<td style="text-align:left">30th</td>
<td style="text-align:right">10</td>
<td style="text-align:right">30</td>
<td style="text-align:right">3</td>
</tr>
<tr>
<td style="text-align:left">40th</td>
<td style="text-align:right">20</td>
<td style="text-align:right">50</td>
<td style="text-align:right">2.5</td>
</tr>
<tr>
<td style="text-align:left">median</td>
<td style="text-align:right">85</td>
<td style="text-align:right">35</td>
<td style="text-align:right">2.4</td>
</tr>
<tr>
<td style="text-align:left">60th</td>
<td style="text-align:right">125</td>
<td style="text-align:right">50</td>
<td style="text-align:right">2.5</td>
</tr>
<tr>
<td style="text-align:left">70th</td>
<td style="text-align:right">220</td>
<td style="text-align:right">85</td>
<td style="text-align:right">2.6</td>
</tr>
<tr>
<td style="text-align:left">75th</td>
<td style="text-align:right">280</td>
<td style="text-align:right">100</td>
<td style="text-align:right">2.8</td>
</tr>
<tr>
<td style="text-align:left">80th</td>
<td style="text-align:right">345</td>
<td style="text-align:right">140</td>
<td style="text-align:right">2.5</td>
</tr>
<tr>
<td style="text-align:left">90th</td>
<td style="text-align:right">525</td>
<td style="text-align:right">280</td>
<td style="text-align:right">1.9</td>
</tr>
</tbody>
</table>
<p>Because the data is skewed in an optimistic direction (thanks to usage biases towards wealth, which correlates with high-performance networks), we pick a 3:1 ratio in our global baseline.</p>
<p>Despite variance in the lower percentiles, it is reasonable to expect tough ratios in the bottom quartile given the build-out properties of various network types. These include:</p>
<ul>
<li>Asymmetries in cable and DSL channel allocations.</li>
<li>Explicit frequency/bandwidth allocation in cellular networks.</li>
<li>Radio power lopsidedness vs. the base stations they connect to, particularly for battery-powered devices.</li>
</ul>
<p>Even new networks like Starlink are spec'd with 10:1 or greater ratios. Indeed, despite being &quot;fast&quot;, the author's own home fixed-line connection has a ratio grater than 30:1. We should expect many such discrepancies up and down the wealth spectrum.</p>
<p>A 4:1 or 5:1 ratio is probably justified, and previous estimates used 5:1 ratios for that reason. Lacking better data, going with 3:1 is a judgement call, and I welcome feedback on the choice. <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-down-up-ratios-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-why-cf-4" class="footnote-item"><p>Why am I relying on Cloudflare's data?</p>
<p>Google, Microsoft, Amazon, Fastly, Akamai, and others obviously <em>have</em> similar data (at least in theory), but do not publish it in such a useful and queryable way. That said, these estimates are on trend with my priors about the network situation developed from many sources over the years (including non-public datasets).</p>
<p>There is a chance Cloudflare's data is unrepresentative, but given their CDN market penetration, my primary concern is that their data is too rosy, rather than too generous. Why? Geographic and use-based bias effects.</p>
<p>The wealthy are better connected and heavier internet users, generating more sessions. Better performance of experiences increases engagement, so we know CF's data contains a bias towards the experiences of the affluent. This potentially blinds us to large fraction of the theoretical <abbr title="Total Addressable Market">TAM</abbr> and (I think) convincingly argues that we should be taking a P90 value instead of <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr>. However, we stick with <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> for two reasons:</p>
<ul>
<li>It would be incongruent to cite P90 this year without first introducing it in previous installations.</li>
<li>A lack of explicitly triangulating data from the current network environment makes it challenging to judge the magnitude of use-based biases in the data.</li>
</ul>
<p>Thankfully, Cloudflare also produces country-level data. We can use this to cabin the scale of potential issues in global data. Here, for instance, are the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> network situations for a few populous geos that every growth-oriented international brand must consider in descending downlink speed:</p>
<table>
<thead>
<tr>
<th style="text-align:left">Geo @ <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr></th>
<th style="text-align:right">Down</th>
<th style="text-align:right">Up</th>
<th style="text-align:right"><abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr></th>
<th style="text-align:right">Pop (MM)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">UK</td>
<td style="text-align:right">21</td>
<td style="text-align:right">7</td>
<td style="text-align:right">34</td>
<td style="text-align:right">69</td>
</tr>
<tr>
<td style="text-align:left">USA</td>
<td style="text-align:right">17</td>
<td style="text-align:right">5.5</td>
<td style="text-align:right">47</td>
<td style="text-align:right">340</td>
</tr>
<tr>
<td style="text-align:left">Brazil</td>
<td style="text-align:right">12</td>
<td style="text-align:right">4</td>
<td style="text-align:right">60</td>
<td style="text-align:right">213</td>
</tr>
<tr>
<td style="text-align:left"><em>Global</em></td>
<td style="text-align:right"><em>9</em></td>
<td style="text-align:right"><em>3</em></td>
<td style="text-align:right"><em>100</em></td>
<td style="text-align:right"></td>
</tr>
<tr>
<td style="text-align:left">Indonesia</td>
<td style="text-align:right">6.4</td>
<td style="text-align:right">2.1</td>
<td style="text-align:right">75</td>
<td style="text-align:right">284</td>
</tr>
<tr>
<td style="text-align:left">India</td>
<td style="text-align:right">6.2</td>
<td style="text-align:right">2.1</td>
<td style="text-align:right">85</td>
<td style="text-align:right">1,417</td>
</tr>
<tr>
<td style="text-align:left">Pakistan</td>
<td style="text-align:right">4</td>
<td style="text-align:right">1.3</td>
<td style="text-align:right">130</td>
<td style="text-align:right">241</td>
</tr>
<tr>
<td style="text-align:left">Nigeria</td>
<td style="text-align:right">3.1</td>
<td style="text-align:right">1</td>
<td style="text-align:right">190</td>
<td style="text-align:right">223</td>
</tr>
</tbody>
</table>
<p>Underweighting the less-affluent is a common bias in tech, and my consulting experience has repeatedly reconfirmed <a href="https://www.speedcurve.com/blog/psychology-site-speed/">what Tammy Everts writes about</a> when it comes to the opportunities that are available when sites push past <a href="https://www.speedcurve.com/blog/web-performance-plateau/">performance plateaus.</a></p>
<p>There is no such thing as “too fast”, but most teams are so far away from minimally acceptable results that they have never experienced the huge wins on the other side of truly excellent and consistent performance. Entire markets open up when teams expand access through improved performance, and wealthy users convert more too.</p>
<p>It's this reality that <a href="https://infrequently.org/2023/02/the-market-for-lemons/">lemon vendors</a> have sold totally inappropriate tools into, and the results remain shockingly poor. <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-why-cf-4" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-why-cf-4:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-compute-impacts-network-speed-5" class="footnote-item"><p>As we mentioned in the last instalment, improvements in mid-tier and low-end mobile <abbr title="System-on-a-Chip">SoCs</abbr> are delivering better network performance <em>independent of protocol and spectrum improvements</em>.</p>
<p>Modern link-layer cell and Wi-Fi stacks rely heavily on client-side compute for the digital signal processing necessary to implement advanced techniques like <a href="https://en.wikipedia.org/wiki/MIMO">MIMO beam forming.</a></p>
<p>This makes the device replacement rates doubly impactful, even within radio generations and against fixed channel capacity. As process improvements trickle down (glacially) to mid-tier and low-end <abbr title="System-on-a-Chip">SoCs</abbr>, the radios they contain also get faster processing, improving latency and throughput, <em>ceteris paribus</em>. <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-compute-impacts-network-speed-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-little-data-big-questions-6" class="footnote-item"><p>The RUM Archive's soft-to-hard navigations ratio and the early data from the Chromium Soft Navigations Origin Trial leave many, many questions unanswered including, but not limited to:</p>
<ul>
<li>What's the distribution?
<ul>
<li>Globally: do some <abbr title="Single Page App">SPA</abbr>-premised sites have many more or many fewer soft-navigations? Are only a few major sites pushing the ratios up (or down)?</li>
<li>Locally: can we characterise user's sessions to understand what fraction trigger many soft-navigations per session?</li>
</ul>
</li>
<li>Do other data sources agree?
<ul>
<li>Will the currently-running <a href="https://developer.chrome.com/blog/new-soft-navigations-origin-trial">Origin Trial</a> for <a href="https://www.youtube.com/watch?v=sDHSn-OryV8">Soft Navigations</a> continue to agree as the reach grows?</li>
<li>Can other RUM vendors validate or refute these insights?</li>
</ul>
</li>
<li>What about in-page changes not triggering URL updates?
<ul>
<li>How should infinite-scrolling be counted?</li>
<li>We should expect Chromium histogram data to capture more of this vs. the somewhat explicit instrumentation of mPulse, driving up soft-navigations per hard navigation. Do things stay in sync in these data sets over time?</li>
</ul>
</li>
</ul>
<p>Given the scale of the mystery, a veritable stampede of research in the web performance community should follow. I hope to see an explosion of tools to guide teams toward the most appropriate architectures based on comparative data within their verticals, first-party RUM data about session lengths, distribution mono/bi/tri/multi-modality of sessions, and other situated factors.</p>
<p>The mystery I have flicked at in the past is now hitting us smack in the face. Will we pay attention? <a href="https://infrequently.org/2025/11/performance-inequality-gap-2026/#fnref-little-data-big-questions-6" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>The App Store Was Always Authoritarian</title>
    <link href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/"/>
    <updated>2025-10-11T00:00:00Z</updated>
    <id>https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/</id>
    <content type="html"><![CDATA[
      <p></p><figure class="lede_figure"><picture style="--lqip: -170653" class="preview">      <img src="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/chains-eric-prouzet-large-unsplash.avif" alt="Eric Prouzet" style="aspect-ratio: 1200 / 800" class="lede_figure preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>      <span class="credit">        <a href="https://unsplash.com/photos/a-bunch-of-rusty-chains-hanging-from-a-wall-0H1uDKDxYjo" taget="_blank">Eric Prouzet</a>      </span>    </figcaption>      </figure><p></p>
<p><a href="https://www.404media.co/apple-banned-an-app-that-simply-archived-videos-of-ice-abuses/">And now we see it clear, like a Cupertino sunrise bathing Mt. Bielawski in amber:</a> Apple will censor its App Store at the behest of the Trump administration without putting up a fight.</p>
<p><a href="https://migrantinsider.com/p/scoop-apple-quietly-made-ice-agents">It will twist words into their antipodes</a> to serve the powerful at the expense of the weak.</p>
<p>To better serve autocrats, it will talk out both sides of its mouth in ways it had previously reserved for dissembling arguments against threats to profits, like <a href="https://www.techfinitive.com/features/parts-pairing-and-the-apple-iphone-16-how-apples-next-phone-will-be-designed-by-oregons-senate/">right-to-repair</a> and <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">browser choice.</a></p>
<p>They are, of course, linked.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#who's-afraid-of-the-big-bad-web%3F">Who's Afraid of the Big Bad Web?</a></li><li><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#dots-unconnected">Dots Unconnected</a></li><li><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#%22who-should-rule%3F%22">&quot;Who should rule?&quot;</a></li><li><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#the-price-of-high-modernism-is-dignity">The Price of High Modernism is Dignity</a></li><li><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#endnote%3A-let's-talk-about-google">Endnote: Let's Talk About Google</a></li></ul></nav>
<p>Apple <a href="https://www.anildash.com/2025/09/09/how-tim-cook-sold-out-steve-jobs/">bent the knee</a> for months, leaving many commentators to ask why. But the reasons are not mysterious: Apple <em>wants</em> things that only the government can provide, things that will defend and extend its power to extract rents, rather than innovate. Namely, selective exemption from tariffs and an end to the spectre of pro-competition regulation that might bring about real browser choice.</p>
<p><a href="https://infrequently.org/2025/09/apples-antitrust-playbook/">Over the past few weeks,</a> Tim Apple got a lot what he paid for,<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-bonus-treats-1" id="fnref-bonus-treats-1">1</a></sup> with the full weight of the US foreign and industrial policy apparatus <a href="https://on.ft.com/4h8bcXt">threatening the EU over <abbr title="The EU's Digital Markets Act">DMA</abbr> enforcement.</a> This has been part of a full-court press from Cupertino. Apple <a href="https://www.france24.com/en/live-news/20250925-apple-asks-eu-to-scrap-landmark-digital-competition-law">simultaneously threatened the EU</a> while rolling out <a href="https://www.linkedin.com/posts/damiengeradin_can-small-tech-survive-the-digital-markets-activity-7376973488991137792-M_kG">fresh astroturf for pliant regulators to recline on.</a> This is loud, coordinated, and calculated. But calculated to achieve <em>what</em>? Why is the <abbr title="The EU's Digital Markets Act">DMA</abbr> such a threat to Apple?</p>
<p>Interoperability.</p>
<p>The <abbr title="The EU's Digital Markets Act">DMA</abbr> holds the power to unlock true, safe, interoperability via the web. Its core terms <em>require</em> that Apple facilitate real browser engine choice, and <a href="https://open-web-advocacy.org/blog/owa-at-the-eu-parliament-dma-working-group/#browser-engines-and-the-dma">Apple is all but refusing,</a> playing games to prevent powerful and safe iOS browsers and the powerful web applications they facilitate. Web applications <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">that can challenge the App Store.</a></p>
<p>Unlike tariffs, which present a threat to short-term profits through higher costs and suppression of upgrades in the near term, interoperability is a larger and more insidious boogeyman for Apple. It could change <em>everything</em>.</p>
<h2 id="who's-afraid-of-the-big-bad-web%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#who's-afraid-of-the-big-bad-web%3F">Who's Afraid of the Big Bad Web?</a></h2>
<p>Apple's profits are less and less attributable to innovation as <a href="https://www.statista.com/chart/14629/apple-services-revenue/?srsltid=AfmBOooHzmlC-KPd9ujiOzEs1lHlaFUDUIsOEC8ODn32ops-5dUK73s_">“services” revenue swells Cupertino's coffers out of all proportion to iPhone sales volume.</a> “Services” is code for rent extraction from captive users and developers. If they could acquire and make safe apps outside the App Store, Apple wouldn't be able to take 30% from an outlandishly large fraction of the digital ecosystem's wealthiest players.</p>
<p>Apple understands browser choice is a threat to its <em>rentier</em> model. The <abbr title="The EU's Digital Markets Act">DMA</abbr> holds the potential for developers to finally access the safe, open, and interoperable web technologies that power most desktop computing today. This is a <em>particular</em> threat to Apple, because its class-leading hardware is perfectly suited to running web applications. All that's missing are browsers that aren't intentionally hobbled. This helps to explain why Apple simultaneously demands control over all browser technology on iOS while <a href="https://infrequently.org/2021/04/progress-delayed/">delaying important APIs</a>, <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">breaking</a> foundational <a href="https://webventures.rejh.nl/blog/2024/web-push-ios-one-year/">capabilities</a>, and <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/">gaslighting developers about Apple's unwillingness to solve pressing problems.</a></p>
<p>Keeping capable, stable, high-quality browsers away from iOS is necessary to maintain the App Store's monopoly on the features every app needs. Keeping other software distribution mechanisms from offering those features at a lower price is a hard requirement for Cupertino's extractive business model. The web (in particular, <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/"><abbr title="Progressive Web Apps">PWAs</abbr></a>) present a worst-case scenario.</p>
<p>Unlike alternative app stores that let developers decouple distribution of proprietary apps from Apple's App Store, <abbr title="Progressive Web Apps">PWAs</abbr> further free developers from building for each OS separately, allowing them to deliver apps though a zero-cost platform that builds on standards. And that platform doesn't feature a single choke point. For small developers, this is transformative, and it's why late-stage Apple cannot abide laws that create commercial fairness and enable safe, secure, pro-user alternatives.</p>
<h2 id="dots-unconnected" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#dots-unconnected">Dots Unconnected</a></h2>
<p>This is what Apple is mortgaging its brand (or, if you prefer, soul) to prevent: a world where users have a real choice in browsers.</p>
<p>Horrors.</p>
<p>Apple is loaning its monopoly on iOS software to <a href="https://pluralistic.net/2025/10/06/rogue-capitalism/#orphaned-syrian-refugees-need-not-apply">yet another</a> authoritarian regime without a fight, painting a stark contrast: when profits are on the line, Cupertino will gaslight democratic regulators and defy pro-competition laws with all the $1600/hr lawyers Harvard can graduate. And when it needs a transactional authoritarian's help to protect those same profits, temporarily<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-it-hopes-2" id="fnref-it-hopes-2">2</a></sup> lending its godlike power over iOS to censor clearly protected speech isn't too high a price to ask. Struggle for thee, but not for me.</p>
<p>The kicker is that the only alternative for affected users and developers is Apple's decrepit implementation of web apps; the same platform Cupertino serially knee-caps to deflect competition with its proprietary APIs.</p>
<p>It is no exaggeration to say the tech press is letting democracy down by failing to connect the dots. Why is Apple capitulating? Because Apple <em>wants things</em> from the government. What are those things? We should be deep into that debate, but our <em>reportage</em> and editorial classes cannot grasp that A precedes B. The obvious answers are also the right ones: selective protection from tariffs, defanged prosecution by the DOJ, and an umbrella from the EU's democratic, pro-competition regulation.</p>
<p><a href="https://www.theverge.com/news/795248/former-apple-exec-iceblock-removal-criticism">The Verge tiptoed <em>ever so close</em> to getting it,</a> quoting <a href="https://wileyhodges.substack.com/p/my-email-to-tim-cook?r=qlwt">letters that former Apple executives sent the company:</a><sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-servile-frames-3" id="fnref-servile-frames-3">3</a></sup></p>
<blockquote>
<p>I used to believe that Apple were unequivocally ‘the good guys,’” Hodges writes. “I passionately advocated for people to understand Apple as being on the side of its users above all else. I now feel like I must question that.”</p>
<p><span class="credit">        <a href="https://www.theverge.com/news/795248/former-apple-exec-iceblock-removal-criticism" taget="_blank">— Wiley Hodges,<br />&quot;The Verge&quot;</a>      </span>    </p></blockquote><p></p>
<p>This is a clue; a lead that a more thoughtful press and tech commentariat could use to evaluate the frames the parties deploy to their own benefit.</p>
<h2 id="%22who-should-rule%3F%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#%22who-should-rule%3F%22"><em>&quot;Who should rule?&quot;</em></a></h2>
<p>The tech press is failing to grasp the moral stakes of API access. Again and again they flunk at connecting boring questions of who can write and distribute programs for phones to urgent issues of power over publication and control of devices. By declining to join these threads, they allow the unearned and increasingly indefensible power app stores to proliferate. The urgent question is how that power can be attenuated in the political economy of mobile OSes, or as Popper put it:</p>
<blockquote>
<p>We must ask whether…we should not prepare for the worst leaders, and hope for the best. But this leads to a new approach to the problem of politics, for it forces us to replace the question: <strong>&quot;Who should rule?&quot;</strong> by the new question: <strong>&quot;How can we so organize political institutions that bad or incompetent rulers can be prevented from doing too much damage?&quot;</strong></p>
<p><span class="credit">        <a href="https://archive.org/details/in.ernet.dli.2015.59272/page/n135/mode/1up" taget="_blank">— Karl Popper,<br />&quot;The Open Society and Its Enemies&quot;</a>      </span>    </p></blockquote><p></p>
<p>But the tech press does not ask these questions.</p>
<p>Instead of questioning why Apple's OS is so fundamentally insecure that an App Store is necessary, they accept the ever-false idea that iOS has been relatively secure <em>because</em> of the App Store.</p>
<p>Rather than confronting Apple with the reality that it used the App Store to hand out privacy-invading APIs in undisciplined ways to unscrupulous actors, it congratulates Cupertino on the next <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">kayfabe performance.</a> Links between Apple's monopoly over APIs and the growth of monopolies in adjacent sectors are rarely, if ever, questioned. Far too often, the tech press accepts the narrative structure of Apple's marketing, satisfying pangs of journalistic conscience with ineffectual critique of surface features, rather analyses of latent power imbalances.</p>
<p>Nowhere, e.g., in <a href="https://www.theverge.com/news/795248/former-apple-exec-iceblock-removal-criticism">The Verge's coverage of these letters</a> is there a discussion about alternatives to the App Store. Only a few outlets ever press Apple on its suppression of web apps, including failure to add <abbr title="Progressive Web App">PWA</abbr> install banners and essential capabilities. It's not an <em>Apple vs. Google</em> horse-race story, and so discussion of power distribution doesn't get coverage.</p>
<p>Settling for occasionally embarrassing Apple into partially reversing its most visibly egregious actions is ethically and morally stunted. Accepting the frame of <em>&quot;who should rule?&quot;</em> that Cupertino reflexively deploys is toxic to any hope of worthwhile technology because it creates and celebrates the idea of kings, leaving us supine relative to the mega-corps in our phones.</p>
<p>This is, in a word, childish.</p>
<p>Adults understand that things are complicated, that even the best intentioned folks get things wrong, or can go astray in larger ways. We build institutions and technologies to protect ourselves and those we love from the worst impacts of those events, and those institutions <em>always</em> model struggles over power and authority. If we are lucky and skilled enough to build them well, the results are balanced systems that attenuate attempts at imposing overt authoritarianism.</p>
<p>In other words, the exact opposite of Apple's infantilising and totalitarian world view.</p>
<p>Instead of debating which wealthy vassals might be more virtuous than the current rulers, we should instead focus on attenuating the power of these monarchical, centralising actors. The <abbr title="The EU's Digital Markets Act">DMA</abbr> is doing this, creating the conditions for interoperability, and through interoperability, competition. Apple know it, and <em>that's</em> why they're willing to pawn their own dignity, along with the rights of fellow Americans, to snuff out the threat.</p>
<p>These are not minor points. Apple has <em>power</em>, and that power comes from its effective monopoly on the APIs that make applications possible on the most important computing platform of our adult lives.</p>
<p>Protecting this power has become an end unto itself, curdling the pro-social narratives Apple takes pains to identify itself with. Any reporter that bothers to do <a href="https://open-web-advocacy.org/blog/balancing-security-and-fair-competition/">what a scrappy band of web developers have done</a> — to actually <em>read</em> the self-contradictory tosh Apple flings at regulators and legislators around the world — would have been able to pattern match; to see that twisting words to defend the indefensible isn't somehow alien to Apple. It's not even unusual.</p>
<p>But The Verge, 404, and even Wired are declining to connect the dots. If our luminaries can't or won't dig in, what hope do less thoughtful publications with wider audiences have?</p>
<p>Apple's power and profits have made it an enemy of democracy and civic rights at home and abroad. A mealy-mouthed tech press that cannot see or say the obvious is worse than useless; it is an ally in Apple's attempts to obfuscate.</p>
<p>The most important story about smartphones for at least the past decade has been <a href="https://infrequently.org/series/browser-choice-must-matter/">Cupertino's suppression of the web,</a> because that is a true threat to the App Store, and Apple's power flows from <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-unique-monopoly">the monopolies</a> it braids together. As Cory Doctorow observed:</p>
<blockquote>
<p>Apple's story – the story of all centralized, authoritarian technology – is that you have to trade freedom for security. If you want technology that Just Works(TM), you need to give up on the idea of being able to override the manufacturer's decisions. It's always prix-fixe, never a la carte.</p>
<p>This is a kind of vulgar Thatcherism, a high-tech version of her maxim that &quot;there is no alternative.&quot; Decomposing the iPhone into its constituent parts – thoughtful, well-tested technology; total control by a single vendor – is posed as a logical impossibility, like a demand for water that's not wet</p>
<p><span class="credit">        <a href="https://pluralistic.net/2025/09/28/works-well/#fails-well" taget="_blank">— Cory Doctorow,<br />&quot;Plenty of room at the bottom (of the tech stack)&quot;</a>      </span>    </p></blockquote><p></p>
<h2 id="the-price-of-high-modernism-is-dignity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#the-price-of-high-modernism-is-dignity">The Price of High Modernism is Dignity</a></h2>
<p><a href="https://pluralistic.net/2025/10/06/rogue-capitalism/#orphaned-syrian-refugees-need-not-apply">Doctorow's piece</a> on these outrages is a must-read, as it does what so many in the tech press fail to attempt: connecting patterns of behaviour over time and geography to make sense of Apple's capitulation. It also burrows into the rot at the heart of the App Store: the claim that anybody should have as much power as Apple has arrogated to itself.</p>
<p>We can see clearly now that this micro-authoritarian structure is easily swayed by macro-authoritarians, and bends easily to those demands. As James C. Scott <a href="https://home.uchicago.edu/csunstei/moreisless.html">wrote</a>:</p>
<blockquote>
<p>I believe that many of the most tragic episodes of state development in the late nineteenth and twentieth centuries originate in a particularly pernicious combination of three elements. The first is the aspiration to the administrative ordering of nature and society, an aspiration that we have already seen at work in scientific forestry, but one raised to a far more comprehensive and ambitious level. “High modernism” seems an appropriate term for this aspiration. As a faith, it was shared by many across a wide spectrum of political ideologies. Its main carriers and exponents were the avant-garde among engineers, planners, technocrats, high-level administrators, architects, scientists, and visionaries.</p>
<p>If one were to imagine a pantheon or Hall of Fame of high-modernist figures, it would almost certainly include such names as Henri Comte de Saint-Simon, Le Corbusier, Walther Rathenau, Robert McNamara, Robert Moses, Jean Monnet, the Shah of Iran, David Lilienthal, Vladimir I. Lenin, Leon Trotsky, and Julius Nyerere. They envisioned a sweeping, rational engineering of all aspects of social life in order to improve the human condition.</p>
<p><span class="credit">        — James C. Scott,<br />&quot;Seeing Like A State&quot;      </span>    </p></blockquote><p></p>
<p>This is also Apple's vision for the iPhone; an unshakeable belief in its own rightness and transformative power for good. Never mind all the folks that get hurt along the way, it is good <em>because Apple does it</em>. There is no claim more central to the mythos of Apple's marketing wing, and no deception more empowering to abusers of power.<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-self-deception-4" id="fnref-self-deception-4">4</a></sup></p>
<p>Apple claims to stand for open societies, but <a href="https://en.wikipedia.org/wiki/The_purpose_of_a_system_is_what_it_does"><abbr title="the Purpose Of the System Is What It Does">POSIWID</abbr></a> shows that to be a lie. It is not just corrupted, but itself has become corrupting; a corrosive influence on the day-to-day exercise of rights necessary for democracy and the rule-of-law to thrive.<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-available-choices-5" id="fnref-available-choices-5">5</a></sup></p>
<p>Apple's Le Corbusierian addiction to control has not pushed it into an alliance with those resisting oppression, but into open revolt against efforts that would make the iPhone an asset for citizens exercising their legitimate rights to aid the powerless. It scuttles and undermines open technologies that would aid dissidents. It bends the knee to tyranny because unchecked power helps Cupertino stave off competition, preserving (it thinks) a space for its own messianic vision of technology to lift others out of perdition.</p>
<p>If the consequences were not so dire, it would be tragically funny.</p>
<p>Let's hope our tech press find their nerve, and a copy of <a href="https://press.princeton.edu/books/paperback/9780691210841/the-open-society-and-its-enemies?srsltid=AfmBOopVprr3l-dLq6nmTTkWDK_rxxVEMN3_FgaZa5135_Qjfrp4UpgY"><em>“The Open Society and Its Enemies,&quot;</em></a> before we lose the ability to laugh.</p>
<h2 id="endnote%3A-let's-talk-about-google" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#endnote%3A-let's-talk-about-google">Endnote: Let's Talk About Google</a></h2>
<p>I spent a dozen and change years at Google, and my greatest disappointment in leadership over those years was the way the founders coddled the Android team's similarly authoritarian vision.</p>
<p>For the price of a prominent search box on every phone,<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-green-thumb-power-6" id="fnref-green-thumb-power-6">6</a></sup> senior leadership (including Sundar) were willing to <a href="https://arstechnica.com/google/2025/09/in-court-filing-google-concedes-the-open-web-is-in-rapid-decline/">sow the seeds of the web's obsolescence,</a> handing untold power to Andy Rubin's team of Java zealots. It was no secret that they sought to displace the web as the primary way for users to experience computing, substituting proprietary APIs for open platforms along the way.</p>
<p>With the growth of Android, Play grew in influence, in part as cover for Android's original sins.<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-rotten-to-the-roots-7" id="fnref-rotten-to-the-roots-7">7</a></sup> This led to a series of subtler, but no less effective, anti-web tactics that dovetailed with Apple's suppression of web apps on iOS. The <a href="https://developer.android.com/develop/ui/views/layout/webapps/trusted-web-activities">back doors</a> and <a href="https://www.pwabuilder.com/">exotic hoops</a> developers must jump through to gain distribution for interoperable apps remains a scandal.</p>
<p>But more than talking about Google and what it has done, we should talk about how we <em>talk about</em> Google. In specific, how the lofty goals of its Search origins were undercut by those anti-social, anti-user failures in Android and Play.</p>
<p>It's no surprise that Google is <a href="https://open-web-advocacy.org/blog/google-must-share-the-ability-to-install-web-apps-in-android/">playing disingenuous games</a> around providing access to competitors regarding web apps on Android, while simultaneously pushing to expand its control over app distribution. The Play team covet what Apple have, and far from exhibiting any self-awareness of their own culpability, are <a href="https://pluralistic.net/2025/09/01/fulu/#i-am-altering-the-deal">content to squander</a> whatever brand reputation Google may have left in order to expand its power over software distribution.</p>
<p>And nobody can claim that power is <a href="https://www.neowin.net/news/following-apple-google-pulls-ice-spotting-app-red-dot-from-play-store/">being used for good.</a></p>
<p>Google is not creating moral distance between itself and Apple, or seeking to help developers build <abbr title="Progressive Web Apps">PWAs</abbr> to steer around the easily-censored channels it markets, and totally coincidentally, taxes.<sup class="footnote-ref"><a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fn-knock-off-objectionability-8" id="fnref-knock-off-objectionability-8">8</a></sup> Google is Apple's collaborator in capitulation. A moral void, trotting out the same, tired tactic of hiding behind Apple's skirt whenever questions about the centralising and authoritarian tendencies of App Store monopolies crop up. For 15 years, Android has been content to pen 1-pagers for knock-off versions of whatever Apple shipped last year, including authoritarian-friendly acquiescence.</p>
<p>Play is now the primary software acquisition channel for most users around the world, and that should cause our tech press to <em>intensify</em> scrutiny of these actions, but that's not how Silicon Valley's wealth-pilled technorati think, talk, or write. The Bay Area's moral universe extends to the wall of the privilege bubble, and no further. We don't talk about the consequences of enshittified, trickle-down tech, or even bother to look hard at it. That would require using Android and…like…<em>eww</em>.</p>
<p>Far from brave truth-telling, the tech press we have today treats the tech the other half (80%) use as a curio; a destination to gawp at on safari, rather than a geography whose residents are just as worthy of dignity and respect as any other. And that's how Google is getting away with shocking acts of despicable cowardice to defend a parallel proprietary ecosystem of gambling, scams, and shocking privacy invasion, but with a fraction of the negative coverage.</p>
<p>And that's a scandal, too.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->
<!-- Footnotes Here -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-bonus-treats-1" class="footnote-item"><p>Does anyone doubt that Tim Apple's wishlist didn't also include a slap-on-the-wrist conclusion to the <a href="https://www.justice.gov/archives/opa/pr/justice-department-sues-apple-monopolizing-smartphone-markets"><em>US vs. Apple</em></a>?</p>
<p>And can anyone safely claim that, under an administration as nakedly corrupt as Donald Trump's, Apple couldn't buy off the DOJ? And what might the going rate for such policy pliability be?</p>
<p>That we have to ask says everything. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-bonus-treats-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-it-hopes-2" class="footnote-item"><p>It hopes. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-it-hopes-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-servile-frames-3" class="footnote-item"><p>I don't know Wiley Hodges, but the tone of <a href="https://wileyhodges.substack.com/p/my-email-to-tim-cook?r=qlwt">his letter</a> is everything I expect from Apple employees attempting to convince their (ex-)bosses: over-the-top praise, verging on hagiography, combined with overt appeals to the brand's value. This is how Apple discusses Apple to Apple, not just the outside world.</p>
<p>I have no doubt that this sort of sickly sweet presentation is necessary for even moderate criticism to be legible when directed up the chain. Autocracies are not given to debate, and Apple is nothing if not internally autocratic.</p>
<p>No large western company exerts deeper control over its image, prying deep into the personal lives of its employees in domineering ways to protect its brand from (often legitimate) critique that might undermine the message of the day. Every Apple employee not named &quot;Tim&quot; submits to an authoritarian regime all day, every day. It's no wonder that the demands of power come so easily to the firm. All of this is done to maintain the control that allows Marketing to cast Apple's image in a light that makes it the obvious answer to <em>&quot;who should rule?&quot;</em></p>
<p>But as we know, that question is itself the problem.</p>
<p>Hodges' <a href="https://substack.com/inbox/post/175654914">follow-up post is more open and honest,</a> and that's commendable. Now on the outside, he's visibly grasping with some level of deprogramming. Like the rest of us, he's discovering that Apple is demanding far more trust than its actions can justify. He's rightly disappointed that Apple isn't living up to the implications <a href="https://www.apple.com/compliance/pdfs/Apple-Human-Rights-Policy.pdf">of its stated commitment to open societies,</a> and that the stated justifications seem uncomfortably <em>ad hoc</em>, if not self-serving.</p>
<p>This discomfort stems from the difference between principle and PR.</p>
<p>Principles construct tests with which we must wrestle. Marketing creates frames that cast one party as an unambiguous hero. I've often joked that Apple is a marketing firm with an engineering side gig, and this is never more obvious than in the stark differences between communicated positions and revealed outcomes.</p>
<p>Reading these posts, I really feel for the guy, and wish him luck in convincing Apple to change course. If (as seems likely) it does not, I would encourage him to re-read that same <a href="https://www.apple.com/compliance/pdfs/Apple-Human-Rights-Policy.pdf">Human Rights Policy</a> and ask: &quot;<em>is this document a statement of principle or is it marketing collateral?</em>&quot; <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-servile-frames-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-self-deception-4" class="footnote-item"><p>The cultish belief that <em>&quot;it is good because we do it&quot;</em> is first and foremost a self-deception. It's so much easier to project confidence in this preposterous proposition when the messenger themselves is a convert.</p>
<p>The belief that <em>&quot;we should rule&quot;</em> is only possible to sustain among thoughtful people once the question <em>&quot;who should rule?&quot;</em> is deeply engrained. No wonder, then, that the firm works so dang hard to market its singular virtue to the internal, captive audience. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-self-deception-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-available-choices-5" class="footnote-item"><p>As I keep pointing out, <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#unilateral-off-ramps">Apple can make different choices.</a> Apple could unblock competing browsers <em>tomorrow</em>. It could fully and adequately fund the Safari team <em>tomorrow</em>. It could implement basic features (like install banners) that would make web apps more viable <em>tomorrow</em>. These are small technical challenges that Apple has used disingenuous rhetoric to blow out of all proportion as it has tried to keep the web at bay. But if Apple wanted to be on the side of the angels, it could easily provide a viable alternative for developers who get edited out of the App Store. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-available-choices-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-green-thumb-power-6" class="footnote-item"><p>Control over search entry points is the purest commercial analogue in Android to green/blue messages on iOS. Both work to dig moats around commodity services, erecting barriers to switching away from the OS's provider, and both have been fantastically successful in tamping down competition. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-green-thumb-power-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-rotten-to-the-roots-7" class="footnote-item"><p>It will never cease to be a scandal that Android's singular success metric in the Andy Rubin years was “activations.” The idea that more handsets running Android was success is a direct parallel to Zuckian fantasies about “connection” as an unalloyed good.</p>
<p>These are facially infantile metrics, but Google management allowed it to continue well past the sell-by date, with predictably horrendous consequences for user privacy and security. Play, and specifically the hot-potato of &quot;GMS Core&quot; (a.k.a., &quot;Play Services&quot;) were tasked with covering for the perennially out of date OSes running on client devices. That situation is scarcely better today. At last check, the ecosystem remains desperately fragmented, with huge numbers of users on outdated and fundamentally insecure releases. Google has gone so far as to remove these statistics from its public documentation site to avoid the press asking uncomfortable questions. Insecurity in service of growth is Android's most lasting legacy.</p>
<p>Like Apple, Andy Rubin saw the web as a threat to his growth ambitions, working to undermine it as a competitor at every step. Some day the full story of how <abbr title="Progressive Web Apps">PWAs</abbr> came to be will be told, but suffice to say, Android's rabid acolytes within the company did everything they could to prevent them, and when that was no longer possible, to slow their spread. <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-rotten-to-the-roots-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-knock-off-objectionability-8" class="footnote-item"><p>Don't worry, though, Play doesn't tax developers <em>as</em> much as Apple. So Google are the good guys. Right?</p>
<p>Right? <a href="https://infrequently.org/2025/10/the-app-store-was-always-authoritarian/#fnref-knock-off-objectionability-8" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>11ty Hacks for Fun and Performance</title>
    <link href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/"/>
    <updated>2025-10-04T00:00:00Z</updated>
    <id>https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/</id>
    <content type="html"><![CDATA[
      <p>This blog <em>really</em> isn't just for beating up on Apple for the way it <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">harms users,</a> <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/">the web,</a> <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">standards,</a> and <a href="https://infrequently.org/2025/09/apples-antitrust-playbook/">society</a> to maintain power and profits. So here's some fun stuff I've been doing in my <a href="https://www.11ty.dev/">11ty</a> setup to improve page performance.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#page-specific-resources-via-shortcodes-and-the-11ty-bundler">Page-Specific Resources via Shortcodes and the 11ty Bundler</a><ul><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#mo-pagination%2C-mo-problems">Mo Pagination, Mo Problems</a></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#build-time-impact">Build Time Impact</a></li></ul></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#scroll-position-based-delayed-code-loading">Scroll-Position Based Delayed Code Loading</a></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#faster-css-selectors-for-11ty-syntax-highlighting">Faster CSS Selectors for 11ty Syntax Highlighting</a></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#lean-rada's-css-only-low-quality-image-previews">Lean Rada's CSS-only Low-Quality Image Previews</a></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#better-abbrs">Bonus Hack: Global Acronyms for Better Abbreviations</a></li><li><a href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#does-it-work%3F">Does It Work?</a></li></ul></nav>
<h2 id="page-specific-resources-via-shortcodes-and-the-11ty-bundler" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#page-specific-resources-via-shortcodes-and-the-11ty-bundler">Page-Specific Resources via Shortcodes and the 11ty Bundler</a></h2>
<p>You know how it gets once you've got a mature 11ty setup: <a href="https://www.11ty.dev/docs/shortcodes/">shortcodes</a> proliferate, and some generate output that might depend on <abbr title="JavaScript">JS</abbr> or <abbr title="Cascading Style Sheets">CSS</abbr>.</p>
<p>If your setup is anything like mine, you might also feel conflicted about including some of those resources globally. It's important to have them available for the posts that need them, but it's not great to bring a charting library, e.g., into every page when only 1 in 20 will need it.</p>
<p>This blog has grown many such shortcodes that generate expansions for features like:</p>
<ul>
<li>
<p>Web Components for <a href="https://github.com/justinribeiro/lite-youtube">YouTube</a> and <a href="https://github.com/slightlyoff/lite-vimeo">Vimeo</a> embeds</p>
</li>
<li>
<p><a href="https://github.com/slightlyoff/wpt-embed">WebPageTest.org test embeds</a></p>
</li>
<li>
<p><a href="https://observablehq.com/plot/"><code>plot.js</code></a> based charts</p>
</li>
</ul>
<p>Here, for instance, is how a Vimeo embed looks in the markdown of a page, using Nunjucks for Markdown pre-processing:</p>
<pre class="language-njk" highlighted="highlighted"><code class="language-njk" highlighted="highlighted"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">vimeo</span> <span class="token string">"VIDEOID"</span><span class="token punctuation">,</span> <span class="token string">"TITLE"</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>This expands to:</p>
<pre class="language-html" highlighted="highlighted"><code class="language-html" highlighted="highlighted"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lite-vimeo</span> 
  <span class="token attr-name">videoid</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>VIDEOID<span class="token punctuation">"</span></span> 
  <span class="token attr-name">videotitle</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>TITLE<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://vimeo.com/VIDEOID<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>TITLE<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lite-vimeo</span><span class="token punctuation">></span></span></code></pre>
<p>But this also requires script; e.g.:</p>
<pre class="language-html" highlighted="highlighted"><code class="language-html" highlighted="highlighted"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> <span class="token attr-name">async</span>
    <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/js/lite-vimeo/lite-vimeo.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<p>And the list keeps growing. To avoid having the weight of these components clogging up every page, a system for selectively pulling in their code would be helpful.</p>
<p>It'd also be grand if we could make sure scripts appear just once, even if shortcodes are invoked multiple times per page. Included code should preferably also be located towards the top of the document.</p>
<p>The <a href="https://www.11ty.dev/docs/plugins/bundle/">11ty Bundle plugin</a> to the rescue!</p>
<p>Sort of.</p>
<p>At first glance, the 11ty Bundle plugin looks ideal for this, but we need to solve two problems the documentation doesn't cover:</p>
<ol>
<li>
<p>Shortcodes should auto-include the scripts they need, but not over-include them. How can we use Bundle plugin provided shortcodes from <em>within</em> other shortcodes? This is important to avoid having every page needing to remember to include scripts.</p>
</li>
<li>
<p>How to make this work with templates that use pagination?</p>
</li>
</ol>
<p>The first problem turns out to be very simple because 11ty shortcodes are themselves callable functions. Somewhere in my <code>.eleventy.js</code> configuration, there's now a function like:</p>
<pre class="language-js" highlighted="highlighted"><code class="language-js" highlighted="highlighted"><span class="token keyword">function</span> <span class="token function">addToBundle</span><span class="token punctuation">(</span><span class="token parameter">scope<span class="token punctuation">,</span> bundle<span class="token punctuation">,</span> code</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  eleventyConfig<span class="token punctuation">.</span><span class="token function">getPairedShortcode</span><span class="token punctuation">(</span>bundle<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> code<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This works because 11ty's internals are dogmatic about not binding <code>this</code>, allowing tools like shortcodes to be regular 'ole functions that can be invoked from dynamic scopes via <code>call()</code> and <code>apply()</code>. This is awesome!</p>
<p>The Vimeo shortcode then calls <code>addToBundle</code> to make sure that the <abbr title="JavaScript">JS</abbr> it depends on will get loaded:</p>
<pre class="language-js" highlighted="highlighted"><code class="language-js" highlighted="highlighted">eleventyConfig<span class="token punctuation">.</span><span class="token function">addShortcode</span><span class="token punctuation">(</span><span class="token string">"vimeo"</span><span class="token punctuation">,</span>
                            <span class="token keyword">function</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">""</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">addToBundle</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">"js"</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    &lt;script type="module" async
        src="/assets/js/lite-vimeo/lite-vimeo.js">
    &lt;/script>
  </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">let</span> titleAttr <span class="token operator">=</span> title <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> videotitle="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">" </span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    &lt;lite-vimeo videoid="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">" </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>titleAttr<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">>
      &lt;a href="http://vimeo.com/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/a>
    &lt;/lite-vimeo>
  </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The real code is a <em>tad</em> more complex to handle things like proper escaping, script file versioning, stripping whitespace to avoid markdown issues, etc…but not much. Page templates then include the usual:</p>
<pre class="language-html" highlighted="highlighted"><code class="language-html" highlighted="highlighted"><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
    <span class="token comment">&lt;!-- ... --></span>

    {% getBundle "js" %}

    <span class="token comment">&lt;!-- ... --></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
  <span class="token comment">&lt;!-- ... --></span></code></pre>
<p>And this should be it!</p>
<h3 id="mo-pagination%2C-mo-problems" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#mo-pagination%2C-mo-problems">Mo Pagination, Mo Problems</a></h3>
<p>Except it didn't work on my homepage.</p>
<p>Why not? Mostly because the 11ty Bundle plugin was built for <em>sane</em> sites; projects where a single output page's content doesn't need to hoist bundle inputs from across multiple entries. But I'm using <a href="https://www.11ty.dev/docs/pagination/">pagination</a>, like a mug.</p>
<p>I've <a href="https://github.com/11ty/eleventy-plugin-bundle/pull/38">got a patch out that addresses this</a>, hackily, and for now I'm using <code>package.json</code> overrides to target that branch. It seems to be working well enough here:</p>
<pre class="language-json5" highlighted="highlighted"><code class="language-json5" highlighted="highlighted"><span class="token punctuation">{</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"infrequently.org"</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
  <span class="token property">"devDependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"@11ty/eleventy"</span><span class="token operator">:</span> <span class="token string">"3.1.2"</span><span class="token punctuation">,</span>
    <span class="token property">"@11ty/eleventy-plugin-rss"</span><span class="token operator">:</span> <span class="token string">"^2.0.4"</span><span class="token punctuation">,</span>
    <span class="token property">"@11ty/eleventy-plugin-syntaxhighlight"</span><span class="token operator">:</span> <span class="token string">"^5.0.2"</span><span class="token punctuation">,</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"overrides"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"@11ty/eleventy-plugin-bundle"</span><span class="token operator">:</span> 
      <span class="token string">"https://github.com/slightlyoff/eleventy-plugin-bundle-pagination.git#pagination-aware"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span></code></pre>
<p>Now I can build shortcodes that use other shortcodes to bundle code only for the pages that need it, trimming the default <abbr title="JavaScript">JS</abbr> payload while leaving me free to build and use richer components as necessary.</p>
<h3 id="build-time-impact" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#build-time-impact">Build Time Impact</a></h3>
<p>The one downside of this approach has been an increase in build times.</p>
<p>I've worked to keep full re-builds under five seconds, and incremental builds under a second on my main writing device (a recent Chromebook). The Bundle plugin adds a post-processing phase (via <code>@11ty/eleventy/html-transformer</code>) to builds which tack on two seconds to both scenarios. This blog generates ~1,500 pages in a build, so the per page hit isn't bad, but it's enough to be noticeable.</p>
<p>I will likely spend time getting this trimmed back down in the near future. If you've got a smaller site, I can recommend the bundler-with-generative-shortcodes approach. If your site is much larger, it may be worth adopting if you're already paying the price of a post-processing step. Otherwise, and as ever, it's worth measuring.</p>
<h2 id="scroll-position-based-delayed-code-loading" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#scroll-position-based-delayed-code-loading">Scroll-Position Based Delayed Code Loading</a></h2>
<p>Loading code only on the pages that need it is great, but you know what's even better? Only loading code when it's going to actually be needed.</p>
<p>For a lot of pages, it makes sense to load specific widgets only when users scroll down far enough to encounter their content. Normally this is the sort of thing folks lean on big frameworks to handle, but that's not how this blog rolls. Instead, we'll use an <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><code>IntersectionObserver</code></a> and a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"><code>MutationObserver</code></a> to:</p>
<ul>
<li>
<p>Locate scripts that want deferred loading.</p>
</li>
<li>
<p>Use attributes on those elements to identify which elements they should be invoked for.</p>
</li>
<li>
<p>Watch the page scrolling and trigger the code loading when target elements get close enough to the viewport.</p>
</li>
</ul>
<p>Taken together, this reduces code loaded up front that might otherwise contend with above-the-fold resources without sacrificing interactive features further down the page.</p>
<p>Here, for instance, was how some code <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/">from a recent blog post that needed charts</a> looked before:</p>
<pre class="language-md" highlighted="highlighted"><code class="language-md" highlighted="highlighted">{% js %}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> 
    <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/js/d3.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> 
    <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/js/plot.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span> 

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
  <span class="token comment">// ...</span>
  <span class="token function">genFeatureTypePlot</span><span class="token punctuation">(</span><span class="token string">"leading"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">caption</span><span class="token operator">:</span> <span class="token string">"Chromium launches ... ahead of other engines."</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// ...</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
{% endjs %}

<span class="token title important"><span class="token punctuation">####</span> Leading Launches by Year</span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>leading<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>The Bundle plugin makes it simple to write code near the elements that will target it and not worry about duplicates. That's helpful, and the bundle plugin provides many tools for choosing where to output the gathered-up bits, but what I really want is to delay the fetching of those scripts until the user might plausibly benefit from them.</p>
<p>Here's what the revised code looks like:</p>
<pre class="language-md" highlighted="highlighted"><code class="language-md" highlighted="highlighted">{% js %}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>io+module<span class="token punctuation">"</span></span> <span class="token attr-name">data-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>leading<span class="token punctuation">"</span></span> 
    <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/js/d3.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>io+module<span class="token punctuation">"</span></span> <span class="token attr-name">data-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>leading<span class="token punctuation">"</span></span> 
    <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/assets/js/plot.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span> 

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>io+module<span class="token punctuation">"</span></span> <span class="token attr-name">data-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>leading<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
  <span class="token comment">// ...</span>
  <span class="token function">genFeatureTypePlot</span><span class="token punctuation">(</span><span class="token string">"leading"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">caption</span><span class="token operator">:</span> <span class="token string">"Chromium launches ... ahead of other engines."</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// ...</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
{% endjs %}

<span class="token title important"><span class="token punctuation">####</span> Leading Launches by Year</span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>leading<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>These scripts will still be hoisted into the <code>&lt;head&gt;</code>, but they won't execute because they are using a <code>type</code> attribute the browser doesn't recognise. The <code>data-for</code> attribute provides an ID of the element to trigger loading of the script. These are enough to build a scroll-based loader with.</p>
<p>Our loader uses a bit of inline'd script at the top of the page to set up an <code>IntersectionObserver</code> to watch scrolling, and a collaborating <code>MutationObserver</code> to identify elements matching this description as the parser creates them.</p>
<p>Here's the meat of that snippet, loaded early in the document as a <code>&lt;script type=&quot;module&quot;&gt;</code>. Pardon the pidgin JavaScript style; the last thing I want is a <abbr title="JavaScript">JS</abbr> transpiler as part of builds, so bytes matter:</p>
<pre class="language-js" highlighted="highlighted"><code class="language-js" highlighted="highlighted"><span class="token comment">// Utilities to delay code until the next task</span>
<span class="token keyword">let</span> rAF <span class="token operator">=</span> requestAnimationFrame<span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token function-variable function">doubleRaf</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">func</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token function">rAF</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">rAF</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Bookkeeping</span>
<span class="token keyword">let</span> ioScripts <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> ioScriptsFor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Map</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> triggerIDs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Record which scripts should wait on elements</span>
<span class="token keyword">let</span> <span class="token function-variable function">processScript</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">s</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>ioScripts<span class="token punctuation">.</span><span class="token function">has</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
  ioScripts<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> idFor <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">"data-for"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> isf <span class="token operator">=</span> ioScriptsFor<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>idFor<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>isf<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    isf <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    ioScriptsFor<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>idFor<span class="token punctuation">,</span> isf<span class="token punctuation">)</span><span class="token punctuation">;</span>
    triggerIDs<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>idFor<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  isf<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Handle existing scripts before setting up </span>
<span class="token comment">// the Mutation Observer</span>
document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">script[type="io+module"]</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>processScript<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Preload element tempalate;</span>
<span class="token keyword">let</span> plt <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"link"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
plt<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"rel"</span><span class="token punctuation">,</span> <span class="token string">"modulepreload"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// For a given element, begin loading scripts </span>
<span class="token comment">// that were waiting on it.</span>
<span class="token keyword">let</span> <span class="token function-variable function">triggerScripts</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> scripts <span class="token operator">=</span> ioScriptsFor<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> head <span class="token operator">=</span> document<span class="token punctuation">.</span>head<span class="token punctuation">;</span>
  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> s <span class="token keyword">of</span> scripts<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>s<span class="token punctuation">.</span>src<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token comment">// Get a preload request started</span>
    <span class="token keyword">let</span> pl <span class="token operator">=</span> plt<span class="token punctuation">.</span><span class="token function">cloneNode</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    pl<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"href"</span><span class="token punctuation">,</span> s<span class="token punctuation">.</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span>
    head<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>pl<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> s <span class="token keyword">of</span> scripts<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// Clone because setting type alone does not </span>
    <span class="token comment">// trigger evaluation.</span>
    <span class="token keyword">let</span> sc <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">cloneNode</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
    <span class="token comment">// Set type to an executable value</span>
    sc<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"type"</span><span class="token punctuation">,</span> <span class="token string">"module"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>sc<span class="token punctuation">.</span>src<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// External scripts</span>
      <span class="token keyword">let</span> lp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        sc<span class="token punctuation">.</span>onload <span class="token operator">=</span> res<span class="token punctuation">;</span> 
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      head<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>sc<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">await</span> lp<span class="token punctuation">;</span> <span class="token comment">// Serialisation handled above</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// Inline modules</span>
      head<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>sc<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> forObs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">IntersectionObserver</span><span class="token punctuation">(</span>
  <span class="token punctuation">(</span><span class="token parameter">entries</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    entries<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>intersectionRatio <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        forObs<span class="token punctuation">.</span><span class="token function">unobserve</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">doubleRaf</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token function">triggerScripts</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> 
  <span class="token punctuation">{</span>
    <span class="token comment">// If we boot far down the page, e.g. via back </span>
    <span class="token comment">// button scroll restoration, load eagerly. </span>
    <span class="token comment">// Else, watch two screens ahead:</span>
    <span class="token literal-property property">rootMargin</span><span class="token operator">:</span> <span class="token string">"1000% 0px 200% 0px"</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// When new elements are added, watch for scripts </span>
<span class="token comment">// with the right type and elements that scripts are </span>
<span class="token comment">// waiting on.</span>
<span class="token keyword">let</span> documentMo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MutationObserver</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">records</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> r <span class="token keyword">of</span> records<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>r<span class="token punctuation">.</span>addedNodes<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> n <span class="token keyword">of</span> r<span class="token punctuation">.</span>addedNodes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span>nodeType <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Elements only</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span>tagName <span class="token operator">===</span> <span class="token string">"SCRIPT"</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
           <span class="token punctuation">(</span>n<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">"io+module"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token function">processScript</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// If we find elements in the watch list, </span>
        <span class="token comment">// observe their scrolling relative to </span>
        <span class="token comment">// the viewport</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span>id <span class="token operator">&amp;&amp;</span> triggerIDs<span class="token punctuation">.</span><span class="token function">has</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          forObs<span class="token punctuation">.</span><span class="token function">observe</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

documentMo<span class="token punctuation">.</span><span class="token function">observe</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span>documentElement<span class="token punctuation">,</span> <span class="token punctuation">{</span> 
  <span class="token literal-property property">childList</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> 
  <span class="token literal-property property">subtree</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>That's the whole job done in just 110 lines of modern platform code, including utility functions and 20 lines of comments.</p>
<p>A few small tricks of note:</p>
<ul>
<li>
<p><code>&lt;link rel=&quot;modulepreload&quot; href=&quot;...&quot;&gt;</code> allows us to get network requests started without waiting on previous scripts to download, parse, and evaluate.</p>
</li>
<li>
<p>Limiting support to modules enables us to get async, but ordered, execution semantics.</p>
</li>
<li>
<p>The early <code>querySelectorAll()</code> ensures hoisted script blocks that occur before the inline'd script are handled correctly.</p>
</li>
</ul>
<p>As this was enough for the moment, I haven't implemented a few obvious improvements:</p>
<ul>
<li>
<p>This technique could be combined with shortcodes-calling-the-bundler to create shortcodes that dynamically load their code based on scroll position <em>and</em> only on pages that need them.</p>
</li>
<li>
<p>The <code>id</code>-based system is a bit fugly and can easily be upgraded to use any simple <abbr title="Cascading Style Sheets">CSS</abbr> selector that <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/matches"><code>matches()</code></a> supports.</p>
</li>
</ul>
<h2 id="faster-css-selectors-for-11ty-syntax-highlighting" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#faster-css-selectors-for-11ty-syntax-highlighting">Faster <abbr title="Cascading Style Sheets">CSS</abbr> Selectors for 11ty Syntax Highlighting</a></h2>
<p>It's a small thing, but I do try to optimise the <abbr title="Cascading Style Sheets">CSS</abbr> selectors used on this blog, as it's element-heavy and doesn't encapsulate much of the style-recalculation time work with Shadow DOM.</p>
<p>It was something of a surprise, then, to find that use of the <code>@11ty/eleventy-plugin-syntax-highlight</code> module's use of some basic styles cargo-culted many years ago was tanking style recalculation performance. How? Slow attribute rules:</p>
<pre class="language-css" highlighted="highlighted"><code class="language-css" highlighted="highlighted"><span class="token selector">code[class*="language-"],
pre[class*="language-"]</span> <span class="token punctuation">{</span>
	<span class="token property">color</span><span class="token punctuation">:</span> #f8f8f2<span class="token punctuation">;</span>
	<span class="token property">background</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
	<span class="token property">text-shadow</span><span class="token punctuation">:</span> 0 1px <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.3<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">/* ... */</span>
<span class="token punctuation">}</span></code></pre>
<p>Thanks to the prevalence of inline <code>&lt;code&gt;</code> blocks in my writing, the <a href="https://learn.microsoft.com/en-us/microsoft-edge/devtools/performance/selector-stats">Selector Stats panel</a> showed a fair few slow-path misses.</p>
<p>Thankfully, the fix is simple. In the <abbr title="Cascading Style Sheets">CSS</abbr> I switched to faster whole-attribute selectors:</p>
<pre class="language-css" highlighted="highlighted"><code class="language-css" highlighted="highlighted"><span class="token selector">code[highlighted],
pre[highlighted]</span> <span class="token punctuation">{</span>
	<span class="token property">color</span><span class="token punctuation">:</span> #f8f8f2<span class="token punctuation">;</span>
	<span class="token property">background</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
	<span class="token property">text-shadow</span><span class="token punctuation">:</span> 0 1px <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.3<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">/* ... */</span>
<span class="token punctuation">}</span></code></pre>
<p>Next, I used the configuration options available in the plugin (which I only figured out from reading the source) to specify those attributes be added to the <code>&lt;pre&gt;</code>s and <code>&lt;code&gt;</code>s generated by the syntax highlighter:</p>
<pre class="language-js" highlighted="highlighted"><code class="language-js" highlighted="highlighted"><span class="token keyword">import</span> syntaxHighlight <span class="token keyword">from</span> 
    <span class="token string">"@11ty/eleventy-plugin-syntaxhighlight"</span><span class="token punctuation">;</span>

<span class="token comment">// ...</span>

eleventyConfig<span class="token punctuation">.</span><span class="token function">addPlugin</span><span class="token punctuation">(</span>syntaxHighlight<span class="token punctuation">,</span> <span class="token punctuation">{</span>
  <span class="token comment">// For faster CSS selectors</span>
  <span class="token literal-property property">preAttributes</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">highlighted</span><span class="token operator">:</span> <span class="token string">"highlighted"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">codeAttributes</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">highlighted</span><span class="token operator">:</span> <span class="token string">"highlighted"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now the browser doesn't have to attempt a slow substring search every time it encounters one of these elements.</p>
<p>There's more to do in terms of selector optimisation on this site, but this was a nice quick win.</p>
<h2 id="lean-rada's-css-only-low-quality-image-previews" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#lean-rada's-css-only-low-quality-image-previews">Lean Rada's <abbr title="Cascading Style Sheets">CSS</abbr>-only Low-Quality Image Previews</a></h2>
<p>The history is boring, but suffice to note that the <code>&lt;img&gt;</code> helpers this site uses predate the official <a href="https://www.11ty.dev/docs/plugins/image/">11ty Image transform plugin</a>, and are tuned to generate URLs that work with Netlify's <a href="https://docs.netlify.com/build/image-cdn/overview/">Image CDN.</a> This means I've also been responsible for generating my own previews for images that haven't loaded yet, and devising strategies for displaying and animating them.</p>
<p>This has been, by turns, fun and frustrating.</p>
<p>The system relies on (you guessed it) shortcodes which both produce a list of images without previews and consume cached preview data to inline the scaled-down versions. Historically this worked by using <a href="https://sharp.pixelplumbing.com/">sharp</a> to generate low-res WebP (then AVIF) base64-encoded values that got blurred. I played a bit with <a href="https://blurha.sh/">BlurHash</a> and <a href="https://github.com/evanw/thumbhash">ThumbHash</a>, but the need for a <code>&lt;canvas&gt;</code> element was unattractive.</p>
<p>A better answer would have relied on <a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS_Painting_API"><abbr title="Cascading Style Sheets">CSS</abbr> custom paint</a>, but between Safari being famously <a href="https://webstatus.dev/stats?startDate=2015-01-01&amp;endDate=2025-10-04">rekt</a> (and representing large fraction of this blog's readership), and the Paint Worklet context missing <a href="https://developer.mozilla.org/en-US/docs/Web/API/ImageData/ImageData">the <code>ImageData()</code> constructor</a>, it never felt like a workable approach.</p>
<p>But as of this year, there's a new kid in town: <a href="https://leanrada.com/notes/css-only-lqip/">Lean Rada's badass <abbr title="Cascading Style Sheets">CSS</abbr>-only LQIP approach.</a></p>
<p>That system is now implemented, which does a lot to shrink the <abbr title="HyperText Markup Language">HTML</abbr> payloads of pages, as well as speeding up raster of the resulting image previews. This is visible in detailed traces, where the layout phase no longer has to wait for a background threads to synchronously decode image literals.</p>
<p>It took a few weekends of playing around to get it going correctly, as the code linked from Lean's blog post is not <a href="https://github.com/Kalabasa/leanrada.com/blob/src/main/scripts/update/lqip/lqip.mjs#L169">what he's using now.</a> The colourspace conversion code they're using is also inaccurate, and so attempts to replace it with <a href="https://www.npmjs.com/package/color-space"><code>color-space</code></a> produced visually incorrect results. Using <a href="https://github.com/Kalabasa/leanrada.com/blob/7b6739c7c30c66c771fcbc9e1dc8942e628c5024/main/scripts/update/lib/color/convert.mjs">the exact code they do for RGB-to-Lab conversion</a> is necessary to generate the correct effect, and dialling in those differences was time-consuming.</p>
<p>Happy to make the code I use for this available upon request, but it's not amazing, and you really should go read <a href="https://leanrada.com/notes/css-only-lqip/">Lean's blog post</a> for yourself. It's a masterpiece.</p>
<h2 id="better-abbrs" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#better-abbrs">Bonus Hack: Global Acronyms for Better Abbreviations</a></h2>
<p>I recently added <a href="https://github.com/markdown-it/markdown-it-abbr"><code>markdown-it-abbr</code></a> to my configuration to make some technical writing a bit more accessible. Across a few posts, this ended up with a lot of repetition for terms like “<abbr title="World Wide Web Consortium">W3C</abbr>”, “<abbr title="Internet Engineering Task Force">IETF</abbr>”, etc.</p>
<p>This was both a bit time-consuming and error-prone. What if, I wondered, it were possible to centralise them?</p>
<p>Turns out it's trivial! My setup pre-processes markdown as Nunjucks (via <a href="https://www.11ty.dev/docs/template-overrides/"><code>markdownTemplateEngine: &quot;njk&quot;</code></a>), which makes the full range of directives available, including…<a href="https://www.11ty.dev/docs/languages/nunjucks/#supported-features"><code>include</code></a>.</p>
<p>This means I can just create a single file with commonly used acronyms and <code>include</code> it from every page; the physical location is <code>_includes/acronyms.md</code>:</p>
<pre class="language-njk" highlighted="highlighted"><code class="language-njk" highlighted="highlighted"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">include</span> <span class="token string">"acronyms.md"</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>This doesn't improve performance, but has been hugely helpful for consistency.</p>
<h2 id="does-it-work%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/#does-it-work%3F">Does It Work?</a></h2>
<p>Putting it all together, what do we get?</p>
<br style="display: none;" />
<video controls="" preload="none" playsinline="" style="display: block; margin: 0px auto; width: 100%; max-width: 520px; aspect-ratio: 600 / 452;" poster="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/before-vs-after.avif">
  <source src="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/before-vs-after.webm" type="video/webm; codecs=av01.0.04M.08" />
  <source src="https://infrequently.org/2025/10/11ty-hacks-for-fun-and-performance/before-vs-after.mp4" type="video/mp4" />
</video>
<p>On <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/">a page</a> which previously saw contention between scripts for charts and above-the-fold fonts and initial layout work, the wins have been heartening on a low-spec test bench:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" breakdown="true" interval="100ms">
      <wpt-test label="Before: page with charts, Sept. 21st">        <script type="text/json" dir="/2025/10/11ty-hacks-for-fun-and-performance/traces/">          {"id":"250922_YiDcQH_14Q","url":"https://infrequently.org/2025/09/cupertinos-comforting-myths/","summary":"https://www.webpagetest.org/results.php?test=250922_YiDcQH_14Q","testUrl":"https://infrequently.org/2025/09/cupertinos-comforting-myths/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1758506680,"testRuns":3,"testName":"250922_YiDcQH_14Q","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/details/","checklist":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/breakdown/","domains":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/domains/","screenShot":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250922_YiDcQH_14Q/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/09/22/YiDcQH/14Q/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/09/22/YiDcQH/14Q/1_connection.png","checklist":"https://www.webpagetest.org/result/25/09/22/YiDcQH/14Q/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250922_YiDcQH_14Q&file=1_screen.jpg"},"breakdown":{"html":{"bytes":29174,"bytesUncompressed":94295,"requests":1},"js":{"bytes":153018,"bytesUncompressed":488888,"requests":2},"css":{"bytes":0,"bytesUncompressed":0,"requests":0},"image":{"bytes":23432,"bytesUncompressed":23432,"requests":2},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":87100,"bytesUncompressed":87100,"requests":2},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":909,"bytesUncompressed":4162,"requests":2}},"loadTime":3730,"docTime":3730,"fullyLoaded":4119,"firstPaint":2605,"firstContentfulPaint":2605,"firstMeaningfulPaint":2968,"lastVisualChange":3900,"visualComplete":3900,"visualComplete85":3000,"visualComplete90":3000,"visualComplete95":3000,"visualComplete99":3900,"SpeedIndex":2968,"TotalBlockingTime":759,"layoutShifts":[2856],"lcps":[2968],"navigationStart":62,"fetchStart":30,"domLoading":849,"responseEnd":1017,"domInteractive":1340,"domContentLoadedEventStart":3542,"domContentLoadedEventEnd":3542,"domComplete":3725,"unloadEventStart":833,"unloadEventEnd":833,"markAsMainFrame":833,"commitNavigationEnd":842,"firstImagePaint":2605,"firstMeaningfulPaintCandidate":2968,"loadEventStart":3730,"loadEventEnd":3730,"LargestTextPaint":2968,"LargestContentfulPaint":2968,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2600,"image":"filmstrip/ms_002600.jpg","VisuallyComplete":17},{"time":3000,"image":"filmstrip/ms_003000.jpg","VisuallyComplete":96},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":69,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
      <wpt-test label="After: page with charts, Oct. 4th">        <script type="text/json" dir="/2025/10/11ty-hacks-for-fun-and-performance/traces/">          {"id":"251004_ZiDc7V_2TZ","url":"https://infrequently.org/2025/09/cupertinos-comforting-myths/","summary":"https://www.webpagetest.org/results.php?test=251004_ZiDc7V_2TZ","testUrl":"https://infrequently.org/2025/09/cupertinos-comforting-myths/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1759568275,"testRuns":1,"testName":"251004_ZiDc7V_2TZ","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://infrequently.org/2025/09/cupertinos-comforting-myths/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":1},{"start":"0.10","end":"0.25","density":0},{"start":"0.25","density":0}],"percentiles":{"p75":"0.00"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.9252},{"start":800,"end":1800,"density":0.0584},{"start":1800,"density":0.0163}],"percentiles":{"p75":411}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.9676},{"start":1800,"end":3000,"density":0.0192},{"start":3000,"density":0.0132}],"percentiles":{"p75":715}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.9743},{"start":2500,"end":4000,"density":0.0193},{"start":4000,"density":0.0063}],"percentiles":{"p75":714}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.6509},{"start":75,"end":275,"density":0.3196},{"start":275,"density":0.0295}],"percentiles":{"p75":81}}},"collectionPeriod":{"firstDate":{"year":2025,"month":9,"day":5},"lastDate":{"year":2025,"month":10,"day":2}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/details/","checklist":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/breakdown/","domains":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/domains/","screenShot":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/251004_ZiDc7V_2TZ/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/10/04/ZiDc7V/2TZ/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/10/04/ZiDc7V/2TZ/1_connection.png","checklist":"https://www.webpagetest.org/result/25/10/04/ZiDc7V/2TZ/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=251004_ZiDc7V_2TZ&file=1_screen.jpg"},"breakdown":{"html":{"bytes":31392,"bytesUncompressed":105204,"requests":1},"js":{"bytes":0,"bytesUncompressed":0,"requests":0},"css":{"bytes":0,"bytesUncompressed":0,"requests":0},"image":{"bytes":23432,"bytesUncompressed":23432,"requests":2},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":87100,"bytesUncompressed":87100,"requests":2},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":552,"bytesUncompressed":552,"requests":1}},"loadTime":1686,"docTime":1686,"fullyLoaded":2296,"firstPaint":2058,"firstContentfulPaint":2058,"firstMeaningfulPaint":2058,"lastVisualChange":2100,"visualComplete":2100,"visualComplete85":2100,"visualComplete90":2100,"visualComplete95":2100,"visualComplete99":2100,"SpeedIndex":2100,"TotalBlockingTime":0,"layoutShifts":[],"lcps":[2058],"navigationStart":96,"fetchStart":71,"domLoading":829,"responseEnd":1025,"domInteractive":1094,"domContentLoadedEventStart":1123,"domContentLoadedEventEnd":1123,"domComplete":1684,"unloadEventStart":824,"unloadEventEnd":824,"markAsMainFrame":825,"commitNavigationEnd":827,"loadEventStart":1685,"loadEventEnd":1685,"firstMeaningfulPaintCandidate":2058,"LargestTextPaint":2058,"LargestContentfulPaint":2058,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2100,"image":"filmstrip/ms_002100.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":51,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>The long tent pole is now Netlify's pokey connection setup and TTFB, and I'm content (if not happy) with that.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

    ]]></content>
  </entry>
  <entry>
    <title>Apple&#39;s Antitrust Playbook</title>
    <link href="https://infrequently.org/2025/09/apples-antitrust-playbook/"/>
    <updated>2025-09-25T00:00:00Z</updated>
    <id>https://infrequently.org/2025/09/apples-antitrust-playbook/</id>
    <content type="html"><![CDATA[
      <nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/09/apples-antitrust-playbook/#lies-by-any-other-name">Lies by Any Other Name</a></li><li><a href="https://infrequently.org/2025/09/apples-antitrust-playbook/#great-artists-steal">Great Artists Steal</a></li><li><a href="https://infrequently.org/2025/09/apples-antitrust-playbook/#dear-tech-reporters%3A-access-is-not-a-beat">Dear Tech Reporters: Access Is Not A Beat</a></li></ul></nav>
<p>This blog is failing on several levels. First, September 2025 is putting the “frequent” in “infrequently”, much to my chagrin. Second, my professional mission is to make a web that's better for everyone, not to tear Apple down.</p>
<p>But <a href="https://www.youtube.com/watch?v=UneS2Uwc6xw">just when I thought I was out, they pull me back in.</a></p>
<p>Over the past 24 hours, Cupertino has played the hits from its iPhone-era anti-user, anti-business, anti-rule-of-law power trip. To recap:</p>
<ul>
<li>
<p>Apple sent a demand that the EU give up on <abbr title="The EU's Digital Markets Act">DMA</abbr> enforcement in a <a href="https://www.apple.com/newsroom/2025/09/the-digital-markets-acts-impacts-on-eu-users/">petulant and utterly misleading press release</a> that mostly served to catalogue Apple's own failures to comply.</p>
</li>
<li>
<p>Cupertino's <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">kept astroturf outfit</a> — <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">ACT | The App Association</a> — penned <a href="https://www.aei.org/technology-and-innovation/can-small-tech-survive-the-digital-markets-act/">unhinged misinformation</a> for consumption by US regulatory types (<a href="https://www.linkedin.com/posts/damiengeradin_can-small-tech-survive-the-digital-markets-activity-7376973488991137792-M_kG?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAAAAfs0gBbCjBFw-tWrcEzKFZ3GZTvTD2Pms">h/t Damien Geradin</a>).</p>
</li>
<li>
<p>The EC then <a href="https://www.france24.com/en/live-news/20250925-apple-asks-eu-to-scrap-landmark-digital-competition-law">called Apple's bluff.</a></p>
</li>
</ul>
<p>Make no mistake about what's going on: Apple is claiming that the EU is forcing Apple to adopt interpretations of the <abbr title="The EU's Digital Markets Act">DMA</abbr> that no other party has, which the EC itself has not backed, and which are “forcing” Apple to avoid shipping features in the EU.</p>
<p>Or, put another way, Apple wants to launder the consequences of its own anticompetitive, anti-user choices through a credulous tech press. The goal is to frame regulators for Apple's own deeds.</p>
<h2 id="lies-by-any-other-name" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-antitrust-playbook/#lies-by-any-other-name">Lies by Any Other Name</a></h2>
<p>If this smells like bullshit, that's because it is.</p>
<p>Apple tried similar ploys last year when it sprung <a href="https://infrequently.org/2024/02/home-screen-advantage/">a blatant attempt to kill <abbr title="Progressive Web Apps">PWAs</abbr></a> on the EU as a price for having the temerity to regulate. The plan, it seemed then, was to adopt an exotic reading of the <abbr title="The EU's Digital Markets Act">DMA</abbr> and frame the EC for killing <abbr title="Progressive Web Apps">PWAs</abbr>.</p>
<p>What Apple's attempting now is even more brazen, particularly after <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">16+ months of serial non-compliance since the <abbr title="The EU's Digital Markets Act">DMA</abbr> came into force (h/t <abbr title="Open Web Advocacy">OWA</abbr>).</a></p>
<p>Remember that:</p>
<ul>
<li>
<p>Apple's browser, and by extension every iOS browser, fails on <a href="https://research.google/pubs/analysis-of-uxss-exploits-and-mitigations-in-chromium/">basic security</a> and <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">privacy controls,</a> putting users at risk constantly. Apple serially misrepresents this situation to anyone who will listen.</p>
</li>
<li>
<p>Cupertino has constructed a <a href="https://developer.apple.com/contact/request/download/web_browser_engine.pdf">legal (PDF)</a> and <a href="https://issues.chromium.org/hotlists/5909213">technical thicket</a> that prevents competitors from building better browsers, including:</p>
<ul>
<li>
<p>Geofencing choice to the EU.</p>
</li>
<li>
<p>Forcing users to download <em>separate</em> browsers to access better versions (should they appear).</p>
</li>
<li>
<p>Withholding <abbr title="Progressive Web App">PWA</abbr> and Push Notification APIs from competitors.</p>
</li>
<li>
<p>Providing a busted SDK that included multiple show-stopping bugs.</p>
</li>
<li>
<p>Making the process of acquiring and using the necessary entitlements for development nearly impossible.</p>
</li>
<li>
<p>Gaslighting the EC and the press at every turn; simultaneously claiming it is complying, while complaining loudly that it has to do work to implement the wholly unnecessary hurdles to compatibility that Apple itself created.</p>
</li>
</ul>
</li>
<li>
<p>Apple have used every opportunity to rubbish both the spirit and letter of the law, spreading outlandish claims about user harms. These claims keep getting rejected whenever they're weighed by regulators and independent third parties.</p>
</li>
</ul>
<p><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">All of this to prevent the web from threatening the App Store, via the <abbr title="The EU's Digital Markets Act">DMA</abbr>.</a></p>
<p>Add today's shake-down, and we see an assault on the rule of law. <a href="https://www.anildash.com/2025/09/09/how-tim-cook-sold-out-steve-jobs/">Tim's appearance in The Oval bearing gaudy-ass trinkets</a> makes sense as a kickback for <a href="https://www.eunews.it/en/2025/08/26/trump-threatens-countries-over-digital-regulations-eu-fires-back-we-decide-our-own-rules/">services rendered</a> against the idea of laws. Or at least laws that bind those with power the way they constrain everyone else.</p>
<p>This is not a one-off or a fluke.</p>
<p>The name of the game is delay, and Apple is using the same tactics it has practised to maintain profits through outrageous <a href="https://www.repair.org/blog/2023/9/25/apples-war-on-right-to-repair-through-serial-numbers">attacks on the right-to-repair</a> and <a href="https://www.ifixit.com/News/82837/you-cant-be-green-and-restrict-repair">sensible anti-e-waste regulation.</a> When you're the incumbent, delay is winning. Apple has pulled out all the stops to prevent the web from providing a safer, more private alternative to native apps, winning long reprieves thus far. And you should see what <a href="https://proton.me/blog/apple-dma-compliance-plan-trap">they did on the native side. <em>phew</em>.</a></p>
<p>This is extremely embarrassing for the EU, which has attempted to respond thoughtfully and reasonably to every provocation. But appeasement of Cupertino isn't working.</p>
<h2 id="great-artists-steal" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-antitrust-playbook/#great-artists-steal">Great Artists Steal</a></h2>
<p>Apple didn't author the playbook it's using now; it has been developed and honed for 40 years by toxic industries trying feverishly to escape the consequences of their actions. Most famously, the tactics Apple is gleefully employing served <a href="https://www.cnn.com/2021/05/13/business/exxon-climate-change-harvard">Big Oil and Big Tobacco extremely well</a>:</p>
<ol>
<li>
<p><strong>Lobbying</strong> (legalised corruption).</p>
<p>This works a shockingly large fraction of the time, and was <a href="https://prospect.org/power/2023-01-26-chuck-schumer-tech-antitrust-bills/">sufficient to kill effective regulation of the smartphone ecosystem</a> in the US during Biden's term, despite overwhelming evidence from <a href="https://www.ntia.gov/report/2023/competition-mobile-app-ecosystem">the <abbr title="National Telecommunications and Information Administration">NTIA</abbr>'s exhaustive report.</a></p>
<p>If first-party lobbying hits roadblocks — e.g., being absolutely outclassed by civil society groups that see the real threats and costs of your actions — there are alternatives, including...</p>
</li>
<li>
<p><strong>Astroturf.</strong></p>
<p>If &quot;ACT&quot; rings a bell, it might be <a href="https://web.archive.org/web/20220615074848/http://www.fosspatents.com/2022/04/microsoft-rightly-withdrew-support-for.html">for the role it played in the '90s in the (hollow) defence of Microsoft.</a></p>
<p>These days, it's a bought-and-paid-for megaphone for Apple, and it is <a href="https://ipfray.com/apple-funded-astroturfers-caught-lying-about-organizations-etsi-membership-act-the-apple-association/">working to worm its way into EU policy circles</a> too. For a flavour of the Klein bottle arguments it serves up regularly, imagine arguing that more choice than a single App Store would be bad <a href="https://actonline.org/2024/03/21/doj-v-apple-statement/">because it would hurt <em>small</em> developers.</a> 🤯</p>
</li>
<li>
<p><strong>Market false comparison points.</strong></p>
<p>Apple has a point about privacy and security when it comes to Android, e.g., but why is that our comparison point? Why is the App Store's historic failure to safeguard anyone from anything (by comparison to browsers) our collective counterfactual? It's nonsense. Hot tosh. But it's marketed with gusto and zeal in the hopes that nobody will notice. And the tech press, to their everlasting discredit, have more than played along.</p>
<p>When that doesn't work...</p>
</li>
<li>
<p><strong>Perform petulance.</strong></p>
<p>If a regulator or government has the stones to stand up for its own democratic polity in a way that attacks your profit potential, go to the matresses. Let everyone know they'll be sorry. <a href="https://theplatformlaw.wpcomstaging.com/2024/01/26/when-apple-takes-the-european-commission-for-fools-an-initial-overview-of-apples-new-terms-and-conditions-for-ios-app-distribution-in-the-eu/">Throw as big a hissyfit as you can manage,</a> then make the same false claims <a href="https://developer.apple.com/security/complying-with-the-dma.pdf"><em>over and over.</em></a></p>
<p>To make obvious falsehoods stick, shameless repetition, at volume, is a must.</p>
</li>
<li>
<p><strong>Market your &quot;compliance.&quot;</strong></p>
<p>But under no circumstances, actually comply.</p>
<p>The trick here is to performatively roll out processes and press briefings telling everyone how seriously you take all of this while actively gumming up the works. Apple have done this on the regular since the <abbr title="The EU's Digital Markets Act">DMA</abbr>'s passage, and if that rhymes with various ongoing plots against right-to-repair after public claims to support it...well...</p>
</li>
<li>
<p><strong>Claim law hurts kittens, blame regulators</strong></p>
<p>Doesn't have to be kittens, obviously. Jobs, privacy, apple pie...anything that seems sympathetic will do. Just make fig-leaf claims to support your side and lean heavily into <em>&quot;won't someone think of the kids?&quot;</em></p>
<p>Assuming your bought-and-paid-for astroturfers and docile access-journalism reporters are still on speed dial, <code>GOTO 2</code>, safe in the assumption that regulators won't do much.</p>
</li>
</ol>
<p>Honestly, it's a winning formula, assuming you have more money than Croesus and lawyers willing to make claims they know to be untrue. All they better if they're so well paid that they can't be bothered to check.</p>
<p>It only falls apart if the folks whose job it is to ferret out the truth, and the people whose role is to stand up for citizens against vested interests, <em>do their jobs.</em></p>
<h2 id="dear-tech-reporters%3A-access-is-not-a-beat" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-antitrust-playbook/#dear-tech-reporters%3A-access-is-not-a-beat">Dear Tech Reporters: Access Is Not A Beat</a></h2>
<p>At the risk of stating the obvious, it does not matter what your relationship to Cupertino is. It's in your head. They threaten to call your boss? Or to stop talking to you? So what? They always do that. To everyone. All the time. Ask anyone. There's no upside, and you can <em>never</em> be on the inside. You were always being managed.</p>
<p>Cupertino's gonna threaten to stop running ads on your site? <em>Print that</em>.</p>
<p>Where are your stones? Why did you get into journalism? Or technology? Or technology journalism? <em>What, would you say, 'ya do here?</em></p>
<p>The obvious stenography around competition issues is mind-numbing when the theory of the case is so bloody simple. Apple and Google want everyone in their app stores <em>because that's how they maintain power,</em> and through that power, <em>profits</em>. They have arranged things such that being in the App Store is the only way developers get access to critical APIs, and those APIs are the only way to make functional apps.</p>
<p>Apple's fighting real browsers and the <abbr title="The EU's Digital Markets Act">DMA</abbr> because they're a threat to that model. Browsers, and the <abbr title="Progressive Web Apps">PWAs</abbr> they enable, are the open, tax-free alternative to app stores, and the Duopolists are extremely displeased that they exist, even in the degraded form they currently allow.</p>
<p>This is simple. Obvious. <em>Incredibly transparent.</em></p>
<p>But almost nobody will connect the dots in print. And that's a scandal, too.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->

    ]]></content>
  </entry>
  <entry>
    <title>Comforting Myths</title>
    <link href="https://infrequently.org/2025/09/cupertinos-comforting-myths/"/>
    <updated>2025-09-23T00:00:00Z</updated>
    <id>https://infrequently.org/2025/09/cupertinos-comforting-myths/</id>
    <content type="html"><![CDATA[
      <aside class="update">
<p><strong>Update:</strong><br />
The charts below were inappropriately snapped, compressing the range of values. This has been corrected. Feature availability numbers also changed since drafting and have been updated.</p>
</aside>
<p>In several recent posts, I've attempted to address how the structure of standards bodies <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/">and their adjacent incubation venues</a> accelerates or <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">suppresses the potential</a> of the web as a platform. The pace of progress matters because <a href="https://infrequently.org/2024/10/platforms-are-competitions/">platforms are competitions</a>, and actors that <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">prevent expansions of basic capabilities</a> risk consigning the web to the dustbin.</p>
<p>Inside that framework, there is much to argue over regarding the relative merits of specific features and evolutionary directions. This is healthy and natural. We should openly discuss features and their risks, try to prevent bad consequences, and work to mend what breaks. This competitive process has made browsers incredibly safe and powerful for 30 years.</p>
<p><a href="https://infrequently.org/2021/04/progress-delayed/">Until iOS,</a> that is.</p>
<p>Imagine my surprise upon hearing that Apple <em>isn't</em> attempting to freeze the web in amber, preserving advantages for its proprietary platform, and that it instead offers to redesign proposals it disagrees with.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#background">Background</a></li><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#is-apple-engaged-in-constructive-api-redesign%3F">Is Apple Engaged In Constructive API Redesign?</a><ul><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#general-trends">General Trends</a></li><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#hard-cases">Hard Cases</a></li></ul></li><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#overall-impressions">Overall Impressions</a></li><li><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#what's-happening-here%3F">What's Happening Here?</a></li></ul></nav>
<p><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-u-turns-1">As I have occasionally documented</a>, this has not been my experience. I have relatively broad exposure to the patterns of Apple's collaboration, having designed, advised on, or led teams that built dozens of features across disparate areas of the platform since the Blink fork.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-unique-perch-1" id="fnref-unique-perch-1">1</a></sup></p>
<p>But perhaps this was the wrong slice from which to judge? I've been hearing of Apple's openness to collaboration on challenging APIs so often that either my priors are invalid, or something else is at work. To find out, I needed data.</p>
<h2 id="background" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#background">Background</a></h2>
<p>A specific parry gets deployed whenever WebKit's sluggish feature pace comes up: <em>“controversial”</em> features <em>“lack consensus”</em> or <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/"><em>“are not standards”</em></a> or <em>“have privacy and security problems”</em> (unspecified). The corollary being that Apple engages in good-faith to address <a href="https://mdn.dev/archives/insights/reports/mdn-web-developer-needs-assessment-2020.html#needs-assessment-progressive-programmers">these developer needs</a> in other ways, even in areas where they have <a href="https://github.com/WebKit/standards-positions/issues?q=label%3A%22position%3A%20oppose%22">overtly objected.</a></p>
<p>Apple's engine has <a href="https://infrequently.org/2021/04/progress-delayed/#confluence">indisputably</a> trailed Blink and Gecko in all manner of features over the past decade. This would not be a major problem, except that <a href="https://infrequently.org/2021/04/progress-delayed/">Apple prevents other browsers from delivering better and more competitive web engines on iOS.</a></p>
<p>Normally, consequences for not adopting certain features arrive in the market. Browsers that <a href="https://webstatus.dev/stats?startDate=2015-01-01&amp;endDate=2025-09-01">fail to meet important needs,</a> or <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">drop the ball on quality</a> lose share. This does not hold on iOS because no browser can ship a less-buggy or more capable engine than Apple's WebKit.</p>
<p>Because <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">competitors are reduced to rebadging WebKit,</a> Apple has created new responsibilities and expectations for itself.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-many-options-2" id="fnref-many-options-2">2</a></sup> Everyone knows iOS <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-unique-monopoly">is the only way to reach wealthy users,</a> and no browser can afford to be shut out of that slice of the mobile market. Therefore, the quality and features of Apple's implementation matter greatly to the health and competitiveness of the web.</p>
<p>This put's Apple's actions squarely in the spotlight.</p>
<h2 id="is-apple-engaged-in-constructive-api-redesign%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#is-apple-engaged-in-constructive-api-redesign%3F">Is Apple Engaged In Constructive API Redesign?</a></h2>
<p>It's possible to size up Apple's appetite for problem-solving in several ways. We can look to understand how frequently Apple ships features ahead of, or concurrently with, other engines because near-simultaneous delivery is an indicator of co-design. We can also look for visible indications of willingness to engage on thorny designs, searching for counter-proposals and shipped alternatives along the way.</p>
<h3 id="general-trends" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#general-trends">General Trends</a></h3>
<p>This chart tracks single-engine omissions over the past decade; a count of designs which two engines have implement but which a single holdout prevents from web-wide availability:</p>
<p></p><figure class="full_wide"><a href="https://webstatus.dev/stats?startDate=2015-09-15&endDate=2025-09-15" alt="Features missing in one engine, '15-25. Lower is better.<br>Safari consistently trails every other engine, and APIs missing from it impact every iOS browser." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/webstatus-missing-features.avif" alt="Features missing in one engine, '15-25. Lower is better.<br>Safari consistently trails every other engine, and APIs missing from it impact every iOS browser." style="aspect-ratio: 1322 / 455" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>Features missing in one engine, '15-25. Lower is better.<br />Safari consistently trails every other engine, and APIs missing from it impact every iOS browser.</figcaption>      </figure><p></p>
<p>Thanks to the same <a href="https://webstatus.dev/stats">Web Features</a> data set, many views are possible. This data shows that there are currently <a href="https://webstatus.dev/?q=-available_on%3Asafari+available_on%3Achrome&amp;sort=availability_safari_desc&amp;num=100">178 features in Chromium that are not available in Safari,</a> and <a href="https://webstatus.dev/?q=available_on%3Asafari+-available_on%3Achrome&amp;sort=availability_safari_desc&amp;num=100">34 features in Safari that are not yet in Chromium.</a> (or <a href="https://webstatus.dev/?q=-available_on%3Asafari_ios+available_on%3Achrome_android&amp;sort=availability_safari_desc&amp;num=100">179</a> and <a href="https://webstatus.dev/?q=available_on%3Asafari_ios+-available_on%3Achrome_android&amp;sort=availability_safari_desc&amp;num=100">37</a> for mobile, respectively). But as I've <a href="https://infrequently.org/2021/04/progress-delayed/">noted previously,</a> point-in-time evaluations may not tell us very much.</p>
<p>I was curious about delays in addition to omissions. How often do we see evidence of simultaneous shipping, indicating strong collaboration? Is that more or less likely than leading vendors feeling the need to go it alone, either because of a lack of collaborative outreach, or because other vendors do not engage when asked?</p>
<p>To get a sense, I downloaded all the available data (<a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/stats/stats.json">JSON file</a>), removed features with no implementations, removed features introduced before 2015, filtered to Chrome, Safari, and Firefox, then aggregated by year. The resulting data set is <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/stats/year-stats.json">here (JSON file).</a></p>
<p>The data can't determine causality, but can provide directional hints:</p>
<h4 id="leading-launches-by-year" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#leading-launches-by-year">Leading Launches by Year</a></h4>
<div id="leading"></div>
<h4 id="features-shipped-within-one-year-of-the-leader" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#features-shipped-within-one-year-of-the-leader">Features Shipped Within One Year of the Leader</a></h4>
<div id="sim-ship"></div>
<h4 id="features-shipped-two%2B-years-after-the-leader" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#features-shipped-two%2B-years-after-the-leader">Features Shipped Two+ Years After the Leader</a></h4>
<div id="catch-up"></div>
<p>Safari rarely leads, but that does not mean other vendor's designs will stand the test of time. But if Apple engages in solving the same problems, we would expect to see Safari leading on alternatives<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-peer-pressure-3" id="fnref-peer-pressure-3">3</a></sup> or driving up the rates of simultaneously shipping features once consensus emerges. But these aren't markedly increased. Apple can, of course, <a href="https://www.bloomberg.com/news/articles/2024-05-01/google-s-payments-to-apple-reached-20-billion-in-2022-cue-says">afford to fund work into substitutes for “problematic” APIs,</a> but it doesn't seem to.</p>
<p>Narratives about collaboration in tricky areas take more hits from Safari's higher incidence of catch-up launches. These indicate Apple shipping <em>the same</em> design that other vendors led with, but on a delay of two years or more from their first introduction. This is not redesign. If there were true objections to these APIs, we wouldn't expect to see them arrive at all, yet Apple has done more catching up over the past several years than it has shipped APIs <em>with</em> other vendors.</p>
<p>This fails to rebut intuitions developed from recent drops of Safari features (<a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/">1,</a> <a href="https://infrequently.org/2025/06/the-ghost-of-christmas-past/">2</a>) composed primarily of APIs that Apple's engineers were not primary designers of.</p>
<p>But perhaps this data is misleading, or maybe I analysed it incorrectly. I have heard allusions to engagement regarding APIs that Apple has publicly rejected. Perhaps those are where Cupertino's standards engineers have invested their time?</p>
<h3 id="hard-cases" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#hard-cases">Hard Cases</a></h3>
<p>Most of the hard cases concern APIs that Apple (and others) have rightly described as having potentially concerning privacy and security implications. Chromium engineers agreed those concerns have merit and worked to address them; we called it “Project Fugu” <a href="https://en.wikipedia.org/wiki/Fugu">for a reason</a>. In addition to meticulous design to mitigate risks, part of the care taken included continually requesting engagement from other vendors.</p>
<p>Consider the tricky cases of <a href="https://caniuse.com/midi">Web MIDI,</a> <a href="https://caniuse.com/?search=usb">Web USB,</a> and <a href="https://caniuse.com/web-bluetooth">Web Bluetooth.</a></p>
<h4 id="web-midi" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#web-midi">Web MIDI</a></h4>
<p>Apple <a href="https://developer.apple.com/documentation/coremidi/">has supported MIDI</a> in macOS <a href="https://en.wikipedia.org/wiki/Mac_OS_X_Tiger">for at least 20 years</a> — likely much longer — and added iOS support for MIDI in <a href="https://www.engadget.com/2010-11-05-ios-4-2-to-support-midi.html">2010</a>. By the time the first <a href="https://www.smashingmagazine.com/2018/03/web-midi-api/">Web MIDI</a> proposals broke cover in 2012, MIDI hardware and software were the backbone of digital music and a billion dollar business; Apple's own physical stores were stocking racks of MIDI devices for sale. Today, an overwhelming fraction of MIDI devices explicitly list their compatibility with iOS and macOS.</p>
<p>It was therefore a clear statement of Apple's intent to cap web capabilities when it objected to Web MIDI's <a href="https://lists.webkit.org/pipermail/webkit-dev/2013-January/thread.html#23376">development <em>just</em> before the Blink fork.</a> The objections by Apple were by turns <a href="https://lists.webkit.org/pipermail/webkit-dev/2013-January/023383.html">harsh</a>, <a href="https://lists.webkit.org/pipermail/webkit-dev/2013-January/023386.html">condescendingly ignorant</a> and <a href="https://lists.webkit.org/pipermail/webkit-dev/2013-January/023391.html">imbued with self-fulfilling stop-energy</a>; patterns that would repeat post-<a href="https://www.chromium.org/blink/">fork.</a></p>
<p>After several years of open development (which Cupertino declined to participate in), Web MIDI <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/oPyFORhQ9jQ/m/1_i9q6AOSXgJ">shipped in Chromium in early 2015</a>. Despite a decade to engage, Apple has not shipped Web MIDI, has not provided a <a href="https://webkit.org/standards-positions/">“standards position”</a> for it<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-arguable-4" id="fnref-arguable-4">4</a></sup>, and has not proposed an alternative. To the best of my knowledge, it has also not engaged in conversations about the core feature set, despite being a member of the <abbr title="World Wide Web Consortium">W3C</abbr>'s <a href="https://www.w3.org/groups/wg/audio/">Audio Working Group</a> which has published many <a href="https://www.w3.org/TR/webmidi/">Working Drafts of the API.</a> That group has consistently <a href="https://www.w3.org/2011/audio/charter/2012/">included publication of Web MIDI as a goal since 2012.</a></p>
<p>Across <a href="https://www.w3.org/2024/07/audio-wg-2024.html#history">11 charters and re-charters,</a> I can find no public objection within the group's mailing list from anyone with an <code>@apple.com</code> email address.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-veil-of-secrecy-5" id="fnref-veil-of-secrecy-5">5</a></sup> Indeed, <a href="https://www.w3.org/Search/Mail/Public/search?keywords=webmidi&amp;from=%40apple.com&amp;lists=public-audio">I can find no mentions of MIDI from anyone at Apple on the public list.</a> Obviously, that is not the same thing as agreeing to publication as a Recommendation, but it also not indicative of any attempts at providing an alternative.</p>
<p>But perhaps alternatives emerged elsewhere, e.g., in an Incubation venue?</p>
<p>There's no counter-proposal listed in the <a href="https://github.com/WebKit/explainers/">WebKit explainers repository</a>, but maybe it was developed in a different venue?</p>
<p>We can look for <a href="https://developer.apple.com/safari/technology-preview/">features available behind flags in Safari Technology Preview</a> and read the Tech Preview release notes. To check them, I used <code>curl</code> to fetch each of the 127 JSON files that are (apparently) the format for Safari's release notes, pretty-printed them with <code>jq</code>, then grepped case-insensitively for mention of “audio” and “midi”. Every mention of “audio” was in relation to the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API">Web Audio API,</a> the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API">Web Speech API,</a> <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API">WebRTC,</a> <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/audio">the <code>&lt;audio&gt;</code> element,</a> or general media playback issues. There were zero (0) mentions of MIDI.</p>
<p>I also cannot locate any public feedback on Web MIDI from anyone I know to have an <code>@apple.com</code> email address in <a href="https://github.com/WebAudio/web-midi-api/issue">the issue tracker for the Web Audio Working Gropup</a> or <a href="https://github.com/search?q=org%3AWICG+midi&amp;type=issues">in <abbr title="Web Incubation Community Group at the W3C">WICG</abbr></a> except for a single issue <a href="https://github.com/WICG/admin/issues/102">requesting that <abbr title="Web Incubation Community Group at the W3C">WICG</abbr> designs look “less official.”</a></p>
<p>The now-closed <a href="https://www.w3.org/groups/cg/webmidi/">Web MIDI Community Group,</a> likewise, had zero (0) involvement by Apple employees on its <a href="https://lists.w3.org/Archives/Public/public-webmidi/">mailing list</a> or on <a href="https://www.w3.org/Search/Mail/Public/search?lists=public-audio-comgp&amp;keywords=midi">the successor Audio Community Group mailing list.</a> There were also no (0) proposals covering similar ground that I was able to discern on the <a href="https://github.com/WebAudio/web-audio-cg/issues?q=is%3Aissue">Audio CG</a> issue list.</p>
<p>Instead, Apple have <a href="https://webkit.org/tracking-prevention/#:~:text=Web%20Bluetooth-,Web%20MIDI%20API,-Magnetometer%20API">issued a missive decrying Web MIDI as a privacy risk.</a> As far as anyone can tell, this was done without substantive analysis or engagement with the evidence from nearly a decade of deploying it in Chromium-based browsers.</p>
<p>If Apple ever offered an alternative, or to collaborate on a redesign, or even an evidence-based case for opposing it,<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-counterfactuals-6" id="fnref-counterfactuals-6">6</a></sup> I cannot find them in the public record.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-mozillas-webmidi-odyssey-7" id="fnref-mozillas-webmidi-odyssey-7">7</a></sup></p>
<h4 id="web-usb" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#web-usb">Web USB</a></h4>
<br style="display: none;" />
<picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2020/12/jeff-yasskin-for-w3c-tag/usb-device-chooser.png" alt="Missing alt text" style="aspect-ratio: 964 / 642" class="preview" decoding="async" loading="lazy" />      </picture>          
<p>USB is a security sensitive API, and <a href="https://developer.chrome.com/docs/capabilities/usb">Web USB</a> was designed with those concerns in mind. All browsers that ship Web USB today present “choosers” that force users to affirmatively select each device they provide access to, from which sites, and always show ambient usage indicators that let users revoke access. Further, sensitive device classes that are better covered by more specific APIs (e.g., the <a href="https://developer.chrome.com/docs/capabilities/web-apis/file-system-access">Filesystem Access API</a> instead of <a href="https://en.wikipedia.org/wiki/USB_mass_storage_device_class">USB Mass Storage</a>) are <a href="https://wicg.github.io/webusb/#usbinterface-interface:~:text=Protected%20interface%20classes">restricted.</a></p>
<p>This is far from the Hacker News caricature of <em>&quot;letting any web page talk to your USB devices,&quot;</em> allowing only point connections between individual devices and sites, with explicit controls always visible.</p>
<p></p><figure class="full_wide"><a href="https://caniuse.com/webusb" alt="Web USB has been available to an overwhelming majority of the web's users for the better part of a decade. The sky has not fallen." target="_blank"><picture style="--lqip: -169436" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/webusb-usage.avif" alt="Web USB has been available to an overwhelming majority of the web's users for the better part of a decade. The sky has not fallen." style="aspect-ratio: 2298 / 1329" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Web USB has been available to an overwhelming majority of the web's users for the better part of a decade. The sky has not fallen.</figcaption>      </figure><p></p>
<p>After two years of <a href="https://github.com/WICG/webusb/commit/a21c17674e99c2dba23e168a26e4730bc4032f64">public development</a> and a series of public Origin Trials lasting seven months (<a href="https://developer.chrome.com/origintrials/#/view_trial/-8538824893494460415">1,</a> <a href="https://developer.chrome.com/origintrials/#/view_trial/2990390152574009345">2</a>), the first version of the API shipped in Chrome 61, released September 2017.</p>
<p>I am unable to locate any substantive engagement from Apple about alternatives for <a href="https://wicg.github.io/webusb/#motivating-applications">the motivating use-cases outlined in the spec</a>.</p>
<p>With many years of shipping experience, we can show that these needs have been successfully addressed by WebUSB; e.g. <a href="https://makecode.microbit.org/device/usb/webusb">teaching programming in classrooms.</a> More than a decade after it was first approached about them, it's unclear what Apple's alternative is. Hollowing out school budgets to buy Cupertino's high-end devices to run unsafe, privacy-invading native apps?</p>
<p>Apple <em>have</em> included Web USB on the list of APIs they <a href="https://webkit.org/tracking-prevention/#anti-fingerprinting">“decline to implement”</a> and quite belatedly <a href="https://github.com/WebKit/standards-positions/issues/68">issued a “standards position” opposing the design.</a> But no counter-proposal was developed or linked from those threads, despite <a href="https://github.com/WebKit/standards-positions/issues/68#issuecomment-1273714834">being asked directly if there might be more palatable alternatives.</a></p>
<p>I can locate no appetite from Apple's standards engineers to address these use-cases, know of no enquiries into <a href="https://docs.google.com/presentation/d/1Nf64QLI-lkyqJ7UoDUPefrLJU7zcTUJKvTYV8L7ZAaY/edit?usp=sharing&amp;resourcekey=0-Bf69ilULrcA4qBZb7ZHdkA">data about our experiences shipping them,</a> and can find no constructive counterproposals. Which raises the obvious question: if Apple <em>does</em> engage to develop counterproposals in tricky areas, how long are counterparties meant to wait? More than eight years?</p>
<h4 id="web-bluetooth" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#web-bluetooth">Web Bluetooth</a></h4>
<p>Like Web USB, Web Bluetooth was designed from the ground-up with safety in mind and, as a result, has been incredibly safe and deployed at massive scale for eight years. It relies on the same chooser model in Chromium-based browsers.</p>
<p></p><figure class="up one">          <picture style="--lqip: 354916" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/pwa-web-bt-1.avif" alt="" style="aspect-ratio: 1601 / 1280" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Prior to getting user consent, <a href="https://scalding.app/">this <abbr title="Progressive Web App">PWA</abbr></a> can't talk to any devices.          </figcaption>        </figure><p></p>
<p></p><figure class="up one">          <picture style="--lqip: 305763" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/pwa-web-bt-2.avif" alt="" style="aspect-ratio: 1601 / 1280" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Pairing is only possible when users explicitly choose a device.          </figcaption>        </figure><p></p>
<p></p><figure class="up one">          <picture style="--lqip: 482916" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/pwa-web-bt-3.avif" alt="" style="aspect-ratio: 1601 / 1280" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Once connected, data can only be sent over the safer <a href="https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gatt">GATT subset</a> of the larger Bluetooth protocol.          </figcaption>        </figure><p></p>
<p>As with all <a href="https://developer.chrome.com/docs/capabilities">Project Fugu device APIs,</a> Web Bluetooth was designed to reduce ambient risks — no access to Bluetooth Classic, available only on secure sites, and only in <code>&lt;iframe</code>&gt;s with explicit delegation, etc. — and to give implementers <a href="https://infrequently.org/2020/07/why-ui-isnt-specified/">flexibility about the UIs they present</a> to maximise trust and minimise risk. This included intentionally designing flexibility for restricting access based on context; e.g., only from installed <abbr title="Progressive Web Apps">PWAs</abbr>, if a vendor chooses that.</p>
<p>The parallels with Web USB continue on the standards track. I can locate no engagement from any <code>@apple.com</code> or <code>@webkit.org</code> email addresses <a href="https://www.w3.org/Search/Mail/Public/search?from=%40apple.com&amp;lists=public-web-bluetooth">on the <code>public-web-bluetooth</code> mailing list.</a> In contrast, when design work began in 2014 and every browser vendor was invited to participate, <a href="https://lists.w3.org/Archives/Public/public-web-bluetooth/2014Aug/thread.html#msg6">Mozilla engaged.</a> I can find no evidence of similar openness on the part of Apple, nor practical counter-proposals.</p>
<p>Over more than three years of design and gestation in public, including <a href="https://developer.chrome.com/docs/capabilities/bluetooth#available_for_origin_trials">very public Origin Trials,</a> Apple <a href="https://github.com/search?q=repo%3AWebKit%2Fstandards-positions+bluetooth&amp;type=issues">did not provide constructive feedback, develop counter-proposals, or offer to engage in any other way I can find.</a></p>
<p>This appears to be a pattern.</p>
<p>From a deep read of the “standards position” <a href="https://github.com/WebKit/standards-positions/issues?q=label%3A%22position%3A%20oppose%22">threads for designs Apple opposes,</a> I cannot find evidence that Cupertino has <em>ever</em> offered a counter-proposal to <em>any</em> API it disfavours.</p>
<p>These threads do demonstrate a history of <a href="https://github.com/WebKit/standards-positions/issues/19#issuecomment-1172823486">downplaying clearly phrased developer needs</a>, rather than proactive engagement, and it seems the pattern is that parties must beg Apple to belatedly form an opinion. When there is push-back, often after years of radio silence, requesters (not Apple) <em>also</em> <a href="https://github.com/WICG/screen-brightness/issues/1">have to invent potential alternatives, which Apple may leave hanging without engagement for years.</a></p>
<p>Worse, there are <a href="https://github.com/WebKit/standards-positions/issues/347#:~:text=and%20efficient%20solution.-,Venue,review%20processes%2C%20the%20working%20group%20lacks%20broad%20engagement%20from%20other%20implementers.,-Notably%2C%20the%20Gyroscope">performative expressions of disinterest</a> which Apple's standards engineers <em>know</em> are in bad-faith. An implementer withholding engagement from a group, then claiming a lack of implementer engagement in that same venue as a reason not to support a design, is the sort of self-serving, disingenuous circularity worthy of disdain.</p>
<h2 id="overall-impressions" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#overall-impressions">Overall Impressions</a></h2>
<p>Perhaps both the general trends and these specific high-profile examples are aberrant. Perhaps Apple's <em>modus operandi</em> isn't to:</p>
<ul>
<li>Ignore new incubations, even when explicitly asked to participate.</li>
<li>Fail to register concerns early and collaboratively, where open design processes could address them.</li>
<li>Force web developers and other implementers to request “positions” <em>at the end</em> of the design process because Apple's disengagement makes it challenging to understand Cupertino's level of support (or antipathy).</li>
</ul>
<p>Mayhaps it's <em>not</em> simply the predicable result of <a href="https://www.bloomberg.com/news/articles/2024-05-01/google-s-payments-to-apple-reached-20-billion-in-2022-cue-says">paltry re-investments in the web by a firm that takes eye watering sums from it.</a></p>
<p></p><figure class="full_wide"><a href="https://chrome-commit-tracker.arthursonzogni.com/organizations/commits?repositories=blink,jsc,v8,webkit&organizations=Apple,Google,Igalia,Individuals,Intel,Microsoft,Opera,Samsung,WebKit&grouping=quarterly&colors=organizations&kind=author&metric=contributor&chart=bar&dates=2018-12-03,2025-06-17" alt="Committers to Blink, V8, WebKit, and JSC by affiliation. Green is Apple, blue is Google, tan is Igalia, and brown is Microsoft." target="_blank"><picture style="--lqip: 173795" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/committers-per-quarter-by-org.avif" alt="Committers to Blink, V8, WebKit, and JSC by affiliation. Green is Apple, blue is Google, tan is Igalia, and brown is Microsoft." style="aspect-ratio: 1740 / 1050" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Committers to Blink, V8, WebKit, and JSC by affiliation. Green is Apple, blue is Google, tan is Igalia, and brown is Microsoft.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://chrome-commit-tracker.arthursonzogni.com/organizations/commits?repositories=blink,dawn,jsc,partition_alloc,skia,v8,webkit,webrtc,wpt&organizations=Apple,Google,Igalia,Individuals,Intel,Microsoft,Opera,Samsung,WebKit&grouping=quarterly&colors=organizations&kind=author&metric=contributor&chart=bar&dates=2018-12-03,2025-06-17" alt="The true scale of the funding gap becomes clearer as more projects are included. Here we add WebRTC and Web Platform Tests, both of which are shared between browsers and take contributions from many engines." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/committers-per-quarter-by-org-with-webrtc-and-wpt.avif" alt="The true scale of the funding gap becomes clearer as more projects are included. Here we add WebRTC and Web Platform Tests, both of which are shared between browsers and take contributions from many engines." style="aspect-ratio: 1753 / 1051" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>The true scale of the funding gap becomes clearer as more projects are included. Here we add WebRTC and Web Platform Tests, both of which are shared between browsers and take contributions from many engines.</figcaption>      </figure><p></p>
<p>If so, I would welcome evidence to that effect. But the burden of proof no longer rests with me.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fn-personal-foibles-8" id="fnref-personal-foibles-8">8</a></sup></p>
<h2 id="what's-happening-here%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#what's-happening-here%3F">What's Happening Here?</a></h2>
<p>It's hard to say why some folks are under the impression that Apple are generous co-designers, or believe Apple's evocative statements about hard-case features are grounded in analysis or evidence. We can only guess at motive.</p>
<p>The most generous case I can construct is that Apple's own privacy and security failures in native apps have scared it away, and that spreading FUD is cover for those sins. The more likely reality is that upper management fears <abbr title="Progressive Web Apps">PWAs</abbr> and wants to keep them from <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">threatening the App Store</a> with safe alternatives that don't require paying Apple's vig.</p>
<p>Whatever the cause, the data does not support the idea that Apple visibly engages in constructive critique or counter-proposal in these areas.</p>
<p>Moreover, it shows that many of Apple's objections and delays were unprincipled. It should be every browser's right to <a href="https://www.mnot.net/blog/2024/03/13/voluntary">control the features it enables,</a> and Cupertino is entirely within those rights to avoid shipping features in Safari. But the huge number of recent “catch-up” features tells a story that aligns more with covering for embarrassing oversights, rather than holding a line on quality, privacy, or security.</p>
<p>On the upside, this suggests that if and when web developers press hard for capabilities that have been safe on other platforms, Cupertino will relent or be regulated into doing so. It scarcely has a choice while simultaneously skimming billions from the web and making <a href="https://assets.publishing.service.gov.uk/media/68c04961838e7712ea2bfdb9/Apple.pdf">arguments like these to regulators (PDF, p35):</a></p>
<p></p><figure class="full_wide"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/09/cupertinos-comforting-myths/cma-submission-argument.avif" alt="Apple is arguing to regulators that the App Store faces plenty of competition, including from web apps. The very same web apps it continually hamstrings, deprives of features, and does not demonstrably engage to improve." style="aspect-ratio: 1521 / 551" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Apple is arguing to regulators that the App Store faces plenty of competition, including from web apps. The very same web apps it continually hamstrings, deprives of features, and does not demonstrably engage to improve.</figcaption>      </figure><p></p>
<p>The moment iPhone users around the world can install high-quality browsers, the conversational temperature about missing features and <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">reliability</a> will drop considerably. Until then, it remains important that Apple bear responsibility for the problems Apple is causing not only for Apple, but for us all.</p>
<aside class="thanks">
<p><em>Thanks to <a href="https://jeffrey.yasskin.info/">Jeffery Yasskin</a>, <a href="https://cwilso.com/">Chris Wilson</a>, and <a href="https://www.linkedin.com/in/vincentscheib/">Vincent Scheib</a> for their feedback on drafts of this post.</em></p>
</aside>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-unique-perch-1" class="footnote-item"><p>My various roles since the Blink fork have included:</p>
<ul>
<li>TC39 representative</li>
<li>Co-designer of Service Workers ('12-'15)</li>
<li>Co-Tech Lead for <a href="https://www.cnet.com/tech/services-and-software/with-fizz-google-hopes-to-bring-new-power-to-mobile-web/">Project Fizz</a> ('14-'16)</li>
<li>Three-time elected member of the <abbr title="World Wide Web Consortium">W3C</abbr>'s <a href="https://www.w3.org/2001/tag/">Technical Architecture Group</a> ('13-'19)</li>
<li>Web Standards Tech Lead for Chrome ('15-'21)</li>
<li>Co-Tech Lead for <a href="https://developer.chrome.com/docs/capabilities">Project Fugu</a> ('17-'21)</li>
<li>Co-designer of <a href="https://chromeos.dev/en/web/isolated-web-apps">Isolated Web Apps</a> ('19-'21)</li>
<li><a href="https://www.chromium.org/blink/guidelines/api-owners/">Blink API OWNER</a> ('18-present)</li>
<li>Ongoing advisor to Edge's web standards team</li>
</ul>
<p>In my role as TAG member, Fizz/Fugu TL, and API OWNER I've designed, reviewed, or provided input on dozens of web APIs. All of this work has been collaborative, but these positions have given me a nearly unique perch from to observe the ebb and flow of new designs from, particularly on the &quot;spicy&quot; end of the spectrum. <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-unique-perch-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-many-options-2" class="footnote-item"><p>Apple has many options for returning voluntarity to the market for iOS browsers.</p>
<p>Most obviously, Apple can simply allow secure browsers to use their own engines. There is no debate that this is possible, <a href="https://googleprojectzero.blogspot.com/2022/02/a-walk-through-project-zero-metrics.html#:~:text=time%20is%20spent.-,Browsers,-For%20most%20software">that competitors generally do a better job regarding security than Apple,</a> and that competitors would avail themselves of these freedoms if allowed.</p>
<p>But Apple has not allowed them.</p>
<p><a href="https://open-web-advocacy.org/apple-dma-review/">Open Web Advocacy has exhaustively documented</a> the land mines that Apple has <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">strewn in front of competitors</a> that have the temerity to attempt to bring their own engines to EU users. Apple's choice to geofence engine choice to the EU, indefensible implementation roadblocks, poison-pill distribution terms, and <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/#:~:text=We%20had%20the%20opportunity%20to%20question%20Apple%20directly%20on%20this%20at%20the%202025%20DMA%20workshop.%20Here%27s%20how%20they%20responded%3A">the continued prevarications and falsehoods</a> offered in their defence, are choices that Apple is affirmatively and continually making.</p>
<p>Less effectively, Apple could provide runtime flags for other browsers to enable features in the engine which Apple itself does not use in Safari. Paired with a commitment to implement features in this way on a short timeline after they are launched in other engines on other OSes, competing vendors could risk their own brands without Apple relenting on its single-implementer demands. This option has been available to Apple since the introduction of competing browsers in the App Store. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">As I have argued elsewhere,</a> near-simultaneous introduction of features is the minimum developers should expect of a firm that skims something like $19BN/yr in profits from the web (a ~95% profit rate, versus current outlays on Safari and WebKit).</p>
<p>Lastly, Apple could simply forbid browsers and web content on iOS. This policy would neatly resolve the entire problem. Removing Safari, along with every other iOS browser, is intellectually and competitively defensible as it removes the “special boy” nature of Safari and WebKit. This would also rid Apple of the ethical stain of continuing to string developers and competitors along within standards venues when it is demonstrably <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">an enemy of those processes.</a> <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-many-options-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-peer-pressure-3" class="footnote-item"><p>Apple regularly goes it alone when it is convinced about a design. We have seen this in areas as diverse as touch events, notch <abbr title="Cascading Style Sheets">CSS</abbr>, web payments, <a href="https://alastair.is/apple-has-a-private-css-property-to-add-liquid-glass-effects-to-web-content/">&quot;liquid glass&quot; effects,</a> and much else. It is not credible to assume that Apple will only ship APIs that have an official seal of an <abbr title="Standards Development Organisation">SDO</abbr> given Cupertino's rich track record of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/webkitmouseforcechanged_event">launch-and-pray</a> web APIs over the years. <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-peer-pressure-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-arguable-4" class="footnote-item"><p>In fairness to Apple regarding a &quot;standards position&quot; for Web MIDI, the feature predates Apple's process. But this brings up the origin of the system.</p>
<p>Why does this repository exist? Shouldn't it be rather obvious what other implementers think of that feature, assuming they are engaged in co-design?</p>
<p>Yes, but that assumes engagement.</p>
<p>Just after the Blink fork, a series of incidents took place in which Chromium engineers extrapolated from vaguely positive-sounding feedback in standards meetings when asked about other vendor's positions as part of the Blink Launch Process. This feedback was not a commitment from Apple (or anyone else) to implement, and various WebKit leaders objected to the charachterisations. As a way to avoid over-reading tea leaves in the absence of more fullsome co-design, the &quot;standards position&quot; process was erected in WebKit (and Gecko) so that Chromium developers could solicit &quot;official&quot; positions in the many instances where they were leading on design, in lieu of clearer (tho long invited) engagement.</p>
<p>If this does not sound like it augurs well for assertions that Apple engages to help shape designs in a timely way...well, you might very well think that. I couldn't possibly comment. <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-arguable-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-veil-of-secrecy-5" class="footnote-item"><p>There may have been Formal Objections (as defined by the <abbr title="World Wide Web Consortium">W3C</abbr> process) in private communications, but Member Confidentiality at the <abbr title="World Wide Web Consortium">W3C</abbr> precludes me from saying either way. If Apple did object in this way, it will have to provide evidence of that objection for the public record, as I cannot. <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-veil-of-secrecy-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-counterfactuals-6" class="footnote-item"><p>Apple's various objections to powerful features have never tried to square the obvious circle: why are camera and microphone access (via <code>getUserMedia()</code>) OK, but MIDI <em>et. al</em> are not? What evidence supports the notion that adding chooser-based UIs will lead to pervasive privacy issues that cannot be addressed through mechanisms like those Apple is happy to adopt for Geolocation? Why, despite their horrendous track records, are native apps the better alternative? <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-counterfactuals-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-mozillas-webmidi-odyssey-7" class="footnote-item"><p>Mozilla objected to Web MIDI on various grounds over the years, and after getting utterly roasted by its own users over failing to support the API, shipped support in <a href="https://caniuse.com/midi">Firefox 108 (Dec '22).</a></p>
<p>The larger question of Mozilla's relationship to device APIs was a winding road. It eventually culminated (for me) in <a href="https://github.com/w3ctag/meetings/blob/gh-pages/raw-minutes/2016-07-28-minutes.md">a long discussion</a> at a TAG meeting in Stockholm with <a href="https://educatedguesswork.org/">EKR</a> of <abbr title="Transport Layer Security">TLS</abbr> and Mozilla fame.</p>
<p>By 2016, Mozilla was licking its wounds from the failure of Firefox OS and retrenching around a less expansive vision of the future of the web. Long gone were <a href="https://web.archive.org/web/20160304065700/https://wiki.mozilla.org/WebAPI">the aspirations for &quot;WebAPIs&quot;.</a> Just a few short years earlier, Mozilla would have engaged (if not agreed) about work in this space, but an overwhelming tenor of conservativism and desktop-centricity radiated from Mozilla by the time of this overlapping <abbr title="Internet Engineering Task Force">IETF</abbr>/<abbr title="World Wide Web Consortium">W3C</abbr> meeting.</p>
<p>It didn't make the notes, but my personal recollection of how we left things late in the afternoon in Stockholm was EKR claiming that bandwidth for security reviews was the biggest blocker that and that it was fine if we (Chromium) went ahead with these sorts of designs to prove they wouldn't blow up the world. Only then would Mozilla perhaps consider versions of them.</p>
<p>True to his word, Mozilla eventually shipped Web MIDI on EKR's watch. If past is prologue, we'll only need to wait another three to five years before Web Bluetooth <em>et al.</em> join them. <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-mozillas-webmidi-odyssey-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-personal-foibles-8" class="footnote-item"><p>My memory is famously faulty, and I have been <a href="https://infrequently.org/series/browser-choice-must-matter/">engaged in a long-running battle</a> with Apple's legal folks relating to the suppression of browser choice on iOS. All of that colours my vision, and so here I have tried to disabuse myself of less generous notions by consulting public evidence to support Apple's case.</p>
<p>From what I was able to gather over many hours was overwhelmingly inculpatory. It is not possible from reading these threads and data points — rather relying on my own recollections — to sustain a belief that Apple have either provided timely constructive feedback on tricky APIs, or worked to solve the problems they address. But I am, in the end, heavily biased.</p>
<p>If my conclusions or evidence are wrong, I would very much appreciate corrections; <a href="https://infrequently.org/about-me/">my inbox and DMs are open.</a></p>
<p>If reliable evidence is provided, I will update this blog post to include it, and I encourage others to post on this topic in opposition to my conclusions. It should not be hard for Apple to make the case, assuming there is evidence to support it, that I've missed important facts. It would have both regulatory and persuasive valence regarding <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">questions I have raised relating to Apple's footprint in the internet standards community.</a> <a href="https://infrequently.org/2025/09/cupertinos-comforting-myths/#fnref-personal-foibles-8" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Web Standards and the Fall of the House of Iamus</title>
    <link href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/"/>
    <updated>2025-09-21T00:00:00Z</updated>
    <id>https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/</id>
    <content type="html"><![CDATA[
      <p></p><figure class="lede_figure"><picture style="--lqip: -152926" class="preview">      <img src="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/greek-ruins-unsplash.avif" alt="Photo by Photo by Artan Sadiku" style="aspect-ratio: 1200 / 798" class="lede_figure preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>      <span class="credit">        <a href="https://unsplash.com/photos/ancient-greek-temple-ruins-stand-against-a-clear-sky-cOnGUq0MWIc" taget="_blank">Photo by Photo by Artan Sadiku</a>      </span>    </figcaption>      </figure><p></p>
<p>Commentary about browsers and the features they support is sometimes pejorative towards pre-standardisation features. Given Apple's <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/">constriction of Mozilla's revenue stream</a> and its own <a href="https://chrome-commit-tracker.arthursonzogni.com/organizations/commits?repositories=blink,jsc,v8,webkit&amp;organizations=Apple,Google,Igalia,Individuals,Intel,Microsoft,Opera,Samsung,WebKit&amp;grouping=quarterly&amp;colors=organizations&amp;kind=author&amp;metric=contributor&amp;chart=bar&amp;dates=2018-12-03,2025-06-17">strategic under-funding of WebKit,</a> this usually takes the form <em>&quot;Chromium just ships whatever it wants.&quot;</em></p>
<p>This is true, of course, but not in the way commenters intend; and not only because <a href="https://www.chromium.org/blink/launching-features/">Blink's rigorous launch process</a> frequently prevents unvalidated designs from shipping.</p>
<p>Except for iOS, <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/">where Apple attempts to hide its role in undermining the competitive foundation of web standards,</a> <strong>every vendor <em>always</em> ships <em>&quot;whatever it wants.&quot;</em></strong> That is <em>the point</em> of <a href="https://www.mnot.net/blog/2024/03/13/voluntary">voluntary standards,</a> and competition is the wind in those sails.</p>
<p>Working Groups don't gate what browsers ship, nor do they define what's useful or worthy. There are no <a href="https://chs.harvard.edu/chapter/part-v-manteis-priests-at-all9-the-iamidae-a-mantic-family-and-its-public-image-michael-flower/">seers;</a> no Delphic oracles that fleetingly glimpse a true <em>logos</em>. Working Groups do not invent the future, nor do they hand down revealed truths like prophets of the House of Iamus.</p>
<p>In practice, they are thoughtful historians of recent design expeditions, critiquing, tweaking, then spreading the good news of proposals that already work through <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#web-standard">Web Standards</a> ratified <em>years</em> after features first ship, serving to licence designs liberally to increase their spread.</p>
<p>In the end, this is the role of standards and the Working Groups that develop them: to license patents that read on existing designs, reducing risks to implementers who adopt them.</p>
<p>Anyone who tries to convince you otherwise, or invites you to try your hand at invention within a chartered Working Group, does not understand <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#chartered-wg-role">what those groups are designed to do.</a> Sadly, this includes some folks who spend a lot of time in them.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#terminology-traps">Terminology Traps</a><ul><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#standardisation-!%3D-interoperability">Standardisation != Interoperability</a></li><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#standardisation-!%3D-responsibility">Standardisation != Responsibility</a></li></ul></li><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#chartered-wg-role">What Working Groups Really Do</a><ul><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#chartered-working-groups-are-not-design-venues">Chartered Working Groups Are Not Design Venues</a></li><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#the-role-of-incubation">The Role of Incubation</a></li></ul></li><li><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#no-prophecies%2C-only-engineering">No Prophecies, Only Engineering</a></li></ul></nav>
<p>Complaints about certain engines leading reveals a bias to fighting the last-war; fear of a return to the late 90s, when <em>“irrational exuberance”</em> applied not just to internet stocks, but also browser engines.</p>
<p>Unfounded optimism about our ability to deal with externalities of shipping prior to consensus created a great deal of pain. Misreadings of <a href="https://infrequently.org/2024/03/why-browsers-get-built/">how browsers evolve in practice</a> over-taught lessons that still invoke fear. But we have enough miles on the tires to see that standards aren't what create responsible feature development; thoughtful launch processes are.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-still-rare-1" id="fnref-still-rare-1">1</a></sup></p>
<p>As we will see, consensus is never a precondition for shipping, nor could it be. If it were, nothing would move forward, for it is the threat (and sometimes reality) of popular features shipping without <em>a priori</em> agreement that brings parties to the table. It's also the only reliable defence against <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/"><em>the fifth column problem</em>.</a></p>
<h2 id="terminology-traps" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#terminology-traps">Terminology Traps</a></h2>
<p>Before we get into the role of the charters that define Standards Development Organisation (<abbr title="Standards Development Organisation">SDO</abbr>) Working Groups, we must define some terms:<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-not-alone-2" id="fnref-not-alone-2">2</a></sup></p>
<dl>
<dt id="proposal">Proposal</dt>
<dd>Any design, in any sort of document (<a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#spec">Specification,</a> <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#explainer">Explainer,</a> or scrawl on the back of a napkin) offered inside an <abbr title="Standards Development Organisation">SDO</abbr> for standardisation. Proposals are revised through collaborative processes which function best inside <abbr title="Standards Development Organisations">SDOs</abbr> thanks to carve-outs in competition laws allowing competitors to collaborate in writing standards.</dd>
<dd>Proposals are implemented, and even shipped, well ahead of formal status as <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#web-standard">Web Standards</a> in order to gain developer feedback, iterate on designs, and build confidence that they meet needs effectively.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-running-code-3" id="fnref-running-code-3">3</a></sup></dd>
<dt id="spec">Specification</dt>
<dd>A document that describes the properties of an implementation, often in technical shorthand (e.g., <a href="https://webidl.spec.whatwg.org/">Web IDL</a>) and with reference to other specifications.</dd>
<dd>Specifications are <em>by and for</em> implementers, rather than working web developers, and are the documents to which the <abbr title="Intellectual Property Rights">IPR</abbr> commitments of Web Standards attach.</dd>
<dt id="explainer"><a href="https://www.w3.org/TR/explainer-explainer/#introduction">Explainer</a></dt>
<dd>An overview of a proposal. Explainers are <em>not</em> specifications, but encapsulate the key points of designs in terms of the problems they solve.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-explainer-provenance-4" id="fnref-explainer-provenance-4">4</a></sup> The goal is to explain the <em>why</em> along with the <em>what</em>, in terms web developers can weigh.</dd>
<dd>In well-incubated designs, Explainers evolve in parallel to specifications. This forces API designers to think like web developers. Explainers serve as foci for considering alternatives and as well as <em>“missing manuals”</em> for early designs.</dd>
<dt id="web-standard">Web Standard</dt>
<dd>A specification that has been put forward by a chartered Working Group to the full membership, and granted official status after ratification. For example, by receiving the status as a <a href="https://www.w3.org/policies/process/#initiating-rec-review">Recommendation of the <abbr title="World Wide Web Consortium">W3C</abbr></a> by a vote of the Advisory Committee, or in the case of <abbr title="European Computer Manufacturers Association, the home of JavaScript">ECMA</abbr> TC39, <a href="https://www.iso.org/standard/73002.html">publication of an International Standard at ISO.</a></dd>
<dd>Web standards create clarity around <abbr title="Intellectual Property Rights">IPR</abbr> concerns which pre-standards specifications cannot. These commitments <a href="https://www.w3.org/policies/patent-policy/#sec-Obligations">license the patents of parties participating in a Working Group</a> under <a href="https://www.w3.org/policies/patent-policy/#sec-Requirements">Royalty Free terms.</a></dd>
<dd>In practice, this also commits major firms to the defence of potential implementers, reducing risks across the ecosystem.</dd>
<dt id="standards-track">Standards Track</dt>
<dd>A specification document is <em>&quot;on the standards track&quot;</em> if its developers have signalled interest in formal, chartered Working Groups taking up their design for publication as a Web Standard, subject to clarification along the way. It is not necessary for any specific Working Group to agree for this description to hold.</dd>
<dd>Designs in this state often carry <abbr title="Intellectual Property Rights">IPR</abbr> grants, but provide less patent clarity (&quot;contribution only&quot;) than official Web Standards.</dd>
<dt id="incubation">Incubation</dt>
<dd>Any process outside a chartered Working Group in which web developers, browser vendors, and other interested parties meet to understand problems and design solutions. Drafts of incubated designs are often volatile. Eventually, if a problem is judged important by participants, one or more designs congeal into brief, high-level <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#explainer">&quot;Explainers&quot;</a>.</dd>
<dd>Before features launch without flags in stable-channel browsers, developer and implementer feedback can lead to large changes in incubated designs. Designers and participants must actively solicit input and respond to substantive feedback constructively.</dd>
</dl>
<p>Proposals whose specifications receive formal status within <abbr title="Standards Development Organisations">SDOs</abbr> are described as “adopted”, “recommended”, or “ratified”. This process binds the intellectual property of chartered Working Group participants to the licensing regime of the <abbr title="Standards Development Organisation">SDO</abbr> by approval of the membership.</p>
<p>From this we can see that is nonsensical to discuss <em>“proposals”</em> and <em>&quot;standards&quot;</em> in the same breath. They are a binary pair. A specification has either one status or the other; it cannot be both.</p>
<p>No design that becomes a standard can start as anything <em>but</em> a proposal,<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-just-venue-things-5" id="fnref-just-venue-things-5">5</a></sup> and the liminal space of non-standard proposal is not somehow less-than or an aberration. Rather, it is an embryonic stage every design must pass through, and which every <a href="https://en.wikipedia.org/wiki/De_jure"><em>de jure</em></a> Web Standard has taken at some point.</p>
<p>Armed with better language, we can develop an understanding of how features <em>actually</em> come to the web. Through this, we'll see why our optimism for standards has to come from our own powers of collaborative problem-solving, rather than waiting for designs to be handed down from Olympus.</p>
<h3 id="standardisation-!%3D-interoperability" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#standardisation-!%3D-interoperability">Standardisation != Interoperability</a></h3>
<p><a href="https://jakearchibald.com/">Jake Archibald</a> pointed out that linguistic precision is uncommon, and developers use the phrase “standard” or “web standard” loosely; a shorthand for features they can use without worry. That ground covers both official Web Standards and <a href="https://en.wikipedia.org/wiki/De_facto_standard"><em>de facto</em> standards.</a> The example of <a href="https://caniuse.com/webp">WebP</a> was <a href="https://mastodon.social/@jaffathecake/115151188595709094">raised,</a> and was even more instructive than I recalled.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-til-6" id="fnref-til-6">6</a></sup></p>
<p>A brief refresher: WebP <a href="https://developers.googleblog.com/en/webp-a-new-image-format-for-the-web/">was introduced by Google in 2010,</a> <a href="https://blog.chromium.org/2011/05/webp-in-chrome-picasa-gmail-with-slew.html">shipping in Chromium in 2011</a>. At that point, and for many years thereafter, WebP was not a standard. <a href="https://github.com/webmproject/libwebp/commit/930e8abbdadd382b321cf69021d97852af5eb949#diff-5bd0c4e08052f210583e2c6659753d4c5d4ae137d5c7566f399156404bf8c486">A high-level specification broke cover in 2012,</a> but was not brought to an <abbr title="Standards Development Organisation">SDO</abbr>. Patent rights and other IP questions were addressed only by <a href="https://github.com/webmproject/libwebp/blob/main/PATENTS">Google's waiver</a> and the Open Source licensing of <code>libwebp</code>.</p>
<p>Nearly all Chromium-based browsers adopted WebP by 2012. Microsoft Edge <a href="https://en.wikipedia.org/wiki/Microsoft_Edge_Legacy#:~:text=WebP%20image%20format%20supporhttps://en.wikipedia.org/wiki/Microsoft_Edge_Legacy#:~:text=WebP%20image%20format%20supportt">added support in 2018,</a> Firefox <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/65#other">joined the party in 2019,</a> and <a href="https://developer.apple.com/documentation/safari-release-notes/safari-14-release-notes#Media">Safari added support in 2020.</a></p>
<p>It was not until <a href="https://datatracker.ietf.org/doc/draft-zern-webp/00/">April 2021</a>, a full decade after the format's introduction and after all major engines supported it, that WebP arrived at the <abbr title="Internet Engineering Task Force">IETF</abbr> for standardisation. It finally earned RFC status in <a href="https://datatracker.ietf.org/doc/rfc9649/">November 2024</a>, four years after Apple unlocked wide compatibility, having been the last hold-out.</p>
<p>WebP gained tremendous adoption despite not being a standard for nearly 15 years. This has led some to suggest it <em>was</em> a Web Standard, as it had many of the properties expected of successful standards. Namely:</p>
<ul>
<li><strong>Broad adoption.</strong> All major engines gained support <em>before standardisation began in earnest.</em></li>
<li><strong>Stability.</strong> Despite adding opacity and animation later, every WebP image produced across the life of the format still renders correctly.</li>
<li><strong>Interoperability.</strong> The same WebP images work across implementations.</li>
<li><strong><abbr title="Intellectual Property Rights">IPR</abbr> clarity.</strong> As the primary contributor to the format and reference implementation, Google's substantial legal and patent assets provided adopters with assurances related to the provenance of both the code and the codec fundamentals.</li>
</ul>
<p>Many assume that Web Standards are the only path to achieving these attributes, but WebP shows us that this is mistaken. Web Standards deliver these properties most effectively and reliably, but WebP shows us that <em>“being a standard”</em> is not a requirement for interoperable implementation at scale, even in browsers.</p>
<p>Interoperability and adoption are, by inspection, independent of official status. Many formal Web Standards have spotty adoption or fail to achieve interoperability. The web also has a long history of <em>de facto</em> behaviours gaining official status long after interoperability and stability manifest in the market. This sits comfortably with the reality that every single web feature is non-standard for some fraction of its lifetime. At the limit, that fraction can be rather large.</p>
<p>Conflation of <em>de facto</em> standards, official Web Standards, wide deployment, and interoperability are likely to persist. However, those of us who work on browsers can and should be more precise, preferring <em>“interoperability”</em>, <em>“widely deployed”</em>, and <em>“standards track”</em> to <em>“Web Standard”</em> when those are more appropriate.</p>
<h3 id="standardisation-!%3D-responsibility" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#standardisation-!%3D-responsibility">Standardisation != Responsibility</a></h3>
<p>If we admit, as we must, that all features begin as non-standard proposals which proceed through official processes to become Web Standards, quality is never as simple as <em>“standard good, non-standard bad.”</em> A design can pass unaltered through every lifecycle stage without change to its technical shape or merits, and questions of wide implementation and interoperability are clearly extrinsic to the status of a design within an <abbr title="Standards Development Organisation">SDO</abbr>.</p>
<p>We must locate definitions of relative goodness in more directly descriptive properties. I have given a few above, namely <strong>adoption</strong>, <strong>stability</strong>, <strong>interoperability</strong>, and <strong><abbr title="Intellectual Property Rights">IPR</abbr> clarity</strong>. For a full account, we need to cover design-time attributes, including <strong>testability</strong>, <strong>specification rigour</strong>, <strong>wide review,</strong> and <strong>responsiveness to developer feedback</strong> . Taken together, they define what it means to <em>solve important problems well</em> on the standards track.</p>
<p>Developers and implementers weigh up these properties when judging APIs. Some designs, like WebP,<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-webp-revisionism-7" id="fnref-webp-revisionism-7">7</a></sup> can score highly on everything but adoption. WebP was not technically worse in 2015 than in 2019, or 2020, or 2024; only less widely adopted. Working web developers were free to exploit its benefits the whole time. Many did, and because it had been responsibly developed, interoperability followed, even before a proposal had been submitted to an internet standards body.</p>
<p>Likewise, we cannot judge other APIs shipped in a single engine to be low-quality on the basis of <abbr title="Standards Development Organisation">SDO</abbr> status. Nor can we credit statements opposing them on that basis, particularly from parties that have not offered counterproposals. A single implementation may preclude features from becoming standards, but that says nothing about design fitness, or even prospects for eventual adoption.</p>
<p>This understanding draws our focus away from formal <abbr title="Standards Development Organisation">SDO</abbr> status and toward more important properties of features. It also helps us weigh up the processes that gestate them:</p>
<ul>
<li>Are they friendly and open to developers, or are they smoke-filled rooms where old-timers hold sway?</li>
<li>Do they encourage new work at the pace of emerging developer needs, or are they <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">artificially constricted by a proliferation of veto players?</a></li>
<li>Do those processes generate good tests and strong specifications, or do a few powerful editors regularly cut corners?</li>
<li>Are features submitted for wide review to competent and responsive experts, or is Working Group <a href="https://en.wikipedia.org/wiki/Go_fever">&quot;go fever&quot;</a> allowed to dominate?</li>
<li>Do processes put evidence of solving end-user and developer problems<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-first-things-first-8" id="fnref-first-things-first-8">8</a></sup> ahead of groupthink and reckons?</li>
<li>Do those processes allow high-quality features to ship ahead of full consensus, based on evidence?</li>
<li>Do they adequately protect implementers from <abbr title="Intellectual Property Rights">IPR</abbr> risks?</li>
</ul>
<p>These questions do not line up clearly with corporate jerseys. They do not favour one company's designs over another's. Google, Microsoft, Apple, and Mozilla all have fielded designs that easily pass these tests, and others that flunked. That's the thing about quality; metrics don't care about status or affiliation. Quality doesn't have a “team”, it has units of measure.</p>
<p>Quality tests help us evaluate features in the market-based ecosystem of voluntary standards. The presumed working mode of Web <abbr title="Standards Development Organisations">SDOs</abbr> is that many ideas will be tried (responsibly, hopefully) and the best ideas should gain traction. Eventually, better designs sway the market, leading to calls for standardisation.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-messy-in-practice-9" id="fnref-messy-in-practice-9">9</a></sup> Competitors who objected, even strenuously, can then adopt liberally-licensed designs, provide alternatives, or lose share. This logic does not designate grandees or smoke-filled rooms as arbiters of quality. Instead, we rely on voluntary adoption, the testable qualities of shipped designs, and developers voting with their feet.</p>
<p>Responsible, quality-oriented feature development processes reject priesthoods, seers, and oracles, putting evidence-based engineering in their place. This focuses us on <em>solving problems we can see,</em> showing our work, inviting critique, and engaging constructively.</p>
<p>There were never curtains from behind which a feature's essential “standardness” could be revealed, and we should not invent them because the messier, egalitarian reality of feature evolution seems disquieting. Like “Best Picture”, formal <abbr title="Standards Development Organisation">SDO</abbr> status isn't a reliable indicator of quality. Each must judge for themselves.</p>
<p>In the end, the wider internet engineering community <em>always</em> decides if problems are relevant and if designs are “correct.”</p>
<p>There are no blinding flashes of insight, only the push and pull of competing proposals to solve user and developer needs. When standards fail to meet needs, developers patch over the gaps at great cost, or route around standards-based platforms altogether. It is no coincidence that the phases of the <a href="https://www.chromium.org/blink/launching-features/">Blink Launch Process</a> and tools like <a href="https://developer.chrome.com/docs/web-platform/origin-trials">Origin Trials</a> present practical steps away from Working Group mysticism. Moving, however haltingly, towards egalitarian, pluralistic collaboration has delivered tremendous progress, despite recalcitrant participants.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-big-old-working-groups-hate-this-one-weird-trick-10" id="fnref-big-old-working-groups-hate-this-one-weird-trick-10">10</a></sup></p>
<h2 id="chartered-wg-role" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#chartered-wg-role">What Working Groups Really Do</a></h2>
<p>Along with other experienced colleagues at Google and Microsoft, I have had the privilege to teach the practice and theory of standards-track feature development to talented engineers working inside Chromium.</p>
<p>The role of chartered Working Groups looms large in those conversations, but it is far from central. This is because the primary job of a Working Group is to accelerate adoption of <em>existing</em> designs that have enough support to move forward and insulate them from <abbr title="Intellectual Property Rights">IPR</abbr>-based attacks. This is both their official job (per <abbr title="Standards Development Organisation">SDO</abbr> process documents) and their primary value.</p>
<p>“I” dotting and “t” crossing is expected, and it can slightly alter designs, but chartered Working Groups never work well as venues for effectively canvassing developers for problems to solve. Nor are they good environments for testing ideas. If the goal is to solve new problems or design new solutions, chartered Working Groups are never the best forum for the simple reason that <em>it is not what they are built to do</em>.</p>
<p>Consider the most recent charters from a few lively <abbr title="World Wide Web Consortium">W3C</abbr> Working Groups:</p>
<ul>
<li><a href="https://www.w3.org/groups/wg/webapps/">Web Apps</a> (<a href="https://www.w3.org/2025/03/css-wg.html">charter</a>)</li>
<li><a href="https://www.w3.org/groups/wg/payments/">Web Payments</a> (<a href="https://www.w3.org/Payments/WG/charter-2025.html">charter</a>)</li>
<li><a href="https://www.w3.org/groups/wg/css/"><abbr title="Cascading Style Sheets">CSS</abbr></a> (<a href="https://www.w3.org/2025/03/css-wg.html">charter</a>)</li>
<li><a href="https://www.w3.org/groups/wg/gpu/">Web GPU</a> (<a href="https://www.w3.org/2025/01/gpuweb-charter.html">charter</a>)</li>
</ul>
<p>Per <a href="https://www.w3.org/policies/process/#WGCharter">the formal process governing charters,</a> each group's convening document contains several sections that outline:</p>
<ul>
<li>A problem statement, laid out at the group's (re)charter.</li>
<li>An explicit scope; i.e., technologies the group can consider in addressing that problem.</li>
<li>An <em>a priori</em> list of documents and deliverables the WG will produce.</li>
</ul>
<p>Everything in these charters works to provide clarity and precision about what the group will deliver because that is how members (firms, in the <abbr title="World Wide Web Consortium">W3C</abbr>'s case) weigh up the costs and benefits of joining relative to their patent portfolios.</p>
<p>Yes, it's all about patents. Standards Development Organisations are, practically speaking, <abbr title="Intellectual Property Rights">IPR</abbr> clearing houses. From this perspective, all the hoops one must jump through to join a chartered group make sense:</p>
<ul>
<li>
<p><strong>Q:</strong> Why do companies have to officially join each Working Group separately?</p>
<p><strong>A:</strong> Patents.</p>
</li>
<li>
<p><strong>Q:</strong> Why does each participant need to be approved by a company's main <abbr title="World Wide Web Consortium">W3C</abbr> delegate?</p>
<p><strong>A:</strong> Patents.</p>
</li>
<li>
<p><strong>Q:</strong> Why are there so many checkpoints in the process that appear to do little more than waste time?</p>
<p><strong>A:</strong> Patents.</p>
</li>
<li>
<p><strong>Q:</strong> Why does the whole membership need to vote to progress a document to a formal standard?</p>
<p><strong>A:</strong> Patents.</p>
</li>
</ul>
<p>Features named in Working Group charters are the only designs a group can standardise, and groups run into trouble with lawyers when they exceed charter scopes, because participating firms may not have done a search in their portfolio (or their competitor's) regarding designs outside the pre-determined scope. When this happens, all progress can halt for an indeterminate amount of time. <abbr title="Standards Development Organisation">SDO</abbr> processes and documents, therefore, work to cabin the risk, moving early design out of Working Groups and into other venues.</p>
<h3 id="chartered-working-groups-are-not-design-venues" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#chartered-working-groups-are-not-design-venues">Chartered Working Groups Are Not Design Venues</a></h3>
<p>All of this drives to a simple set of obvious conclusions: venues other than chartered Working Groups are necessary in order to do the sort of high-iteration-pace design work that leads to higher-quality designs.</p>
<p>It's a punchline that standards committees are bad at design, but this is <em>by design</em>. They do not have the cycles, mission, or tools needed to explore developer problems, let alone iterate towards compelling solutions. Their job, <a href="https://www.w3.org/policies/process/#Reports">per the official process documents that convene them,</a> is to ensure that <a href="https://www.w3.org/policies/process/#general-requirements">certain quality attributes</a> are <a href="https://www.w3.org/policies/process/#transition-rec-requirements">tended to</a> (e.g., tests and complete specifications) on the way towards licensing of the intellectual property embodied in specifications.</p>
<h3 id="the-role-of-incubation" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#the-role-of-incubation">The Role of Incubation</a></h3>
<p>To this end, internet <abbr title="Standards Development Organisations">SDOs</abbr> have many alternatives that are better suited to design work, and which create glide paths for the fittest proposals into chartered Working Groups to gain eventual status as Web Standards. Here are a few:<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-wtf-whatwg-11" id="fnref-wtf-whatwg-11">11</a></sup></p>
<ul>
<li>
<p><a href="https://www.w3.org/"><abbr title="World Wide Web Consortium">W3C</abbr></a></p>
<ul>
<li><a href="https://www.w3.org/groups/ig/">Interest Groups</a></li>
<li><a href="https://www.w3.org/groups/bg/">Business Groups</a></li>
<li><a href="https://www.w3.org/groups/cg/">Community Groups</a>, particularly <a href="https://www.w3.org/community/wicg/">the <abbr title="Web Incubation Community Group at the W3C">WICG</abbr></a></li>
</ul>
</li>
<li>
<p><a href="https://www.ietf.org/"><abbr title="Internet Engineering Task Force">IETF</abbr></a></p>
<ul>
<li><a href="https://www.rfc-editor.org/rfc/rfc6771.html">&quot;Bar BOFs&quot;</a></li>
<li><a href="https://www.ietf.org/process/bofs/">Official BOFs</a></li>
</ul>
</li>
<li>
<p><a href="https://tc39.es/">TC39</a></p>
<ul>
<li><a href="https://tc39.es/process-document/">Stage 0/1 Drafts</a></li>
</ul>
</li>
</ul>
<p>It's always possible for designs to fail to solve important problems, or fail to solve them well, and better designs flow naturally from a higher pace of iteration and feedback. Incubation venues <em>tend</em> to work better for design because they lower some strictures Working Groups erect to create patent clarity. Instead of needing to pre-define their deliverables, these groups can fail fast and iterate. When they work, they can be submitted to Working Groups to get patent and IP issues finalised.</p>
<p>Incubation venues display very different working modes and membership than formal Working Groups. Instead of pre-decided, formal deliverables, groups can form around nebulous problem statements and define the issues long before landing on a single design. There is no stable set of delegates from member firms, largely dominated by implementers. Rather, interest groups may form organically, even <a href="https://www.w3.org/community/respimg/">from web developers interested in shared problems.</a> Instead of predefined timelines and pre-ordained deliverables, these groups work at the speed of their need and understanding. And instead of design pivots representing potential failure, incubation venues can test multiple alternatives. Discarding entire designs is even healthy while the furious iteration of incubation plays out.</p>
<p>Lower barriers to entry for web developers, along with structures that encourage dynamic problem-solving coalitions, tend to create higher pace and more focused work. This, in turn, allows consideration of more alternatives and helps facilitate the iterations that hone design. Not every Incubation venue succeeds, and not every design they consider wins. But their outsized success vs. design-in-committee approaches has been apparent for more than a decade.</p>
<p>Only those mistakenly wedded to, or cynically selling, mystical notions of Working Groups as diviners of revealed truth try to rubbish the web's incubation venue's outstanding track record of delivery. Given the overwhelming success of incubation, including the demonstrated benefits of fail-fast iteration, we <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">must then ask</a> why there are still proponents of Working Group misuse and process opacity.</p>
<h2 id="no-prophecies%2C-only-engineering" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#no-prophecies%2C-only-engineering">No Prophecies, Only Engineering</a></h2>
<p>Splitting the needs of design from the strictures of standardisation isn't against the spirit of standardisation, nor is shipping ahead of a vote by the full membership of an <abbr title="Standards Development Organisation">SDO</abbr> problematic. These approaches are <em>written into the process documents of the internet's most effective bodies.</em> Implementation experience is required for a proposal to become a ratified standard, and Working Groups are enjoined by process from undertaking the explorations incubation venues specialise in. Which is why those same <abbr title="Standards Development Organisations">SDOs</abbr> build and encourage incubation groups.</p>
<p>This is an uncomfortable acknowledgement for some.</p>
<p>Folks I have talked to seem to imagine rooms filled with people who know everything and always make correct decisions. There are no such rooms. We're all just engineers trying to solve problems, from the heights of the TAG and the Internet Architecture Board to the scrappiest <abbr title="World Wide Web Consortium">W3C</abbr> Community Group or <abbr title="Internet Engineering Task Force">IETF</abbr> Bar BOF. And sometimes we get it very wrong. But that should not immobilise us in fear; it should cause us to do what we always do when engineering: adopt processes and guardrails to improve quality and increase the rate of delivery.</p>
<p>Problems only get solved by people of good cheer working hard to spot them,<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fn-essential-12" id="fnref-essential-12">12</a></sup> trying out solutions, and working collaboratively to document the ones that work best. There are no oracles in standards work, only engineers. And that's more than enough.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->
<!-- ####################################################################### -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-still-rare-1" class="footnote-item"><p>While the Blink Launch Process raised the bar in some ways for every project, many parts of Blink's <a href="https://youtu.be/1Z83L6xa1tw?si=vuKZnxSXPkne8plz">risk-based logic</a> for feature leadership still lack analogues for tools like Origin Trials in other projects. Over the past decade, this has generally not been a major problem because other projects rarely lead (sadly). <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-still-rare-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-not-alone-2" class="footnote-item"><p>And, it would seem, long-time browser engineers and standards participants. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-not-alone-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-running-code-3" class="footnote-item"><p>The <abbr title="Internet Engineering Task Force">IETF</abbr> famously phrases this principal as <a href="https://www.ietf.org/runningcode/"><em>&quot;rough consensus and running code&quot;</em></a>, which indicates that that formal status as an official standard should be reserved for designs with experience in the market.</p>
<p>A frustrating fraction of the web's erstwhile friends twist the arrow of causality, demanding formal standards status before they (or anyone else) dare to ship a proposal. This is, of course, entirely backwards, but sounds convincing to web developers who desire interoperability which comes from uniform implementation status which, historically, correlates with <em>de jure</em> status.</p>
<p>This rhetorical bait-and-switch is deployed very frequently by <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">fifth columnists.</a> <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-running-code-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-explainer-provenance-4" class="footnote-item"><p>Most contemporary web standards explainers use <a href="https://github.com/w3ctag/explainer-explainer/blob/main/template.md">a template</a> derived from a document I authored for use by Google's Web Standards engineers, and which was adopted by the <abbr title="World Wide Web Consortium">W3C</abbr>'s <a href="https://www.w3.org/2001/tag/">Technical Architecture Group</a> during my service there.</p>
<p>The current template has drifted from the original somewhat, but the initial intent is in tact: to favour the perspective of working developers over implementers when weighing up potential designs.</p>
<p>This explicit goal is realised through many steps of <a href="https://www.chromium.org/blink/launching-features/">the Blink Launch Process.</a> It's that process which forces Blink engineers to request <a href="https://github.com/w3ctag/design-reviews">TAG design review</a> for new features. This combines with the reality that most new web features begin life within Chromium and Blink's <em>“coalition of the willing”</em>. As a result, designers of important new features experience Blink's process guardrails as the most constricting influence on quality as they work towards shipping. And one of those guardrails is to explain features in terms that web developers can understand via Explainers.</p>
<p>As a sociotechnical system, the Blink Launch Process, and its integrations with the TAG and various incubation bodies, are calculated to act in a Popperian mode, rejecting claims to design authority and oracular Working Group pronouncements. In their place, we explicitly delegate power to groups that have done a good job of representing wider constituencies. The goal is to place the key question <em>&quot;does this design solve an <em>important</em> problem <em>well</em>?&quot;</em> at the centre of feature development, and to trust users (web developers) as judge of the results.</p>
<p>We reject both essentialist and inductive intuitions about where features “should” come from, and instead require designers walk a mile in the shoes of their users. This is easiest to do in incubation venues like the <abbr title="Web Incubation Community Group at the W3C">WICG</abbr>, where the barriers to bringing web developers into the conversation are lowest.</p>
<p>This also is why the <a href="https://www.chromium.org/blink/guidelines/api-owners/">Blink API OWNERS</a> expect “Considered Alternatives” sections of explainers to be exhaustive, and that examples appear the languages developers use (<abbr title="HyperText Markup Language">HTML</abbr>, <abbr title="Cascading Style Sheets">CSS</abbr>, and <abbr title="JavaScript">JS</abbr>), not the languages implementers think in (WebIDL and C++). Domain experts may understand the system, by sympathy for the machine is not a substitute for web developers trying designs and rendering their own judgement. The Blink Launch Process guards against <a href="https://en.wikipedia.org/wiki/Go_fever">go fever</a> while enabling feature designers to launch responsibly, even when forced to go first by the disinterest of other vendors in solving problems. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-explainer-provenance-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-just-venue-things-5" class="footnote-item"><p>Even if a proposal is, for some blighted reason, floated first within a chartered Working Group, it is still only that: a proposal without any standing as a standard. It is only upon publication of a formal standard document months or years later that a proposal, encoded in a specification, can be called a Web Standard and carry any of the attendant IP protections.</p>
<p>That <em>necessarily</em> happens <em>after</em> the proposal has been offered, and generally happens months or years after all design work has completed and multiple interoperable implementations are fielded. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-just-venue-things-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-til-6" class="footnote-item"><p>Until prompted to consider it, I had not been aware that WebP had made the transition to a formal standard in any venue. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-til-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-webp-revisionism-7" class="footnote-item"><p>It would, obviously, have been better for WebP to be floated at <abbr title="Internet Engineering Task Force">IETF</abbr> many years prior, but adoption in every major engine occurred before that process began. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-webp-revisionism-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-first-things-first-8" class="footnote-item"><p>In that order, always. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-first-things-first-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-messy-in-practice-9" class="footnote-item"><p>In reality, new web features are a thinly traded market, and long experience (e.g., <abbr title="Cascading Style Sheets">CSS</abbr>'s “prefixpocalypse&quot;) has taught the web community that uncontrolled experiments are disruptive and costly. This lesson has, in my view, been heavily over-sold.</p>
<p>Responsible approaches (e.g., Origin Trials) now have a long track record of success. Those who argue that we must sort out differences in perspective exclusively by thinking hard about designs within the teleconferences of chartered Working Groups have not demonstrated that their approach is superior in any way that I can see. Simply trying ideas and gathering developer feedback has, despite tremendous resistance from Apple, generated a many important and high-quality features over the past decade using this model.</p>
<p>Had we waited for Working Groups to recover from stupors induced by <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">fifth columnist's</a> disinterest, the quality of the resulting designs would not have improved substantially. Nor, in my estimation, would they be more likely to eventually achieve status as ratified and widely adopted Web Standards.</p>
<p>There will always be a role for chartered Working Groups to improve on extant designs, but we have falsified the thesis that it is necessary for design to happen within them. The positive qualities of successful features are not down to venue, but the constituencies involved, and the evidence used to evolve them. That developer involvement and vendor flexibility towards feedback overlapped with Working Group-centered design efforts at certain moments in the past gives rise to much confusion. New entrants, thankfully, can skip old muddles and move straight to beginning their work in more entrepreneurial, high-iteration-rate venues built for incubation. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-messy-in-practice-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-big-old-working-groups-hate-this-one-weird-trick-10" class="footnote-item"><p>Many big, old chartered Working Groups attract participants who are earnestly confused about the value of their own contributions or the correct scope of the group's activities. Luckily, it is not necessary to convince <em>them</em> that they should not have outsized power in these domains. Instead, we only need to route around by moving early design work to incubation venues that enable more productive and egalitarian practices.</p>
<p>There is little that hard-done-by WG delegates can do when this happens, other than to muddy the waters about what the best order of operations is. They cannot prevent design work from decamping to more fertile ground because it is in full alignment with the roles assigned to Working Groups and their feeder venues by the formal processes that govern <abbr title="Standards Development Organisations">SDOs</abbr>.</p>
<p>Design work should <em>never</em> have been on their docket, and it is <em>always</em> illegitimate Working Groups to attempt to monopolise it. Their charters make this extremely clear. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-big-old-working-groups-hate-this-one-weird-trick-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-wtf-whatwg-11" class="footnote-item"><p>The WHATWG is unique among internet <abbr title="Standards Development Organisations">SDOs</abbr> in <a href="https://whatwg.org/workstream-policy#workstream-proposals">disavowing any sort of incubation or early design process</a>, which largely serves to make the <abbr title="World Wide Web Consortium">W3C</abbr>'s various appendages (particularly <a href="https://www.w3.org/community/wicg/">the <abbr title="Web Incubation Community Group at the W3C">WICG</abbr></a>) more useful and vibrant. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-wtf-whatwg-11" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-essential-12" class="footnote-item"><p>Taking developers seriously and not being dismissive about the needs they express is the first step in this work. It is therefore <em>extremely</em> problematic when implementers gaslight developers or claim the needs they are taking time to express are somehow illegitimate.</p>
<p>There are many cases where an <abbr title="Standards Development Organisation">SDO</abbr> or Working Group can't, or shouldn't, work to solve certain problems. But we can engage those questions without being dismissive, and should show our work along the way. Vendors who make a habit of brushing off developers, therefore, bring disrepute to the whole goal of standards work. <a href="https://infrequently.org/2025/09/standards-and-the-fall-of-iamus/#fnref-essential-12" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Apple&#39;s Assault on Standards</title>
    <link href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/"/>
    <updated>2025-09-02T00:00:00Z</updated>
    <id>https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/</id>
    <content type="html"><![CDATA[
      <aside class="tldr">
<p><strong><abbr title="&quot;Too long; didn't read&quot;; a summary of a post">TL;DR</abbr>:</strong>
Market competition underlies the enterprise of standards. It creates the only functional test of designs and lets standards-based ecosystems route around single-vendor damage. Without competition, standards bodies have no purpose, and neither they, nor the ecosystems they support, can retain relevance. Apple has poisoned the well through a monopoly on influence, which it has parleyed into suppression of browser choice. This is an existential threat to the web, but also renders web and internet standards moot. Internet standards bodies should recognise the threat and respond.</p>
</aside>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#the-power-of-interoperability">The Power of Interoperability</a></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#voluntary-adoption-is-foundational-to-internet-standards">Voluntary Adoption Is Foundational to Internet Standards</a></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-unique-monopoly">Apple's Unique Monopoly</a><ul><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#how-apple-uses-its-monopoly-to-centralise-and-enclose">How Apple Uses Its Monopoly to Centralise and Enclose</a></li></ul></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-transgressions-against-voluntary-adoption">Apple's Transgressions Against Voluntary Adoption</a><ul><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#unilateral-off-ramps">Unilateral Off-Ramps</a></li></ul></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#how-apples-crimes-differ-from-prior-episodes">How Apples Crimes Differ From Prior Episodes</a></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#necessary%2C-proportional-responses">Necessary, Proportional Responses</a><ul><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#why-now%3F">Why Now?</a></li></ul></li><li><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#do-standards-matter%3F">Do Standards Matter?</a></li></ul></nav>
<p>Internet enthusiasts of the previous century sometimes expressed the power of code <a href="https://www.eff.org/cyberspace-independence">by declaring the sovereignty of cyberspace,</a> or that <a href="https://lessig.org/product/code/"><em>&quot;code is law.&quot;</em></a></p>
<p>As odd as these claims sound today, they hit a deep truth: end-users, and even governments, lack power to re-litigate choices embodied in software. Software vendors, therefore, have power. Backed by <a href="https://en.wikipedia.org/wiki/Bootloader_unlocking">deeply embedded control chokepoints</a>, and without a proportional response from other interests, this control is akin to state power.</p>
<p>Both fear and fervour about these properties developed against a backdrop of libertarian<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-liberaltarian-1" id="fnref-liberaltarian-1">1</a></sup> attitudes toward regulation and competition. Attenuating vendor power through interoperability was, among other values, a shared foundation of collaboration for internet pioneers.</p>
<p>The most fervent commitment of this strain was faith in markets to sort out information distribution problems through pricing signals,<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-many-perspectives-2" id="fnref-many-perspectives-2">2</a></sup> and that view became embedded deeply into the internet's governance mechanisms.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-standards-as-critique-3" id="fnref-standards-as-critique-3">3</a></sup> If competition does not function, neither do standards.</p>
<p>The internet's most consequential designs took competitive markets as granted. Many participants believed hardware and software markets would (and should) continue to decouple; that it would be easier for end-users to bring their own software to devices they owned. It is odd from the perspective of 2025 to suggest that swapping browsers, e.g., should come at the cost of replacing hardware. This is why Apple have worked so hard to obscure that this is exactly the situation it has engineered, to the detriment of users, the web, and internet standards.</p>
<p>Internet standards bodies assumed the properties of open operating systems and low-cost software replacement to such an extent that their founding documents scarcely bother to mention them.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-the-long-arc-of-att-4" id="fnref-the-long-arc-of-att-4">4</a></sup> Only later did statements of shared values <a href="https://open-stand.org/about-us/principles/">see fit to make the subtext clear.</a></p>
<p>And it has worked. Internet standards have facilitated interoperability that has blunted lock-in, outsized pricing power, and other monopolistic abuses. This role is <em>the entire point</em> of standards at a societal level, and the primary reason that competition law carves out space for competitors to collaborate in developing them.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-collusion-protection-5" id="fnref-collusion-protection-5">5</a></sup></p>
<p>But this is not purely an economic project. Standards attenuate the power of firms that might seek to arrogate code's privileges. Functional interoperability enables competition, reallocating power to users. Standardisation is therefore, at least partially a political project; one that aligns with the values of open societies:</p>
<blockquote>
<p>We must ask whether ... we should not prepare for the worst leaders, and hope for the best. But this leads to a new approach to the problem of politics, for it forces us to replace the question: <strong>&quot;Who should rule?&quot;</strong> by the new question: <strong>&quot;How can we so organize political institutions that bad or incompetent rulers can be prevented from doing too much damage?&quot;</strong></p>
<p><span class="credit">        <a href="https://archive.org/details/in.ernet.dli.2015.59272/page/n135/mode/1up" taget="_blank">— Karl Popper,<br />&quot;The Open Society and Its Enemies&quot;</a>      </span>    </p></blockquote><p></p>
<p>Without a counterweight, network effects allow successful tech firms to concentrate wealth and political influence. This power allows them to degrade potential competitive challenges, enabling rent extraction for services that would otherwise be commodities. This mechanism operates through (often legalised) corruption of judicial, regulatory, and electoral systems. When left to fester, it corrodes democracy itself.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-hard-proof-6" id="fnref-hard-proof-6">6</a></sup></p>
<p>Apple has deftly used a false cloak of security and privacy to move the internet, and the web in particular, toward enclosure and irrelevance. Cupertino acts as a corrupted, and indeed <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">incompetent,</a> autocrat in our digital lives, even for folks who don't carry iPhones. It accomplishes this trick through abuse of a unique monopoly, allowing it to <a href="https://www.theverge.com/2023/11/13/23959353/google-apple-safari-search-revenue-antitrust-trial">extract rents, including on the last remnants of open ecosystems it tolerates.</a></p>
<p>Worse, Apple's centralisation through the App Store <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">entrenches the positions of peer big tech firms, harming the prospects of competitors in turn.</a> Apple have been, over the course of many years, poisonous to internet standards and the moral commitments of that grand project.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-not-lightly-7" id="fnref-not-lightly-7">7</a></sup></p>
<p>Despite near continuous horse-race coverage in the tech press, the consequences of this regression in civic/technical affairs is not well socialised.</p>
<h2 id="the-power-of-interoperability" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#the-power-of-interoperability">The Power of Interoperability</a></h2>
<p>Standardisation expands the reach of interoperable technology, pushing firms to innovate, rather than extracting rents on commodities.</p>
<p>Interoperability-in-being gives users choice, forcing competitors to differentiate on quality and not-yet-standard features. Standards expedite interoperability by lowering the costs for implementers and reducing tail risks, e.g. from patent trolls. Over time, a complete enough set of standards can attenuate the power of vendors to extract rents and prevent progress in important domains.</p>
<p>Interoperability is not the only mechanism that can reduce the power of dominant firms, but it is the most powerful. Free and Open Source software (<abbr title="Free and Open Source Software">FOSS</abbr>) can provide a counterweight too, but <abbr title="Open Source Software">OSS</abbr> is not a full solution.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-the-limits-of-oss-8" id="fnref-the-limits-of-oss-8">8</a></sup></p>
<h2 id="voluntary-adoption-is-foundational-to-internet-standards" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#voluntary-adoption-is-foundational-to-internet-standards">Voluntary Adoption Is Foundational to Internet Standards</a></h2>
<p>Interoperability, and the <a href="https://en.wikipedia.org/wiki/Economic_surplus">economic surpluses</a> that flow from it, are underpinned by <em>voluntary adoption</em>. This is enshrined in the <a href="https://open-stand.org/about-us/principles/">&quot;open stand&quot; principles</a> <a href="https://open-stand.org/about-us/affirmation/">agreed to by no less than ISOC, <abbr title="Internet Engineering Task Force">IETF</abbr>, <abbr title="In-App Browser">IAB</abbr>, IEEE, and the <abbr title="World Wide Web Consortium">W3C</abbr>.</a>:</p>
<blockquote>
<p>...</p>
<p><strong>5. Voluntary Adoption</strong></p>
<p>Standards are voluntarily adopted and success is determined by the market.</p>
<p><span class="credit">        <a href="https://open-stand.org/about-us/principles/" taget="_blank">— The <abbr title="In-App Browser">IAB</abbr>, IEEE, <abbr title="Internet Engineering Task Force">IETF</abbr>, ISOC, and <abbr title="World Wide Web Consortium">W3C</abbr>,<br />&quot;The OpenStand Principles&quot;</a>      </span>    </p></blockquote><p></p>
<p>This final principle is the shortest, and many readers will understand it as a dodge; a way for Standards Development Organisations (<abbr title="Standards Development Organisations">SDOs</abbr>) to avoid being seen to pick winners. But it is more than that.</p>
<p>Voluntary adoption is necessary for internet standards to function, and it creates a presumption of fair play.</p>
<p>Several implications bear mentioning.</p>
<p>First, the principle of voluntary adoption is necessary for effective standards development. Without a mechanism for determining which designs are better, we are unable to make consistent progress. That test never comes from within an <abbr title="Standards Development Organisation">SDO</abbr>; it is always customer-defined. Writing a standard is not a test of quality, and without a functional market to test designs in, <abbr title="Standards Development Organisations">SDOs</abbr> are irrelevant.</p>
<p>Second, this principle outlines a live-and-let-live doctrine, both within standards bodies and in the market. Participants may want their design to win, but are enjoined from procedural shenanigans to prevent competing designs from also being standardised.</p>
<p>Lastly, voluntary adoption marks customers (developers) and suppliers (browser vendors, etc.) as peers and creates norms of mutual respect within the walls of <abbr title="Standards Development Organisations">SDOs</abbr>.</p>
<p>For all of these reasons, voluntary adoption must be defended, and actions taken to undermine it met with resistance and eventual sanction.</p>
<h2 id="apple's-unique-monopoly" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-unique-monopoly">Apple's Unique Monopoly</a></h2>
<p>Regulators have had no difficulty in building market tests that demonstrate the power Apple holds in the lives of users.</p>
<p>Some of these tests have produced comical contortions as Apple has attempted to weasel out of its responsibilities. Consider the Trinitarian <a href="https://www.theregister.com/2023/11/02/apple_safari_browser/">claim that Safari is simultaneously one product, and also three.</a> Or that iPadOS, despite sharing nearly all code with iOS, marketed under that brand for years, supporting identical features, running the same third-party software, releasing on the same cadence, and running exclusively on the same hardware architecture is (somehow) an entirely different product.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-rejected-9" id="fnref-rejected-9">9</a></sup></p>
<p>But for as clear and effective as <a href="https://ec.europa.eu/commission/presscorner/detail/en/qanda_20_2349">regulator's tests have been in piercing these smoke screens,</a> they do not capture the most important aspects of Apple's influence on the market for smartphone software: the monopoly on wealth.</p>
<p>Apple suppresses standards-based platforms and their disruptive potential through a mechanism every software developer understands: wealthy users carry iPhones, and they have all the influence.</p>
<p>Competition law does not explicitly recognise this distortion of the market, but the connection between the influence of the wealthy and the choices available to other end-users is indisputable.</p>
<p>Despite selling fewer than a quarter of smartphones globally for the past decade, Apple has built and anti-competitively maintained a supermonopoly among the wealthiest 10-20% of the world's population who, in turn, <a href="https://en.wikipedia.org/wiki/Distribution_of_wealth">control effectively all wealth on the planet.</a> This has handed it control over software distribution due to the social effects of wealth. Apple pairs legitimately superior product attributes (e.g., leading chip design) with anti-user and anticompetitive tactics — e.g., green vs. blue chat bubbles, suppression of browsers — to maintain this position.</p>
<p>Apple has put in place a set of interlocking restrictions to ensure the web cannot disrupt native apps within this user base. Those users, in turn, warp the behaviour of software developers thanks their spending power and positions within the software industry. Developers understand that if they cannot demo their wares to bosses and VCs (all of whom are wealthy) on their own devices, their software might as well not exist.</p>
<p>The long-stable propensity of users who make more than $100K USD/year to carry iPhones combines with Apple's suppression of browsers and <abbr title="Progressive Web App">PWA</abbr> capabilities to ensure developers have no choice but to build native applications. These effects were visible in population-level statistics a decade ago and have been stable ever since:</p>
<blockquote>
<p>Knowing whether someone owns an iPad in 2016 allows us to guess correctly whether the person is in the top or bottom income quartile 69 percent of the time. Across all years in our data, no individual brand is as predictive of being high-income as owning an Apple iPhone in 2016.</p>
<p><span class="credit">        <a href="https://www.nber.org/system/files/working_papers/w24771/w24771.pdf" taget="_blank">— Marianne Bertrand and Emir Kamenica,<br />&quot;Coming Apart? Cultural Distances in the United States Over Time&quot;</a>      </span>    </p></blockquote><p></p>
<p>Developers are forced into the App Store by missing web capabilities, ensuring an advantage for Apple's proprietary ecosystem. This induces wealthy and influential users to default to the App Store for software, further damping the competitiveness of open platforms.</p>
<p>The monopoly on influence explains why Apple is <a href="https://open-web-advocacy.org/apple-dma-review/">wedded to legalistic, dissembling tactics</a> in order to <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">prevent the spread</a> of web apps. Should the work of internet and web standards bodies ever become relevant, Cupertino understands the market for software will transform in ways it cannot control or tax.</p>
<h3 id="how-apple-uses-its-monopoly-to-centralise-and-enclose" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#how-apple-uses-its-monopoly-to-centralise-and-enclose">How Apple Uses Its Monopoly to Centralise and Enclose</a></h3>
<p>Developers are forced into the App Store by a lack of functionality in browsers and web apps. By contrast, Apple has <a href="https://arxiv.org/abs/2506.22639">liberally meted out fingerprintable system capabilities to privacy-invading native apps</a>. It has also allowed them to <a href="https://www.theregister.com/2024/03/27/inapp_browsers/">suppress pro-privacy interventions</a> when it serves them.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-privacy-counterfactuals-10" id="fnref-privacy-counterfactuals-10">10</a></sup></p>
<p>Apple professes that <a href="https://www.nbcnews.com/tech/tech-news/apple-ceo-tim-cook-slams-facebook-privacy-human-right-it-n860816"><em>&quot;privacy is a human right&quot;</em></a>, but this as an attempt to turn the consequences of Apple's own largesse towards data abusers into a marketing asset. Wide-scale privacy erosion has depended, fundamentally, on Apple's own decisions, and it has not recanted.</p>
<p>It was Apple's choice to introduce less safe, less privacy-preserving native apps into iOS. It was also Apple's choice to deny competing browsers engines the freedom of voluntary feature adoption. This has ensured that important underlying capabilities could only ever be accessed through Apple's proprietary APIs, and only ever by those who are willing to agree to Cupertino's extractive terms.</p>
<p>The result has been API <a href="https://en.wikipedia.org/wiki/Enclosure"><em>enclosure</em></a>; appropriation of commodity capabilities that themselves are standards-based — e.g., rich graphics, USB, Bluetooth, NFC, file storage, etc. — by a proprietary ecosystem. Meanwhile, it has delayed and undermined the emergence of safe and privacy-preserving versions of those features on the web.</p>
<p>This, in turn, has created a winner-take-all dynamic inside the app store, harming privacy, security, and competition in the process.</p>
<h2 id="apple's-transgressions-against-voluntary-adoption" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#apple's-transgressions-against-voluntary-adoption">Apple's Transgressions Against Voluntary Adoption</a></h2>
<p>This strategy relies on interlocking policies that harm competitors, and the sabotage of voluntary standards adoption lies at its heart. A Bill of Particulars for crimes against the internet community springs from a small set of undisputed facts.</p>
<p>Apple has:</p>
<ul>
<li>
<p>Restricted competitors from shipping their own implementations of web and internet standards, depriving them access to influential users.</p>
</li>
<li>
<p>Forced all iOS browsers to use Apple's own <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">defective,</a> <a href="https://infrequently.org/2021/04/progress-delayed/">impoverished</a> implementation.</p>
</li>
<li>
<p>Undermined user security and privacy through iOS browser engine monoculture.</p>
</li>
<li>
<p>Used contractual terms to dissuade competitors from supporting standards Apple disfavours.</p>
</li>
<li>
<p>Objected spuriously within standards bodies to prevent standardisation of features which Apple offered no counter-proposal.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-evidence-of-bad-faith-11" id="fnref-evidence-of-bad-faith-11">11</a></sup></p>
</li>
<li>
<p>Engaged in marketing and product UI that discourages use of web-based alternatives.</p>
</li>
<li>
<p>Misled regulators and the public when presented with evidence of the harm from these actions.</p>
</li>
</ul>
<p>Through these and other overt acts, Apple has worked to disempower users, depriving them of choice by preventing open platforms from challenging native apps.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-platforms-are-competitions-12" id="fnref-platforms-are-competitions-12">12</a></sup></p>
<p>This isn't just a fierce market participant competing aggressively. Apple has done violence to the founding ethos of internet and web standards development. Instead of honourably withdrawing from those groups, Apple has maintained <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">a charade of engagement,</a> and gaslights other participants while actively sabotaging the principle of voluntary adoption that internet standards rely on.</p>
<h3 id="unilateral-off-ramps" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#unilateral-off-ramps">Unilateral Off-Ramps</a></h3>
<p>Apple has never been forced to suppress its competitors, nor to create an anticompetitive landscape. Cupertino's senior management have intellectually consistent options that would allow it to pursue growth of the superior (we are told) native app ecosystem without threatening browser choice or the good functioning of internet standards.</p>
<p>Let's consider two: <em>all safe browsers</em>, and <em>no browsers</em>.</p>
<p>Apple could, of course, simply enable the same sort of level playing field for high-quality browsers that every competing general-purpose OS vendor has for the web's entire history. Apple itself facilitates this sort of ecosystem on macOS.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-dark-days-13" id="fnref-dark-days-13">13</a></sup> Any plausible restrictions stemming from available system resources have long been overcome by progress in mobile hardware, <em>particularly</em> within Apple's ecosystem.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-fully-aware-14" id="fnref-fully-aware-14">14</a></sup></p>
<p>The only reasonable restrictions on competing browser engines relate to security. As other vendors have generally had a better track records than Apple regarding sandboxing, incident response, patch gaps, and support for older OS versions, this should be no practical obstacle.</p>
<p>Lest Apple's defenders worry about the impact on Safari, recall that under true browser choice, Apple retains considerable market advantages, including (but not limited to) pre-installation, lower structural costs<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-safari-is-cheap-to-build-15" id="fnref-safari-is-cheap-to-build-15">15</a></sup>, and continued differentiation through integration.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-doth-protest-too-much-16" id="fnref-doth-protest-too-much-16">16</a></sup> Such bulwarks have allowed Safari to retain considerable share on macOS in spite of stiff competition and Safari's poor track record on security and standards conformance.</p>
<p>Alternatively, Apple could withdraw Safari while forbidding web content on iOS. This is a fully consistent position, and has been available to Apple from the moment of the App Store's release. The iPod did not include a browser, and many subsequent Apple OSes lack functional browsers. iOS and visionOS are uniquely deficient in this regard.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-too-late-maybe-17" id="fnref-too-late-maybe-17">17</a></sup></p>
<p>Either way, the decision to undermine choice and standards rests entirely with Apple. It has always had intellectually honest solutions to the problems it has created. Apple cannot claim the situation is anyone else's fault, or that it has had no alternative.</p>
<h2 id="how-apples-crimes-differ-from-prior-episodes" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#how-apples-crimes-differ-from-prior-episodes">How Apples Crimes Differ From Prior Episodes</a></h2>
<p>Under voluntary implementation, every vendor is free to ship what they please, including Apple. It may be sad, or even damaging, when features go missing from important products, but that is not a calamity; just an input to be priced by the market — a reason for a specific browser to gain or lose share.</p>
<p>It's not enough to cite a lack of features, <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">bungled implementations,</a> <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-counter-or-gtfo-2">peevish behaviour in working groups</a> — or even <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">rank dishonesty</a> — as reason for censure. These are, to greater or lesser degrees, players playing the game. Certain tactics may be distasteful, but are squarely inside the <em>&quot;awful but lawful&quot;</em> zone. Standards venues <em>should</em> allow them, with sanctions for poor behaviour meted out in the social realm.</p>
<p>But by undercutting voluntary implementation, Apple has committed a more fundamental and more dangerous outrage.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-high-crimes-18" id="fnref-high-crimes-18">18</a></sup></p>
<p>Some will see a parallel to the <a href="https://en.wikipedia.org/wiki/Paradox_of_tolerance">Paradox of Tolerance</a>, and I do not believe this is mistaken. Standards bodies can, and should, admit many positions by their participants, but granting membership in good standing to those who are actively poison the basis for standards is madness. It ensures that standards, and the ecosystems that depend on them, wither and die.</p>
<p>By subverting the voluntary nature of open standards, Apple has defanged them as tools for users against the totalising power of technology firms in their digital lives. This <a href="https://home.uchicago.edu/~csunstei/moreisless.html">high-modernist</a> approach is antithetical to the foundational commitments of internet standards bodies and, over time, erode them.</p>
<p>Indeed, no other vendor has achieved what Apple has in suppressing the web through anticompetitive means. We must not imagine that Apple would stop at the Application layer given a chance. The same mechanism threatens voluntary feature adoption in networking and every other layer down the stack, too.</p>
<h2 id="necessary%2C-proportional-responses" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#necessary%2C-proportional-responses">Necessary, Proportional Responses</a></h2>
<p>The web and internet communities should understand the threat and clock the cumulative harm done to internet standards and open technology ecosystems. It seems to me that this point has hardly been engaged, let alone won, within the walls of <abbr title="Standards Development Organisations">SDOs</abbr>. But if it were, then what? What can be done?</p>
<p>The founding documents of internet <abbr title="Standards Development Organisations">SDOs</abbr> do not include censure mechanisms for sabotage. The <a href="https://www.w3.org/2024/09/25-w3c-bylaws-copy.html"><abbr title="World Wide Web Consortium">W3C</abbr>'s bylaws,</a> for example, only relate membership in good standing with paying dues. Regardless, it is possible — and I believe urgent — to do more.</p>
<p>First, proposals can be raised to amend bylaws to include mechanisms for censure by votes of the membership for the kinds of outrages alleged here. These are likely to fail, and will surely be rejected at first, but the act of raising these questions has power. Bringing up these issues in plenary meetings can, at a minimum, elicit a response. That, on its own, is valuable to the community.</p>
<p>Next, leadership boards with moral authority can consider the question and issue guidance. The <abbr title="World Wide Web Consortium">W3C</abbr>'s <a href="https://www.w3.org/2002/ab/">Advisory Board</a> and <a href="https://www.w3.org/2001/tag/">Technical Architecture Group</a> and the <abbr title="Internet Engineering Task Force">IETF</abbr>'s <a href="https://www.iab.org/about/">Internet Architecture Board</a> have the ear of the membership, even on non-technical topics, should they choose to weigh in on the side of their own continued relevance.</p>
<p>Most importantly, individual delegates to Working Groups can recognise that Apple's forced monoculture is illegitimate and corrosive. They can resolve not to accept <em>&quot;Apple does not comment on future products&quot;</em> in response to questions about implementation timelines.</p>
<p>As long as Cupertino demands a monopoly, we must demand it take responsibility for the consequences.</p>
<p>Today, Apple alone chooses which features ship in WebKit, and which can be used by competing browsers. Even if it does not to enable them in Safari, it can provide more to others. It is simply <em>illegitimate</em> for Apple to claim that it cannot, or should not, allow other vendors to reach feature parity between their iOS browsers and other products that use their own engines.</p>
<p>WebKit purports to be Open Source, but in practice Apple has used it to undermine the <em>&quot;bring your own code&quot;</em> foundation of <abbr title="Open Source Software">OSS</abbr>. It is illogical for Apple to cite a disinterest in a feature <em>in Safari</em> as a reason for Apple not to be expected to implement those features in iOS's WebKit binary, making them available for other embedders to flag on.</p>
<p>The sham of WebKit as an Open Source project is incompatible with preventing other vendors from introducing features they would turn on for their iOS users if allowed. The destruction of voluntary adoption is not a shield against critique. Instead, it must heighten expectations. Apple agues it should be singularly entrusted with control over all web features on iOS, despite Safari and WebKit's trailing record on standards' conformance, security, and even privacy. This is nonsense, but so long as it is the law of the land in code, Apple should bear the costs.</p>
<p>Apple alone must be on the hook to implement <em>any and every</em> web platform feature shipped by <em>any and every</em> other engine. It does not need to enable them in Safari, but must make them available for use by others as they see fit.</p>
<p>So long as competing vendors are forced into the App Store and required to use Apple's engine, Cupertino owes much more when it comes to completeness and quality. So long as Cupertino compels use of WebKit, the demand should be echoed back: <em>parity with browser features on other Operating Systems is the minimum bar</em>.</p>
<p>Fundamentally, the web and internet community must stop accepting the premise that Apple should benefit from the protections and privileges of voluntary feature adoption while denying it to others.<sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-consequences-19" id="fnref-consequences-19">19</a></sup></p>
<p>Lastly, and perhaps most controversially, delegates and organisations can use their positions to vote against Apple's personnel in elections to leadership positions within internet and web <abbr title="Standards Development Organisations">SDOs</abbr>. It is inconsistent for Apple to hold positions of influence in organisations it works to sabotage, and fellow participants are under no obligation to pretend otherwise. Handing Apple formal or persuasive power within these groups is a mistake, and one that can be corrected without changes to bylaws.</p>
<h3 id="why-now%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#why-now%3F">Why Now?</a></h3>
<p>In raising these questions, colleagues have invariably asked <em>&quot;why now? What changed?&quot;</em></p>
<p>Beyond the threshold point that the damage is cumulative, and therefore it isn't necessary to identify specific instances to discuss the spreading rot, it's fair to ask why anyone should be agitated tomorrow when they might not have been yesterday.</p>
<p>Most of the factors involved have indeed changed very gradually, and humans are famously poor judges of slowly emergent threats. Apple's monopoly on influence, Cupertino's post-2009 WebKit priorities, the suppression of browser competitors, and the never-ending parade of showstopping bugs are all gradually emergent factors. Despite all of this long-running, unrefuted evidence, many continue to think of Apple an ally of the web for helpful acts now more than 15 years old.</p>
<p>But recent events must shake us awake. <a href="https://infrequently.org/2024/02/home-screen-advantage/">Apple's petulant attempt to duck regulations, destroy the web as a competitor for good, and frame regulators for the dirty deed</a> was shocking. In recurring misrepresentations to regulators before and <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">since,</a> it has dissembled about its role in suppressing the web, and <a href="https://open-web-advocacy.org/blog/interop-2025-must-drop-secret-vetos/">through its demand for secrecy in quasi-standards processes,</a> has worked tirelessly to cover its tracks.</p>
<p>Taken individually, and in ignorance of iOS's coerced WebKit use by competing browsers, <a href="https://open-web-advocacy.org/blog/slap-and-flop--apples-lack-of-full-site-isolation-and-ios-browser-ban-puts-users-at-risk/">forced monoculture, habitual security failures,</a> and <a href="https://chrome-commit-tracker.arthursonzogni.com/organizations/commits?repositories=blink,jsc,v8,webkit&amp;organizations=ARM,Adobe,Apple,ByteDance,Google,Igalia,Individuals,Intel,LGE,Microsoft,Nokia,Opera,Samsung,Unknown,WebKit,Yandex&amp;grouping=yearly&amp;colors=organizations&amp;kind=both&amp;metric=contributor&amp;chart=bar&amp;dates=2017-12-11,2025-08-20">strategic starvation of the Safari team</a>, these shameful acts would simply indicate another monopolist behaving badly. It is only when considered alongside the wider set of facts that the anti-standards strategy and impact become clear.</p>
<h2 id="do-standards-matter%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#do-standards-matter%3F">Do Standards Matter?</a></h2>
<p>Like most who have dedicated the greater proportion of their working lives to the cause of an open and interoperable web, the conclusions offered here shock me as well.</p>
<p>In the end, however, the question <em>&quot;do standards matter any more?&quot;</em> is intrusive, despite my aversion to reconsidering a question whose answer I thought obvious. But in light of the past decade's <a href="https://infrequently.org/2024/10/platforms-are-competitions/">sidelining of the web,</a> we must grapple with the consequences. To allow Apple to continue to abuse the foundation of standards without acknowledgement would be a failure of honesty towards my own intellectual commitments.</p>
<p>My personal affinity for the many talented and thoughtful people that Apple has sent to standards bodies over the years — including those I think of as friends — has, on reflection, been an emotional blind spot. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/">But here we are.</a> The realisation that they have been an unwitting fifth column against the web is nauseating for me, and I expect many will loudly reject the conclusion. I do not blame them.</p>
<p>For all the harm Apple has done to the web and to competition, I had hoped that it would relent before any of this became necessary. Like most web developers, I harboured hope that, true to Steve Job's promise in '07, Apple would let the web be a <em>&quot;sweet solution&quot;</em> for delivering safe, powerful applications. Piggybacked on that hope was a belief that a relevant mobile web would bolster the relevance of standards. But Cupertino has gone a different way, choosing profit over collaboration and the needs of users.</p>
<p>The web matters too much for the standards-based future it represents to fade without so much as a nod.</p>
<aside class="thanks">
<p>Thanks to <a href="https://toot.cafe/@kylealden">Kyle Pflug</a> and <a href="https://formularsumo.co.uk/">James Heppell</a> for their thoughtful feedback on drafts of this post.</p>
</aside>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-liberaltarian-1" class="footnote-item"><p>Or, if you like, <a href="https://www.gsb.stanford.edu/insights/rise-liberaltarian">&quot;liberaltarian&quot;</a>. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-liberaltarian-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-many-perspectives-2" class="footnote-item"><p>A faith I do not share. Markets fail frequently, never mind that most goods are hardly substitutable, thinly traded, and lack reliable public prices. All of this means that the information capacity of markets <em>a priori</em> the rationalising effect of standards and market fairness regulation is heavily suspect.</p>
<p>But even for those that take a market fundamentalist perspective, restrictions on trade such as Apple has imposed are offensive to the basic logic of the market's role in bettering society. Only those who would see markets subjugate all, forever, because of one-time power imbalances can be sanguine about what Apple has done.</p>
<p>We do not have to grant pro-totalitarian arguments the assumption of good faith given what we know about where unchecked power leads. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-many-perspectives-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-standards-as-critique-3" class="footnote-item"><p>It is not original to note that there is an inherent contradiction in the idea of liber(al)tarian participants in standards bodies collaborating through non-market mechanisms. We do not have to ignore it, however, or even treat those holding both an affinity to open standards and libertarian ideals as hypocrites, in order to accept that the development of standards is often a creative act of critique for which there is no other functional venue (or, if you like, &quot;market&quot;).</p>
<p>Proposals for open internet standards often begin as personal drafts of individual authors, working in a community of like-minded developers experiencing similar challenges and working to design solutions. These proposals are situated in a context that is often opaque to those outside narrow circles, and the communities that form around them trade in reputation as much as any other currency.</p>
<p>In addition to personal status, there is a distinguishable ideology at work:</p>
<blockquote>
<p>The open systems ideology that was developed in computing between the 1970s and the 1990s embodied several assumptions articulated in previous open system visions in diplomacy, economics, philosophy, and engineering. These assumptions included:</p>
<ul>
<li>an economic commitment to global markets;</li>
<li>a moral support of international and multicultural ties;</li>
<li>a political opposition to centralized power — either in governments or in monopolies — that threatened individual autonomy;</li>
<li>a belief that technical professionals could achieve these economic, moral, and political aspirations through cooperation and standardization.</li>
</ul>
<p><span class="credit">        <a href="https://www.cambridge.org/core/books/open-standards-and-the-digital-age/3605A03EC74D80F2D30FE233C7BCBF35" taget="_blank">— Andrew L. Russell,<br />&quot;Open Standards and the Digital Age&quot;</a>      </span>    </p></blockquote><p></p>
<p>These <a href="https://open-stand.org/about-us/principles/">principles</a> stand as critique to older, less open ways of working. Technology that is more interoperable makes a larger space for critique through code and the market, and that is essential to the openness of any society that depends on software as much as modern, western nations do today. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-standards-as-critique-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-long-arc-of-att-4" class="footnote-item"><p>The history of Bell Labs, the antitrust battles of IBM, the birth of Unix, and <a href="https://historyofcomputercommunications.info/section/5.8/AT&amp;T-and-Computer-Inquiry-I-1970-1971/">the expectations of &quot;common carrier&quot; treatment</a> for data transmission help to situate the thinking of participants in setting up the foundational standards bodies that we now take for granted. Major battles were fought to keep computing out of the hands of a few corporations with outsized power, and the consequences continue to reverberate.</p>
<p>It is my personal view that it has been the good work of antitrust and anti-monopoly reformers — both within and outside government — that made it possible for other parties to believe in the abstraction of functional markets. Functioning markets are not, in fact, self-organising, and are enabled explicitly by law that helps to minimise noise in the channel (e.g., from fraud).</p>
<p>That self-identified libertarians (along with the rest of society) have benefited dramatically from the gains enabled by these anti-monopoly regimes is not in doubt; the only mystery is how fervently some cling to the belief that regulation <em>must</em> be problematic as a way to skip past its content and ignore engaging on substance. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-the-long-arc-of-att-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-collusion-protection-5" class="footnote-item"><p>Without an &quot;all clear&quot; signal for explicit standardisation, antitrust law in most advanced nations would explicitly forbid the sorts of coordination among industry peers that standards bodies facilitate. Authorities permit, and even encourage, standardisation in contrast to other forms of collaboration because the positive externality benefits of reduced friction to trade from interoperability is so compelling. For more on the history and structure of this now-international regime, see <a href="https://www.cambridge.org/core/books/open-standards-and-the-digital-age/3605A03EC74D80F2D30FE233C7BCBF35">Russell (2014)</a> <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-collusion-protection-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-hard-proof-6" class="footnote-item"><p>One needs to look no further than <a href="https://apnews.com/article/trump-inauguration-tech-billionaires-zuckerberg-musk-wealth-0896bfc3f50d941d62cebc3074267ecd">tech CEOs lining up to hail</a> the rise of explicitly fascist leaders and <a href="https://wapo.st/45EdNmI">ply them with gifts,</a> to understand the ways in which this corruption corrodes our hopes for open, tolerant societies. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-hard-proof-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-not-lightly-7" class="footnote-item"><p>This is not an accusation to be levelled lightly, and not without overwhelming evidence. But that evidence has accrued, and so I feel compelled to speak.</p>
<p>Apple are known both to be capricious and retributive, and its antipathy towards <a href="https://www.khronos.org/">Khronos</a> provides an excellent example of the decade-length grudge-holding for which Cupertino is infamous. I therefore write this post advisedly and with trepidation. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-not-lightly-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-limits-of-oss-8" class="footnote-item"><p>More than twenty years into the experience of Open Source as a force in software, we can clearly discern that the licence of source code is not, in-and-of itself, a solution to the imbalances inherent in software's relationship to users, or even to other parties with the capacity to develop software.</p>
<p>I believe that history demonstrates clearly that (F)<abbr title="Open Source Software">OSS</abbr> licensing and effective governance are only related by the intellectual and commercial commitments of those building software, and are therefore easily co-opted by wealthy and powerful firms.</p>
<p>We have witnessed the limits of forking as a bulwark against bad behaviour, through both the persistent upward reach of firmware into &quot;open&quot; systems, and through capture in higher layers due to the carrying costs of complex systems. Licensing has also been little help in courts against large and determined enemies of <abbr title="Open Source Software">OSS</abbr> and the freedoms it attempts preserve. The limits of licensing, and the lack of IP defence pooling inherent in common licences, create risks that successful firms and projects hit regularly.</p>
<p>At the limit, (F)<abbr title="Open Source Software">OSS</abbr> licensing is not a significantly disruptive force against wealthy and powerful technology firms, but rather a tool that is useful to peer-level adversaries. For <abbr title="Open Source Software">OSS</abbr> licences and defences to have purchase in practice, a significantly endowed group of technologist's interests must be at stake. The interests of informed and financially capable technologists and the firms that use their software bear only passing resemblance to the needs and interests of society more broadly.</p>
<p>From this perspective, we can understand (F)<abbr title="Open Source Software">OSS</abbr> as complementary to standards development, but unable to fully replace standards-based interoperability as an attenuating force on the power of software in the lives of users. Standards retain a unique ability to build space for challengers within and between proprietary products, which (F)<abbr title="Open Source Software">OSS</abbr> do not. The power of <abbr title="Standards Development Organisations">SDOs</abbr> to pool the patent interests of proprietary players has parallels in (F)<abbr title="Open Source Software">OSS</abbr>, but with more clarity and lower risk, further accelerating practical interoperability.</p>
<p>Therefore, we must understand that it is a rhetorical and intellectual trap to consider (F)<abbr title="Open Source Software">OSS</abbr> a replacement for standards. Each hasten interoperability and attenuate power in different and complementary — but not substitutable — ways, and both mechanisms are healthier when the other succeeds. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-the-limits-of-oss-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-rejected-9" class="footnote-item"><p>The EC, having borne witness to <a href="https://infrequently.org/2022/02/minimum-standards/">Apple's appalling behaviour</a> within its borders, and more generally to boot, <a href="https://academic.oup.com/jeclap/article/16/1/3/8034849">was having none of it.</a></p>
<p>The <a href="https://ec.europa.eu/competition/digital_markets_act/cases/202427/DMA_100047_5491.pdf">full finding (PDF)</a> is a masterclass in even-handed consideration, and as such it is not surprising that Apple's legal and marketing fictions failed. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-rejected-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-privacy-counterfactuals-10" class="footnote-item"><p>Helpfully for Apple, the conversation around privacy and technology has barely progressed past Apple's <a href="https://www.ft.com/content/916a766a-3d27-11ea-a01a-bae547046735">anti-Google</a> and <a href="https://mobiledevmemo.com/apple-robbed-the-mobs-bank-part-2/">anti-Facebook</a> <a href="https://www.macrotrends.net/stocks/charts/META/meta-platforms/revenue">kayfabes.</a></p>
<p>Privacy advocates are regularly taken in by Apple's marketing, and the tech press remains in a largely <a href="https://9to5mac.com/2025/07/29/with-ios-26-safari-will-counter-one-of-the-webs-most-invasive-tracking-methods/">stenographic mode.</a> None of this is to say that Google or Facebook are good actors (they are not), only that Apple is also <a href="https://wapo.st/3JWFdNl">not on the level.</a></p>
<p>We can begin an analysis by noting that Apple does not encourage users to move their computing to the web where browsers can attenuate the worst invasions of privacy. Browsers do not provide nearly as much information to trackers as even the most locked-down native app in Apple's ecosystem, and Apple know this.</p>
<p>Next, Apple has not funded lobbying and regulatory outreach efforts to establish privacy laws worth a damn. Instead, it channels huge amounts into defeating right-to-repair legislation and defeating browser engine choice around the world, including going as far as <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">funding astroturf groups</a> to provide Cupertino's views in stereo.</p>
<p>Moreover, Apple takes no responsibility for its historical role in the growth of tracking via the native API surfaces Apple created relative to the web. Nor does it demand audits of data use by App Store participants, or to even set policy about acceptable uses of data collected via App Store-vended applications.</p>
<p>Apple <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/">does not even forbid pervasive &quot;ad blocker blocking&quot;</a> by the worst actors in its ecosystem, even when interventions are trivial from a policy and technical perspective.</p>
<p>That all of this aligns with Apple's preference for control over, and taxation of, developers cannot escape comment. It further forces us to entertain the idea that Apple's position as a defender of privacy is a cynical show, or that it is incompetent in assessing privacy risks, or that it is out of touch with the behaviour of snooping developers. Any of these would be enough to judge it an incompetent regulator, asleep at the switch.</p>
<p>Depressingly, these are not even exclusive choices. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-privacy-counterfactuals-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-evidence-of-bad-faith-11" class="footnote-item"><p>It is <em>prima facie</em> evidence of bad faith for a vendor <a href="https://www.bloomberg.com/news/articles/2024-05-01/google-s-payments-to-apple-reached-20-billion-in-2022-cue-says">that skims as much cash from the open web as Apple does</a>, and which insists it must maintain a monopoly on browser engines, to object to providing implementations of proposals that other vendors have shipped safely for years, without offering their own designs to address similar needs,</p>
<p>This case is bolstered by <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-counter-or-gtfo-2">Apple late-implementing designs which it spuriously objected to as regulatory pressure has grown.</a></p>
<p>By failing to engage in solving problems, then citing its own objections as reason not to implement the resulting demonstrably safe features, Apple have cut the legs out from underneath any protection from critique. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-evidence-of-bad-faith-11" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-platforms-are-competitions-12" class="footnote-item"><p><a href="https://infrequently.org/2024/10/platforms-are-competitions/">Platforms are in competition.</a></p>
<p>It cannot escape notice that Apple's undermining of voluntary adoption most damages interoperable platforms that might challenge the App Store-based native app ecosystem which supports Apple's vertical integration agenda. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-platforms-are-competitions-12" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-dark-days-13" class="footnote-item"><p>Here we must mention other instances of operating systems imperilling browser choice. Microsoft, for instance, <a href="https://x.com/BrendanEich/status/1636810626625601536">was credibly accused of making text less readable on Netscape Navigator.</a></p>
<p>Google, for its part, introduced ChromeOS without any provision for competing browsers. Subsequently, it allowed Android versions of competing browser products using their own engines to register as the default system browser. This is an unsatisfying solution, as Play-based apps are a poor experience on low-end devices and competing browsers are prevented from integrating as deeply as Chrome does. This may not rise to the level of Apple or Microsoft's acts as ChromeOS <a href="https://gs.statcounter.com/os-market-share">remains a niche product,</a> ranks lowest in influence, and features a capable browser — regardless, the precedent, combined with prior episodes of Microsoft and Apple turning away from their successful and capable browsers, remains troubling. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-dark-days-13" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-fully-aware-14" class="footnote-item"><p>No company in the world is more aware of the awesome power and capability of Apple's A-series chips than Apple itself.</p>
<p>Apple executives know, for instance, that even the least expensive iPhone produced in the past five years is hundreds of times faster than the first iPhones which gave rise to resource-based restrictions on engine choice. They are either aware, or can trivially deduce, that there is no legitimate system health or resource-related reason to disallow competing browser engines. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-fully-aware-14" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-safari-is-cheap-to-build-15" class="footnote-item"><p><a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/">As I have discussed before,</a> Apple economises on the development of WebKit and Safari not only by failing to fund development of web features in a timely way, drafting on the path-breaking work of others, but also through an (over)reliance on OS components in lieu of more easily defended abstractions. This goes much deeper than only needing to support a single family of operating systems; unlike competitors, Apple directly leans on OS systems where competitors rebuild large swaths of the runtime to enable the web where underlying OS APIs are more limited.</p>
<p>The result, for Apple, is reduced headcount and a lower <a href="https://en.wikipedia.org/wiki/Bill_of_materials">bill-of-materials</a> when producing devices (read: higher profits), owing to higher code page sharing across applications.</p>
<p>The consequence for users is an implementation monoculture and <a href="https://googleprojectzero.blogspot.com/2022/02/a-walk-through-project-zero-metrics.html#h.4ajnbffcm6lj">slower patch delivery,</a> harming security. Apple's users remain vulnerable to attacks for longer and without recourse to competing alternatives with stronger track records. The downside of all high modernism is brittleness, borne of uniformity, and iOS is no exception. The lack of the ecological diversity that Apple demands undermines security and resilience. This is not a price society should pay for the convenience of a blue chat bubble. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-safari-is-cheap-to-build-15" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-doth-protest-too-much-16" class="footnote-item"><p>In testimony before various competition authorities around the world, and in <a href="https://developer.apple.com/support/dma-and-apps-in-the-eu/">peevish</a> <a href="https://developer.apple.com/support/downloads/DMA-Interoperability-Dec-2024.pdf">screeds</a> in response to those arguments failing, Apple habitually attempts a rhetorical redirection that unmasks its anti-Popperian thirst for control.</p>
<p>It appears to believe, on the strength of brand, that it can win on the ground of <em>&quot;who should rule?,&quot;</em> rather than <em>&quot;how can institutions keep bad rulers from doing too much damage?&quot;</em> In so doing, Apple offers an authoritarian model of technology. Cupertino proposes that all sources of control attenuation are themselves totalising, and any compromise forced on the ruler therefore equivalent to a coup.</p>
<p>This is nonsense, both practically and historically, and technologists that support democratic norms should reject this framing.</p>
<p>History shows clearly that open systems in open societies enable civil society to take many effective positions that attenuate untrammelled power, both of the state and of other actors. We can further see that neither open nor closed systems are full bulwarks against government coercion. The prospects for improved societies must not be invested in autocratic technology firms for the simple reason that they are powerless to deliver it.</p>
<p>Apple itself has <a href="https://www.wired.com/story/apple-iphone-parts-pairing-right-to-repair/">been forced to compromise</a> in areas such as <a href="https://www.repair.org/">right-to-repair</a> without any of the <a href="https://pluralistic.net/2023/09/22/vin-locking/">apocalyptic prophecies of Cupertino's lobbyists</a> coming to pass.</p>
<p>Here Apple, and its extremely vocal band of apologists, will bring up overreaches by others, including <a href="https://www.internetsociety.org/blog/2025/07/a-uk-government-order-threatens-the-privacy-and-security-of-all-internet-users/">disastrous and ill-advised anti-encryption pushes by national governments.</a> The goal of this argument is to sully the idea of democratic control of technology. <em>&quot;How&quot;</em>, it asks leadingly, <em>&quot;can anyone trust <strong>these</strong> people to do what's right for users?&quot;</em></p>
<p>How indeed! For the central point is that we do not have to. Recourse is available (in functioning democracies) through elected representatives and the responsiveness to citizen's concerns. We can even accept that democracies will get many of these issues wrong for a time without seceding any ground to Apple's authoritarian offer. It is intellectually consistent to reject both noxious positions taken by elected officials and offers of high modernist control by firms opposed to the current positions of a government.</p>
<p>Apple's arguments are microns deep on the merits. They attempt to erase both the <a href="https://www.wired.com/story/britain-admits-defeat-online-safety-bill-encryption/">successes of civil society</a> (rather than Apple) in curbing abuses along with Apple's own shameful track record of <a href="https://restofworld.org/2022/apple-airdrop-china-memes/">capitulation to overtly authoritarian regimes.</a><sup class="footnote-ref"><a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fn-complexified-20" id="fnref-complexified-20">20</a></sup></p>
<p>Apple's framing asserts that total control by a famously unaccountable firm is a Panglossian utopia. That any decision Cupertino makes now, has ever made, or has ever reversed, have unquestionably been the best of all possible options. That by paying a thousand dollars for a phone, we are but lucky to bask in the glow of such resplendent wisdom.</p>
<p>It's all too much to take, at least for anyone with a working memory. As I hope I have demonstrated here, this posture fails on ethical as well as practical grounds.</p>
<p>Apple, with all of its power and money, could be an ally to civil society in curbing abuses without claiming total and unaccountable control for itself in the process. It is incumbent on any thinking technologist to reject such land grabs, even when they come wrapped in causes we otherwise support. To do otherwise is to co-sign the doctrine of <em>&quot;who should rule?,&quot;</em> a framing that is caustic to both our short-term technical and long-term societal interests. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-doth-protest-too-much-16" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-too-late-maybe-17" class="footnote-item"><p>Paradoxically, it may be Apple's own malign behaviour regarding browser choice that might prevent a <em>&quot;no browsers&quot;</em> policy from being possible today.</p>
<p>Even if we were to ignore Cupertino's incentive to maintain browsers on iOS owing to the shockingly large flows of money from Google for search placement (which Apple records as nearly pure profit), regulators may require it to pursue an <em>&quot;all browsers&quot;</em> alternative to fairly redress the harms from the previous 15 years of abuses. Should this come to pass, Cupertino would (again) have no party to blame but itself. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-too-late-maybe-17" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-high-crimes-18" class="footnote-item"><p>The damage Apple has done to the cause of internet and web standardisation is analogous to the (US) concept of impeachable <em>&quot;high crimes and misdemeanours&quot;</em>, rather than better enumerated, more pedestrian infractions. This category covers acts that are destructive to the foundational principles of the enterprise, regardless of narrow legality.</p>
<p>Internet <abbr title="Standards Development Organisations">SDOs</abbr> are not set up well to police or react to this class of offence, which may help explain why Apple's violence against the community has gone unremarked for so many years. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-high-crimes-18" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-consequences-19" class="footnote-item"><p>Apple engineers should be questioned (politely, but insistently) about timelines for implementation of any feature that any other engine chooses to ship, and failure to provide that timeline should be viewed as ongoing evidence of malfeasance against the internet and web community for as long as Apple withholds the ability for others to bring their own engines and whatever features they choose.</p>
<p>If this causes Apple to retreat from sponsoring work in these venues, that is regrettable, but must also be understood as a choice that is entirely within Apple's power to reverse. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-consequences-19" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-complexified-20" class="footnote-item"><p><a href="https://restofworld.org/2024/exporter-apple-airdrop-security-china/">The fuller airdrop story</a> creates a cross-pressured narrative in which it is possible to claim that Apple was acting to protect, rather than suppress, A4 protesters. But such a pose must also contend with Apple's own history of failure, <a href="https://blog.cryptographyengineering.com/2024/01/11/attack-of-the-week-airdrop-tracing/">first to build a truly private version</a> of a system marketed in those terms, thereby encouraging users in sensitive situations to expose themselves to great risk. Second, Apple's <a href="https://blog.cryptographyengineering.com/2024/01/11/attack-of-the-week-airdrop-tracing/#:~:text=but%20even%20if%20they%20didn%E2%80%99t%2C%20they%20were%20told%20about%20these%20issues%20back%20in%20May%202019%20by%20the%20Darmstadt%20folks">unwillingness to patch post-disclosure.</a></p>
<p>Owing to AirDrop's use of <a href="https://www.ditto.com/blog/cross-platform-p2p-wi-fi-how-the-eu-killed-awdl">closed protocols</a> that Apple does not make available to developers of competing applications, it also falls exclusively on Apple's shoulders that better solutions were not available to replace Apple's own botched implementation.</p>
<p>The story <em>is</em> more complex than <em>&quot;Apple sold protesters up the river,&quot;</em> but no publicly available version of events is a defence the argument that Apple is a bellicose marketing outfit with a situational and opportunistic relationship to user privacy and security.</p>
<p>When the effect is to expose or debilitate users that rely on the very properties Apple so truculently asserts its competitors fail to deliver, it becomes impossible to defend Cupertino's insistence that it alone should be trusted. <a href="https://infrequently.org/2025/09/apples-crimes-against-the-internet-community/#fnref-complexified-20" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Apple vs. Facebook is Kayfabe</title>
    <link href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/"/>
    <updated>2025-08-25T00:00:00Z</updated>
    <id>https://infrequently.org/2025/08/apple-vs-fb-kayfabe/</id>
    <content type="html"><![CDATA[
      <!-- LTeX: language=en-GB -->
<p></p><figure class="lede_figure"><picture style="--lqip: -40605" class="preview">      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/claudia-raya-wrestling-unsplash.avif" alt="Photo by Claudia Raya" style="aspect-ratio: 1500 / 1000" class="lede_figure preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>      <span class="credit">        <a href="https://unsplash.com/photos/a-group-of-people-in-a-wrestling-ring-1euWXa-SEKw" taget="_blank">Photo by Claudia Raya</a>      </span>    </figcaption>      </figure><p></p>
<p>Apple vs. Facebook is, and always was, <a href="https://en.wikipedia.org/wiki/Kayfabe">kayfabe</a>. In reality, Apple is Facebook's chauffeur; holding Zuck's coat while Facebook<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fn-not-calling-it-that-1" id="fnref-not-calling-it-that-1">1</a></sup> wantonly surveils iPhones owners.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fn-kayfabe-for-now-2" id="fnref-kayfabe-for-now-2">2</a></sup></p>
<p></p><figure><a href="https://m.macrotrends.net/stocks/charts/META/meta-platforms/gross-profit" alt="Facebook's gross profit over time." target="_blank"><picture style="--lqip: 173529" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-profits-historical-chart.png" alt="Facebook's gross profit over time." style="aspect-ratio: 800 / 500" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Facebook's gross profit over time.</figcaption>      </figure><p></p>
<p>Facebook and Apple mugged convincingly for the cameras as <a href="https://developer.apple.com/documentation/apptrackingtransparency">&quot;App Tracking Transparency&quot;</a> rolled out, talking up the impact to Facebook's business. But San Mateo's profits tell a very different story. <a href="https://www.macrotrends.net/stocks/charts/META/meta-platforms/net-income">Net income</a> dipped between late 2021 and early 2023 thanks to <a href="https://finbox.com/SWX:FB/explorer/capex/">accelerating capital expenditures</a>, not reductions in revenue. Despite strenuous efforts to sell the move, it's hard to discern any impact from <abbr title="App Tracking Transparency">ATT</abbr> whatsoever.</p>
<p>How can we be sure Apple's wise? Because Cupertino continues to allow Facebook's wide-scale abuse of <a href="https://open-web-advocacy.org/blog/in-app-browsers-the-worst-erosion-of-user-choice-you-havent-heard-of/">In-App Browsers:</a></p>
<p><lite-youtube videoid="-6mFC__dMWM" videotitle="Open Web Advocacy - In-App Browser Primer" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=-6mFC__dMWM">Open Web Advocacy - In-App Browser Primer</a>              </lite-youtube></p>
<p>Apple has long facilitated and enriched mass surveillance through native apps, both directly from in-app activity, but much more insidiously through the In-App Browsers that lurk behind every link in Facebook, Instagram, Messenger, Threads, TikTok, Pinterest, etc.</p>
<p><a href="https://infrequently.org/2021/07/hobsons-browser/">I have written about them before</a>, and they still stink to high heavens. Facebook couldn't ask for a better or more willing accomplice than Apple as it glides into the second decade of its browserjacking spree.</p>
<p>In-App Browsers are, for Facebook's purposes, <em>ad-blocker blockers</em>. Cheat codes for the enterprising panopticon proprietor. <a href="https://krausefx.com/blog/ios-privacy-instagram-and-facebook-can-track-anything-you-do-on-any-website-in-their-in-app-browser">Much wringing of hands transpires</a> every time one of these knockoff browsers is suspected of injecting script into web pages. The fear is that this will enable a level of tracking by apps that is not otherwise possible.</p>
<p>As scary (and real) as the threat is, it is also a misdirection.</p>
<p>To effect total surveillance, Facebook <em>et al.</em> don't need to inject scripts into the runtime, they only need your browser not to block their &quot;ad tags&quot; that are <em>already</em> embedded in every high-traffic page on the internet. Combined with <a href="https://developer.apple.com/documentation/webkit/wknavigationdelegate">the ability to watch every URL you navigate to in a WebView</a>, this is more than enough to correlate in-app activity with web browsing without leaving overt fingerprints.</p>
<p>As long as users remain in the web purgatory of native apps, data collected from tracking endpoints remains immeasurably richer. It is, in effect, a loophole that only requires users be denied access to their browser of choice whenever it is convenient for native apps.</p>
<p>Real browsers matter because they are <em>user agents</em>; they <a href="https://www.w3.org/TR/design-principles/#priority-of-constituencies">represent the interests of users,</a> rather than ad networks (Facebook, Google, ByteDance) and the OS vendors that are desperate to keep apps from decamping to portable, interoperable alternatives like <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/"><abbr title="Progressive Web Apps">PWAs</abbr>.</a> Users configure their browsers' privacy and security settings, knowing they will synchronize between devices. They can expand those protections with extensions that further ward against unwanted snooping.</p>
<p>By contrast, <abbr title="In-App Browsers">IABs</abbr> from Facebook and ByteDance (etc.) do not feature many privacy-preserving settings or extensions, are fiendishly hard to disable, and do not sync between devices in the same app. They don't even synchronise preferences <em>between multiple apps from the same company on the same device</em>.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fn-the-biggest-tell-3" id="fnref-the-biggest-tell-3">3</a></sup></p>
<p></p><figure class="up three">          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-home.png" alt="Promising-looking options for users trying to disable Facebook's IAB. Now to find the right one...maybe we can just search?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 524131" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png" alt="Promising-looking options for users trying to disable Facebook's IAB. Now to find the right one...maybe we can just search?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-search.png" alt="Promising-looking options for users trying to disable Facebook's IAB. Now to find the right one...maybe we can just search?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Promising-looking options for users trying to disable Facebook's <abbr title="In-App Browser">IAB</abbr>. Now to find the right one...maybe we can just search?          </figcaption>        </figure><p></p>
<p></p><figure class="up three">          <picture style="--lqip: 524131" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web.png" alt="Ok, let's search for 'web'...ah! 'Apps and websites', looks promising...well...no...maybe if we scroll. Hmmm. Nope." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 524066" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites.png" alt="Ok, let's search for 'web'...ah! 'Apps and websites', looks promising...well...no...maybe if we scroll. Hmmm. Nope." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search-web-apps-and-websites-2.png" alt="Ok, let's search for 'web'...ah! 'Apps and websites', looks promising...well...no...maybe if we scroll. Hmmm. Nope." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Ok, let's search for 'web'...ah! 'Apps and websites', looks promising...well...no...maybe if we scroll. Hmmm. Nope.          </figcaption>        </figure><p></p>
<p></p><figure class="up three">          <picture style="--lqip: 511843" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-search.png" alt="Well, what if we search for 'browser' instead? Tapping on 'Browser' takes us to a tab that...doesn't let us turn it off? Hm. Let's go back to the start...might have seen something about 'Content Preferences'...hrm, nope, not that." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png" alt="Well, what if we search for 'browser' instead? Tapping on 'Browser' takes us to a tab that...doesn't let us turn it off? Hm. Let's go back to the start...might have seen something about 'Content Preferences'...hrm, nope, not that." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: -221" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-content-preferences.png" alt="Well, what if we search for 'browser' instead? Tapping on 'Browser' takes us to a tab that...doesn't let us turn it off? Hm. Let's go back to the start...might have seen something about 'Content Preferences'...hrm, nope, not that." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Well, what if we search for 'browser' instead? Tapping on 'Browser' takes us to a tab that...doesn't let us turn it off? Hm. Let's go back to the start...might have seen something about 'Content Preferences'...hrm, nope, not that.          </figcaption>        </figure><p></p>
<p></p><figure class="up three">          <picture style="--lqip: 524131" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab.png" alt="Ok, it has to be in 'Settings and Privacy'...but where? We've tried 'Browser', and that's not it. It's not 'Content Preferences'...maybe 'Media'? Worth a shot..." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 524067" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-2.png" alt="Ok, it has to be in 'Settings and Privacy'...but where? We've tried 'Browser', and that's not it. It's not 'Content Preferences'...maybe 'Media'? Worth a shot..." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 524067" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-tab-3.png" alt="Ok, it has to be in 'Settings and Privacy'...but where? We've tried 'Browser', and that's not it. It's not 'Content Preferences'...maybe 'Media'? Worth a shot..." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Ok, it has to be in 'Settings and Privacy'...but where? We've tried 'Browser', and that's not it. It's not 'Content Preferences'...maybe 'Media'? Worth a shot...          </figcaption>        </figure><p></p>
<p></p><figure class="up three">          <picture style="--lqip: 522075" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media.png" alt="I'm sorry...what? Are you actually kidding? The option is hidden two levels deep, not in the 'Browser' section, but in 'Media', and you have to scroll to get to it?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 491355" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-2.png" alt="I'm sorry...what? Are you actually kidding? The option is hidden two levels deep, not in the 'Browser' section, but in 'Media', and you have to scroll to get to it?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 491355" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-3.png" alt="I'm sorry...what? Are you actually kidding? The option is hidden two levels deep, not in the 'Browser' section, but in 'Media', and you have to scroll to get to it?" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          I'm sorry...what? Are you actually kidding? The option is hidden two levels deep, not in the 'Browser' section, but in 'Media', and you have to scroll to get to it?          </figcaption>        </figure><p></p>
<p></p><figure class="up one">          <picture style="--lqip: 491355" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-media-4.png" alt="Bewildering placement" style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Be honest: would you think to look in:<br />&quot;Menu&quot; &gt; &quot;Settings &amp; privacy&quot; &gt;<br />&quot;Settings&quot; &gt; [ scroll to &quot;Preferences&quot; ] &gt;<br />&quot;Media&quot; &gt; [ scroll to bottom ] &gt;<br />&quot;Open links in external browser&quot;?          </figcaption>        </figure><p></p>
<p>This goat rodeo is wilfully obtuse in a way that only an organisation dedicated through-and-through to A/B testing can accomplish. You might very well think that Facebook is working hard to trick users into a knockoff browser in the hopes they don't notice.</p>
<p>Even without assuming intentional obfuscation, it is shocking how laughably incomplete the privacy and security settings of Facebook's <abbr title="In-App Browser">IAB</abbr> remain, more than a dozen years after it was introduced:</p>
<p></p><figure class="seventy_wide"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/settings-and-privacy-browser-settings.png" alt="Facebook's IAB fails to provide standard security, privacy, and accessibility settings. This single page is the entire set of available configuration options, and they are not sync'd." style="aspect-ratio: 1080 / 2408" class="seventy_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Facebook's <abbr title="In-App Browser">IAB</abbr> fails to provide standard security, privacy, and accessibility settings. This single page is the entire set of available configuration options, and they are not sync'd.</figcaption>      </figure><p></p>
<p>An identical thicket of pain awaits anyone trying to disable the Facebook <abbr title="In-App Browser">IAB</abbr> on iOS. Facebook's UI is screen-for-screen the same across mobile OSes, and iOS users enjoy no advantage in finding the settings to disable <abbr title="Facebook">FB</abbr>'s <abbr title="In-App Browser">IAB</abbr>.</p>
<p>Chrome and Edge's sync'd settings are vast by comparison, as are the offerings from every other responsible browser vendor:</p>
<p></p><figure class="up three">          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page.png" alt="Firefox for Android has such detailed settings that users have to scroll twice to see just the top-level entry points. The 'Privacy and Security' section alone offers as many options as all of FB's IAB." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-2.png" alt="Firefox for Android has such detailed settings that users have to scroll twice to see just the top-level entry points. The 'Privacy and Security' section alone offers as many options as all of FB's IAB." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/ff-android-settings-page-3.png" alt="Firefox for Android has such detailed settings that users have to scroll twice to see just the top-level entry points. The 'Privacy and Security' section alone offers as many options as all of FB's IAB." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Firefox for Android has such detailed settings that users have to scroll twice to see just the top-level entry points. The 'Privacy and Security' section alone offers as many options as all of <abbr title="Facebook">FB</abbr>'s <abbr title="In-App Browser">IAB</abbr>.          </figcaption>        </figure><p></p>
<p></p><figure class="up two">          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings.png" alt="Opera is similarly flexible and settings follow logged-in users through sync." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/opera-settings-2.png" alt="Opera is similarly flexible and settings follow logged-in users through sync." style="aspect-ratio: 1080 / 2408" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>          Opera is similarly flexible and settings follow logged-in users through sync.          </figcaption>        </figure><p></p>
<p>The difficulty in disabling Facebook's <abbr title="In-App Browser">IAB</abbr>, failure to synchronize opt-out choices, and a crippled privacy features are calculated to enable maximum tracking when tapping links. Even when Apple's vaunted <em>&quot;App Tracking Transparency&quot;</em> is enabled:</p>
<p></p><figure class="up one">          <picture style="--lqip: 172707" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/fb-ios-att-dialog.png" alt="" style="aspect-ratio: 1668 / 1494" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>            App Tracking Transparency was enabled, yet Facebook's <abbr title="In-App Browser">IAB</abbr> continues to be invoked when tapping on links. The <abbr title="In-App Browser">IAB</abbr> was also disabled on the same account via another device within the hour, showing that Facebook disregards privacy settings when it suits them.          </figcaption>        </figure><p></p>
<p>Here are the results of the EFF's <a href="https://coveryourtracks.eff.org/">&quot;Cover Your Tracks&quot;</a> testing tool on (left-to-right) the iOS Facebook <abbr title="In-App Browser">IAB</abbr>, Firefox Focus, and the DuckDuckGo browser, all with default settings under iPadOS 17.7.10:</p>
<p></p><figure class="up three">          <picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-fb-iab.png" alt="FB's IAB scores worst of all" style="aspect-ratio: 1668 / 2224" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: 10979" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ff-focus.png" alt="FB's IAB scores worst of all" style="aspect-ratio: 1668 / 2224" class="preview" decoding="async" loading="lazy" />      </picture>          <picture style="--lqip: -349469" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/fb-iab-opt-out/cyt-ddg.png" alt="FB's IAB scores worst of all" style="aspect-ratio: 1668 / 2224" class="preview" decoding="async" loading="lazy" />      </picture>                    <figcaption>            Facebook's <abbr title="In-App Browser">IAB</abbr> reports 'some protection' with 'some gaps', leaking a unique fingerprint, while both Firefox Focus and DuckDuckGo do better, featuring 'strong protection', despite using exactly the same browser engine under the hood, as Apple (unfairly) requires.          </figcaption>        </figure><p></p>
<p>Users that install browsers, configure them to preserve their privacy, then use Facebook app's after selecting <em>&quot;Ask App Not to Track&quot;</em> are reliably sold up the river by Apple, who seem content to facilitate this end-run around the rules.</p>
<p>Privacy settings? Gone. Extensions? Poof! And because Facebook has code on every top site, the tracking suddenly roars back to life, out of band of the channels that Apple wants you to believe are important (or at least that it has taken heat for in the past).</p>
<p><abbr title="Facebook">FB</abbr>'s tracking is so pervasive in modern web pages that it doesn't need to exfiltrate data from the <abbr title="In-App Browser">IAB</abbr> to track you. It just needs to keep you away from your real browser, where it might not be able to join up clicks and taps.</p>
<p>It isn't exactly clear if the <abbr title="In-App Browser">IAB</abbr> is the basis for <a href="https://on.ft.com/4lIHyJ6">recent reports of secretive &quot;deterministic matching&quot;</a> efforts, but it's safe to assume that Facebook's bullheaded determination to steal clicks and deny users their choice in browsers isn't simply an oversight.</p>
<h2 id="apple-knows" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#apple-knows">Apple Knows</a></h2>
<p>None of this is news to Apple. <a href="https://infrequently.org/2021/07/hobsons-browser/#minimal-interventions">They have read the posts</a> and have <a href="https://webkit.org/blog/10882/app-bound-domains/">made timid interventions</a> to avoid being blamed for the most obviously nasty versions of <abbr title="In-App Browser">IAB</abbr> tracking. But acting against the deep rot? No joy.</p>
<p>Not only has Apple not responded to <a href="https://open-web-advocacy.org/blog/in-app-browsers-the-worst-erosion-of-user-choice-you-havent-heard-of/">advocacy on behalf of users</a> from groups like <a href="https://open-web-advocacy.org/"><abbr title="Open Web Advocacy">OWA</abbr></a>, it has failed to impose either common-sense, pro-privacy restrictions on <abbr title="In-App Browsers">IABs</abbr>, or to support action by regulators. As we've seen above, it doesn't even require apps to avoid privacy-degrading <abbr title="In-App Browsers">IABs</abbr> when <abbr title="App Tracking Transparency">ATT</abbr> is enabled or provide a global opt-out.</p>
<p>And Apple is absolutely aware of these concerns because they have been raised publicly and in regulatory circles for years. Yet it does not act.</p>
<p>Why?</p>
<p>Facebook's dark patterns are directly facilitated by Apple and Google. It is their SDKs and policies that make this not only possible, but pervasive. So why do they deliver users unto perdition?</p>
<p>Denying users true browser choice helps keep the big app vendors in the store. Those whales understand that native APIs offer increased data collection, which they monetize.</p>
<p>Keeping big fish in the store, in turn, helps Apple and Google corral others into their API enclosure ghettos. If users know that to get their &quot;main&quot; apps, they must go to the store, then the store becomes the place to look for all software. Moreover, for competitors to have any hope of equivalent profits, they must enter the same Store-enabled race to the privacy bottom.</p>
<p>And that race to the bottom helps the duopolists, no matter how much they want you to believe otherwise.</p>
<p>Apple and Google are trying to maintain a distribution model chokehold over mobile software. Their duopoly allows them to tax developers outrageously for access to commodity APIs. Dependence on proprietary versions of bog-stock APIs, in turn, makes it hard for software vendors to consider building for other platforms with their limited engineering budgets.</p>
<p>This, not coincidentally, reduces the size of the (potentially) portable software catalogue, harming the prospects of new entrants that might challenge the duopoly. For users, a lack of apps in open ecosystems make it hard to escape for less predatory alternatives.</p>
<p>The entire point of the multi-layered exercise, in the end, is to subvert interoperability. And to do <em>that</em>, it's necessary to keep the anchor apps happy. Which is why Apple and Google let Facebook spy on you via through the web.</p>
<p>Apple isn't defending your privacy, it's retreating just far enough into the hedge that you won't notice the App Store dangling Facebook, Messenger, Instagram, and TikTok to take the blame for the APIs that Apple itself has recklessly provided. Compared to the web, iOS native apps have facilitated a universe of privacy invasion that was previously unthinkable. Apple <em>did that</em>, and <em>continues to do that</em>, and now it wants credit for forcing developers to &quot;comply&quot; (<em>wink wink</em>) with anti-tracking rules it can't be bothered to enforce.</p>
<p>The answer is blindingly obvious: forbid <abbr title="In-App Browsers">IABs</abbr>, particularly under <abbr title="App Tracking Transparency">ATT</abbr>, and/or force native apps to use the system-provided browser-overlay systems — <a href="https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller"><code>SFSafariViewController</code></a> and <a href="https://developer.chrome.com/docs/android/custom-tabs">Android Custom Tabs</a> — where user's choice of browser and customisations will be respected.</p>
<p>This isn't hard. In fact, it's one of the simplest interventions possible. And yet neither Apple nor Google are willing to pick a real fight with Facebook and do right by users.</p>
<p>And until they do, you can be certain the privacy preening is all for show.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fn-the-only-solution-worth-a-damn-4" id="fnref-the-only-solution-worth-a-damn-4">4</a></sup></p>
<aside class="thanks">
<p><em>This post is an edited and expanded version of <a href="https://toot.cafe/@slightlyoff/115079820070441051">a Mastodon thread.</a> Thanks to folks who asked probing questions about the situation there.</em></p>
</aside>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-not-calling-it-that-1" class="footnote-item"><p>I will continue to refer to Facebook as &quot;Facebook&quot; and Twitter as &quot;Twitter&quot; despite their sweaty, grasping rebrands.</p>
<p>It is an act of complicity to assist folks this guilty in turning the page on their transgressions. Using their new names helps oligarchs who retain standing through collective amnesia by disconnecting what is from what was, and they know it. Which is why they tried to rebrand in the first place.</p>
<p>The US legal fiction of &quot;corporate personhood&quot; does not entitle that corporation to respect. As a corporation's feelings cannot be hurt, either because it has none, or because it is a sociopath (as the market demands). If a billionaire is so embarrassed of their monster that they long for its rebirth it, I say fine; go ahead. I'll happily call it something else, just so long as it dies first. Liquidate the assets, pay your bloody taxes, fire everyone, put the winnings into a holding LLC, then start afresh. Then I'll call the new thing whatever they please.</p>
<p>Never deadname a trans person, but the pet amphisbaenas of billionares? Always and forever. <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fnref-not-calling-it-that-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-kayfabe-for-now-2" class="footnote-item"><p><a href="https://mobiledevmemo.com/apple-robbed-the-mobs-bank-part-2/">At least until Apple can wrestle away Facebook's ad business for itself.</a> <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fnref-kayfabe-for-now-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-biggest-tell-3" class="footnote-item"><p>A reliable measure of a tech firm's disrespect is making users frequently re-select privacy-enhancing choices. A good proxy for this is which settings are sync'd. Chrome's disregard for choices which Google dislikes is evident when logging into each new device:</p>
<p></p><figure><picture style="--lqip: 310627" class="preview">      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/chrome-new-device-who-dis.avif" alt="Every time a user visits settings on a new device, they're obliquely informed that the settings they laboriously configured on previous devices have been disregarded." style="aspect-ratio: 1819 / 1392" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Every time a user visits settings on a new device, they're obliquely informed that the settings they laboriously configured on previous devices have been disregarded.</figcaption>      </figure><p></p>
<p></p><figure><picture style="--lqip: 92899" class="preview">      <img src="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/chrome-new-device-ads.avif" alt="Chrome settings after verifying that sync has completed for the profile." style="aspect-ratio: 1689 / 711" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Chrome settings after verifying that sync has completed for the profile.</figcaption>      </figure><p></p>
<p>All of this has been carefully considered, and it is exceedingly likely that Figma mocks exist for versions that respect user choices. Those designs were not put into production. It's impossible to know from the outside exctly who made the call, but it's a reliable guess that the ads team won a Product Manager cage match.</p>
<p>Facebook, for its part, is even worse, failing to join up browser choice settings on any surface or across apps. Hardly a surprise, but in a world where almost every other setting is synchronised, the difference is confirmation of anti-user intent. <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fnref-the-biggest-tell-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-only-solution-worth-a-damn-4" class="footnote-item"><p>It should go without saying that the only truly effective solutions in this space will be legislative and regulatory. That neither Apple nor Google have put their aggressive lobbying teams to work to get effective privacy laws passed should also be a warning flag.</p>
<p>Until and unless they're willing to put the same sorts of money behind drafting model legislation and donating to the coffers of electeds via proxies that they do to degrade right-to-repair and browser engine choice, it's all kayfabe. <a href="https://infrequently.org/2025/08/apple-vs-fb-kayfabe/#fnref-the-only-solution-worth-a-damn-4" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Put Names and Dates On Documents</title>
    <link href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/"/>
    <updated>2025-08-13T00:00:00Z</updated>
    <id>https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/</id>
    <content type="html"><![CDATA[
      <!-- LTeX: language=en-GB -->
<p>Anyone who has worked closely with me, or followed on social media [<span style="font-family: share-button-combined; font-size: 0.9rem;"><a href="https://toot.cafe/@slightlyoff"></a>, <a href="https://bsky.app/profile/infrequently.org"></a></span>], will have seen a post or comment to the effect of:</p>
<blockquote>
<p>Names and dates on docs. Every time. Don't forget.</p>
</blockquote>
<p>This is most often tacked onto design documents lacking inline attribution, and is phrased provocatively to make it sticky.</p>
<p>Why do I care enough about this to be prescriptive — bordering on pushy — when colleagues accuse me of being Socratic to a fault about everything else? Because not only is unattributed writing a reliable time-waster, the careers of authors hang in the balance.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#weighing-up-inline-attribution">Weighing Up Inline Attribution</a><ul><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#readability">&quot;These blocks detract from readability.&quot;</a></li><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#edit-logs">&quot;There's already an edit log.&quot;</a></li><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#small-teams">&quot;Our team is small.</a></li><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#contribution-ellision">&quot;Specifying an author elides the contributions of collaborators.&quot;</a></li></ul></li><li><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#minimum-viable-attribution">Minimum Viable Attribution</a></li></ul></nav>
<p>Having to work to find the best person to discuss a topic with is annoying, but in large organisations, the probability of authors having work appropriated without credit goes up when they fail to claim ownership of their writing. It should go without saying that this is toxic, and that functional engineering cultures look harshly on it. But to ward off bad behaviour, it helps to model what's healthy.</p>
<p>The best reminder to cite work is for authors to name themselves. Doing this increases their stature, unsubtly encourages others to link and cite, and leaves a trail of evidence for authors to reference when building a case for promotion.</p>
<p>The importance of evidence to support claims of design work in technical fields cannot be overstated. Having served on hiring and promotion committees for many years, I can unequivocally say that this collateral is often pivotal. The difference between <code>&quot;[x] promote&quot;</code> and <code>&quot;[x] do not promote&quot;</code> often comes down to the names on documents. Reviewers will pay attention to both the authors list and the propensity of design doc authors to cite others.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#fn-selfish-docs-are-a-tell-1" id="fnref-selfish-docs-are-a-tell-1">1</a></sup></p>
<h2 id="weighing-up-inline-attribution" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#weighing-up-inline-attribution">Weighing Up Inline Attribution</a></h2>
<p>In response to unsubtle nudges, several recurring arguments are offered against explicit authorship notices.</p>
<h3 id="readability" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#readability"><em>&quot;These blocks detract from readability.&quot;</em></a></h3>
<p>This is fair, but does not outweigh the needs of future readers who may be working to trace a chain of events or ideas. Nor does it outweigh the needs of authors for credit regarding their work at a future date.</p>
<h3 id="edit-logs" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#edit-logs"><em>&quot;There's already an edit log.&quot;</em></a></h3>
<p>This crutch fails in any number of ways:</p>
<ul>
<li>PDFs and printed copies do not include authorship data that is not in body text.</li>
<li>Some systems (e.g. Google Docs) do not make the history available to non-editors.</li>
<li>Documents may be copied or re-published in ways that disconnect the content from the original revision tracking system; e.g., in a systems transition as part of an acquisition.</li>
</ul>
<p>Moreover, design is a complex and collaborative process. Ideas and concepts captured in documents are not always the contribution of the person writing down the conclusions of a whiteboarding session. A clear, consistent way to give credit helps everyone feel included and encourages future collaboration.</p>
<h3 id="small-teams" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#small-teams"><em>&quot;Our team is small.</em></a></h3>
<p>This is usually offered as a claim of superfluousness. If everyone knows everything and everyone working in a system, why does attribution matter?</p>
<p>Perhaps a team is small now, but will it always be? I am not in a position to tell, and my interlocutors also lack crystal balls. Given the downside risks, attribution is a pittance of an insurance premium.</p>
<h3 id="contribution-ellision" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#contribution-ellision"><em>&quot;Specifying an author elides the contributions of collaborators.&quot;</em></a></h3>
<p>This is easily countered with invitations in comments and drafts for contributors to add themselves to the authorship section. Generous and collaborative folks — the sorts of people we want to promote — reliably add their collaborators to documents proactively and set the expectation that others will do the same. Over time, practice becomes habit, which crystallises into culture.</p>
<h2 id="minimum-viable-attribution" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#minimum-viable-attribution">Minimum Viable Attribution</a></h2>
<p>A final concern I hear is that these blocks require a great deal of upkeep. Long-form revision logs might be onerous, but the minimum viable attribution style only needs three elements: names, emails, and dates. These should be provided on the very first page, ideally just below the title.</p>
<p>The primary date always refers first drafting, even if that is before publication. If deemed necessary, authors can optionally add a <em>&quot;Last Updated&quot;</em> field below the primary date, but this is optional. Documents authored in a single sitting by a lone author should avoid extra visual noise.</p>
<p>Revision logs are generally unnecessary, and my personal view is that they distract from content; if they're a requirement (e.g., in a heavily regulated industry), record them in an Appendix, but do not remove minimum viable attributions.</p>
<p>Here's <a href="https://github.com/slightlyoff/local_font_access">a screenshot of an explainer I helped draft</a> many years ago showing the basic form<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#fn-email-etiquette-2" id="fnref-email-etiquette-2">2</a></sup>:</p>
<p></p><figure><picture style="--lqip: -174813" class="preview">      <img src="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/minimal-attribution.avif" alt="Minimum Viable Attribution in a Markdown document." style="aspect-ratio: 1490 / 388" class="preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>Minimum Viable Attribution in a Markdown document.</figcaption>      </figure><p></p>
<p>If a document is still an early draft, it can be helpful to put some indication in the title — I use a prefix like <em>&quot;<code>[ Draft ] ...</code>&quot;</em> — and invite collaborators to add themselves to the authors list by including an entry there of the form <em>&quot;<code>Your Name &lt;your_email@example.com&gt;</code>&quot;</em>. Once a document is circulated widely, remove these inline markers.</p>
<div style="font-size: 1rem;">
<p><em>Thanks to <a href="https://aluhrs.com/">Andy Luhrs</a> for his feedback on drafts of this post.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-selfish-docs-are-a-tell-1" class="footnote-item"><p>If you write technical design docs, it is <em>always</em> a good sign if you cite prior work and parallel efforts, including competing designs. Omitting those references is something that both technical and promotion reviewers are alert to and are primed to think poorly of. No design is entirely new, and it is a sign of maturity to give others their due. <a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#fnref-selfish-docs-are-a-tell-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-email-etiquette-2" class="footnote-item"><p>Don't worry, all of these email addresses are now inactive.</p>
<p>On the question of emails and spam in authoring public documents, views are split. I favour always using them, but understand if authors prefer other sorts of contact information; e.g., their personal website. Best not to be too fussy about this sort of thing, except to ensure that <em>internal</em> documents always contain email addresses. <a href="https://infrequently.org/2025/08/names-and-dates-on-docs-every-time/#fnref-email-etiquette-2" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>How Do Committees Fail To Invent?</title>
    <link href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/"/>
    <updated>2025-08-11T00:00:00Z</updated>
    <id>https://infrequently.org/2025/08/how-do-committees-fail-to-invent/</id>
    <content type="html"><![CDATA[
      <!-- LTeX: language=en-GB -->
<p>Mel Conway's seminal paper <a href="https://www.melconway.com/Home/pdf/committees.pdf">&quot;<em>How Do Committees Invent?</em>&quot; (PDF)</a> is commonly paraphrased as <a href="https://en.wikipedia.org/wiki/Conway%27s_law">Conway's Law</a>:</p>
<blockquote>
<p>Organizations which design systems are (broadly) constrained to produce designs which are copies of the communication structures of these organizations.</p>
</blockquote>
<p>This is deep organisational insight that engineering leaders ignore at their peril, and everyone who delivers code for a living benefits from a (re)read of <a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month"><em>&quot;The Mythical Man-Month&quot;</em></a>, available at <a href="https://bookshop.org/p/books/the-mythical-man-month-essays-on-software-engineering-anniversary-edition-frederick-brooks/9437212">fine retailers everywhere.</a></p>
<p>Conway's Law is generally invoked to describe organisations working to solve well-defined problems, in which everyone is working towards a solution. But what if there are defectors? And what if they can prevent forward progress without paying any price? This problem is rarely analysed for the simple reason that such an organisation would be <em>deranged.</em></p>
<p>But what if that happened regularly?</p>
<p>I was reminded of the possibility while chatting with a colleague joining a new (to them) Working Group at the <abbr title="World Wide Web Consortium">W3C</abbr>. The most cursed expressions of Conway's Law regularly occur in Standards Development Organisations (<abbr title="Standards Development Organisations">SDOs</abbr>); specifically, when delegates refuse to communicate their true intentions, either through spurious objection or tactical silence.</p>
<p>This special case is <em>the <a href="https://en.wikipedia.org/wiki/Fifth_column">fifth column</a> problem</em>.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#how-does-this-happen%3F">How Does This Happen?</a></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#mayfly-half-lives">Mayfly Half-Lives</a></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#the-web-platform's-power-structure">The Web Platform's Power Structure</a><ul><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#but-why%3F">But Why?</a></li></ul></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#problem-misstatements">Problem Misstatements</a><ul><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#closed-for-business">Closed For Business</a></li></ul></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#survivorship-bias-and-the-problem-of-big%2C-old-rooms">Survivorship Bias and The Problem of Big, Old Rooms</a></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#marketing-gridlock-as-thoughtfulness">Marketing Gridlock As Thoughtfulness</a><ul><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#when-is-a-%22consensus%22-not-consensus%3F">When Is A &quot;Consensus&quot; Not Consensus?</a></li></ul></li><li><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#defences-against-fifth-columns">Defences Against Fifth Columns</a></li></ul></nav>
<p>Expressed in Conwayist terms, <em>the fifth column problem</em> describes the way organisations mirror the miscommunication patterns of their participants when they fail to deliver designs of any sort. This pathology presents when the goal of the majority is antithetical to a small minority with a veto.</p>
<p>Reticence of certain <abbr title="Standards Development Organisation">SDO</abbr> participants to consider important problems is endemic, in part, due to open membership. Unlike corporate environments where alignment is at least partially top-down, the ability of any firm to join an <abbr title="Standards Development Organisation">SDO</abbr> practically invites subterfuge. This plays out calamitously when representatives of pivotal firms obfuscate their willingness to implement, or endlessly delay consideration of important designs.</p>
<p>Open membership alone would not lead to crisis, except that certain working groups adopt rules or norms that create an explosion of <a href="https://en.wikipedia.org/wiki/Veto_Players"><em>veto players</em></a>.</p>
<p>These veto-happy environments combine with bad information to transmute opaque communication into arterial blockage. <abbr title="Standards Development Organisation">SDO</abbr> torpidity, in turn, colours the perception of web developers against standards. And who's to say they're wrong? Bemoaning phlegmatic working groups is only so cathartic.</p>
<p>Eventually, code must ship, and if important features are missing from standards-based platforms, it becomes inevitable that developers will decamp to proprietary solutions.</p>
<p>Instances of the fifth column problem are frequently raised to me by engineers working in these groups. <em>&quot;How,&quot;</em> they ask, <em>&quot;can large gatherings of engineers meet regularly, accomplish next-to-nothing, yet continue pat themselves on the back?&quot;</em></p>
<p>The sad answer is <em>&quot;quite easily.&quot;</em></p>
<p>This dynamic has recurred with surprising regularity over the web's history,<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-failure-epochs-1" id="fnref-failure-epochs-1">1</a></sup> and preventing it from clogging the works is critical to the good order of the entire system.</p>
<h2 id="how-does-this-happen%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#how-does-this-happen%3F">How Does This Happen?</a></h2>
<p>The primary mechanism that produces consequential fifth column episodes is internal competition within tech giants.</p>
<p>Because the web is a platform, and because <a href="https://infrequently.org/2024/10/platforms-are-competitions/">platforms are competitions,</a> it's natural that companies that make both browsers and proprietary platforms favour their owned-and-operated offerings.</p>
<p>The rent extraction opportunities from controlling OS APIs are much more lucrative than an open ecosystem's direct competition. Decisions about closed platforms also do not have to consider other players as potential collaborators. Strategically speaking, managing a proprietary platform is playing on easy mode. When that isn't possible, the web can provide a <a href="https://infrequently.org/2024/03/why-browsers-get-built/">powerful bridge</a> to the temporarily embarrassed monopolist, but that is never their preference.</p>
<p>This competition is often hard to see because the decisive battles between proprietary systems and open platforms are fought behind the tallest, most heavily guarded walls of tech giants: budget planning.</p>
<p>Because budgets are secret, news of the web losing status is also a secret. It's a firing offence to leak budget details, or even share internally to those without a need to know, so line engineers may never be explicitly told that their mission has fundamentally changed. They can experience transitions away from the web as <em>&quot;Plan A&quot;</em> to <em>&quot;Plan Z&quot;</em> without their day-to-day changing much. The team just stops growing, and different types of features get priority.</p>
<p>OS vendors that walk away from the web after it has served their businesses can simply freeze browser teams, trimming ambitions around the edges without even telling the team that their status has been lowered. Capping and diverting funding away from new capabilities is easily explained; iteration on existing, non-threatening features is important, after all, and there are always benchmarks to optimise for.</p>
<p>Most fifth columnists are, therefore, unwitting and unknowing accomplices to corporate machinations well above their own pay grades. They cannot acknowledge that a vibrant web is not valuable to their firm because they will have never been told as much, and should they enquire, will hear only that the important work they are doing continues to be valued.</p>
<h2 id="mayfly-half-lives" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#mayfly-half-lives">Mayfly Half-Lives</a></h2>
<p>Until recently, the impact of fifth column tactics was obscured in a haze of legacy engines. Web developers take universality seriously, so improvements in capabilities have historically been experienced as the rate at which legacy UAs fall below a nominal relevance threshold.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-blocking-share-2" id="fnref-blocking-share-2">2</a></sup> Thanks to pervasive auto-updates, the historical problem of dead-code-walking has largely been resolved. Major versions of important browsers may have entire cradle-to-grave lifecycles on the order of two or three months, rather than <abbr title="Internet Explorer">IE</abbr> 6's half-decade half-life.</p>
<p>This has clarified the impact of (dis)investments by certain vendors and makes fifth columnists easier to spot. Web developers now benefit from, or are held back by, recent decisions by the companies (under)funding browser development. If sites remain unable to use features launched in leading-edge engines, it's only because of deficiencies in recent versions of competing engines. This is a much easier gap to close — in theory, anyway.</p>
<h2 id="the-web-platform's-power-structure" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#the-web-platform's-power-structure">The Web Platform's Power Structure</a></h2>
<p>Web standards are <a href="https://open-stand.org/about-us/principles/#:~:text=5.%20Voluntary%20Adoption"><em>voluntary</em>,</a> and the <a href="https://standards.ieee.org/wp-content/uploads/2022/02/antitrust.pdf">legal structures that create <abbr title="Standards Development Organisation">SDO</abbr> safe-harbours (PDF)</a> create the space in, and rules under, which <abbr title="Standards Development Organisations">SDOs</abbr> must operate. <abbr title="Standards Development Organisations">SDOs</abbr> may find their designs written into legislation after the fact, or as implementation guides, but there is a strong aversion to being told what to design by governments within the web community, particularly among implementers. Some new participants in standards arrive with the expectation that the <em>de jure</em> nature of a formal standard creates a requirement for implementation, but nothing could be further from fact. This sometimes leads to <a href="https://infrequently.org/2018/06/effective-standards-work-part-2-threading-the-needle/">great frustration</a>. Enshrining a design in a ratified standard does not obligate anyone to do anything, and many volumes of pure <em>specifiction</em> have been issued to little effect.</p>
<p>The voluntary nature of web standards is based on the autonomy of browsers, servers, and web developers to implement whatever they please under own brand.</p>
<p>Until <a href="https://infrequently.org/series/browser-choice-must-matter/">Apple's flagrantly anticompetitive iOS policies,</a> this right was inviolable because, when compromised, erosions of feature sovereignty undermine the premise of <abbr title="Standards Development Organisations">SDOs</abbr>.</p>
<p><strong>When products lose the ability to differentiate on features, quality, performance, safety, and standards conformance, the market logic underpinning voluntary standards becomes a dead letter.</strong> There's no reason to propose an improvement to the collective body of the web when another party can prevent you from winning share by supporting that feature.</p>
<p>The harms of implementation compellence are proportional to market influence. iOS's monopoly on the pockets of the wealthy (read: influential) has decisively undermined the logic of the open internet and the browser market. Not coincidentally, this has also desolated the prospect of a thriving mobile web.</p>
<p><lite-vimeo videoid="364402896" videotitle="The Mobile Web: MIA">        <a href="http://vimeo.com/364402896">The Mobile Web: MIA</a>      </lite-vimeo></p>
<p>It's no exaggeration to say that it is <em>anti-web</em> to constrain which standards vendors can implement within their browsers, and implementation coercion is antithetical to the good functioning of <abbr title="Standards Development Organisations">SDOs</abbr> and the broader web ecosystem.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-w3c-as-hostage-3" id="fnref-w3c-as-hostage-3">3</a></sup></p>
<p>In a perverse way, Apple's <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">policy predations,</a> <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-u-turns-1">strategic under-investment,</a> and <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">abusive incompetence</a> clarify the basic terms of the web's power structure: <abbr title="Standards Development Organisations">SDOs</abbr> are downstream of browser competition, and browser competition depends on open operating systems.</p>
<h3 id="but-why%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#but-why%3F">But Why?</a></h3>
<p>Why do vendors spend time and money to work in standards, only to give away their IP in the form of patent licences covering ratified documents?</p>
<p>When vendors enjoy product autonomy, they develop standards to increase interoperability at the behest of customers who dislike lock-in. Standards also lower vendor's legal risk through joint licensing, and increase marketability of their products. Behind this nondescript summary often lies a furious battle for market share between bitter competitors, and standards development is famous for playing a subtle role. <a href="https://faculty.haas.berkeley.edu/shapiro/wars.pdf">Shapiro and Varian's classic paper <em>&quot;The Art of Standards Wars&quot;</em> (PDF)</a> is a quarter-century old now, but its description of these sorts of battles is no less relevant today that it was in '99.</p>
<p>Like this classic, most discussions of standards battles highlight parties with differing visions but similar goals — should <code>margin-sizing</code> or <code>border-sizing</code> be the default? — rather than situations where one vendor has a proprietary agenda and wishes to grow or maintain a <a href="https://infrequently.org/2020/06/platform-adjacency-theory/#katamari-capability">capability gap versus standards-based alternatives.</a> Denying features to open ecosystems makes high-tax proprietary platforms more attractive, and gridlock in standards is an effective strategy for accomplishing it. These cases are under-discussed, in part, because they're hard to perceive over short time periods or by observing a single working group.</p>
<p>Parties that maintain a footprint in standards, but are unhappy to see standards-based platforms compete with their proprietary offerings, only need <a href="https://www.cia.gov/static/5c875f3ec660e092cf893f60b4a288df/SimpleSabotage.pdf">a few pages from the Simple Sabotage manual (PDF).</a></p>
<p>Often, they will send delegates to important groups and take visible leadership positions. Combined with <em>juuuuuust</em> enough constructive technical engagement, obstreperous parties scarcely have to say anything about their intent. Others will raise their own hopes, and cite (tepid) participation as evidence of good faith. The fifth columnist doesn't need to raise a finger, which is handy, as doing nothing is the goal.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-big-blue-4" id="fnref-big-blue-4">4</a></sup></p>
<h2 id="problem-misstatements" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#problem-misstatements">Problem Misstatements</a></h2>
<p>Working group composition also favours delays at the hands of fifth columnists. Encouraged by defectors, they regularly divert focus from important problems, instead spending huge amounts of time on trivialities because few customers (web developers) have the time, money, and energy to represent their own needs in committee. Without those voices, it's hard to keep things on track.</p>
<p>Worse, web developers generally lack an understanding of browser implementation details and don't intone the linguistic airs and shorthands of committeespeak, which vary from venue to venue. This hampers their ability to be taken seriously if they do attend. At the limit, dismissing pressing problems on technicalities can become something of a committee pastime.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-as-days-go-by-5" id="fnref-as-days-go-by-5">5</a></sup></p>
<p>There's also a great deal of opportunity for fifth columnists to misrepresent the clearly stated needs of web developers, launching projects to solve adjacent (but unimportant) sub-issues, while failing to address the issues of the day. This is particularly problematic in big, old rooms.</p>
<p>A competent fifth columnist only needs to signal in-group membership to amplify the impact of their own disinterest in topics they would prefer to avoid. Ambiguous &quot;concerns&quot; and scary sounding caveats are raised, and oven-ready designs which <em>do</em> arrive are reframed as naive proposals by outsiders. Process-level critique, in lieu of discussing substance, is the final line of defence.</p>
<p>Deflecting important work is shockingly easy to pull off because organisations that wish to defeat progress can send delegates that can appeal to rooms full of C++/Rust engineers as peers. The tripwires in web API design are not obvious to the uninitiated, so it's easy to move entire areas of design off the agenda through critique of small details.</p>
<p>The most depressing thing about this pattern is that these tactics work <em>because other vendors allow it</em>.</p>
<h3 id="closed-for-business" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#closed-for-business">Closed For Business</a></h3>
<p>One problem facing new areas in standards is that chartered Working Groups are just that: chartered. They have to define what they will deliver years in advance, and anything not on the agenda is, by definition, not in scope. The window in many <abbr title="Standards Development Organisation">SDO</abbr> processes for putting something new into the hopper is both short and biased towards small revisions of the existing features. Spinning up new Working Groups is a huge effort that requires political clout.</p>
<p>Technically, this is a <em>feature</em> of <abbr title="Standards Development Organisations">SDOs</abbr>; they jointly licence the IP of members to reduce risks to implementers and customers of adopting standards-based products. Patent trolls have to consider the mutual defences of the whole group's membership and cannot easily pick off smaller prey. Most developers never give a second thought to patent portfolios and do not live in fear of being personally sued for infringement.</p>
<p>This is a sign web standards are a smashing success, but also makes it unlikely that working developers understand that standards processes are designed with bounded IP commitments in mind. Internet <abbr title="Standards Development Organisations">SDOs</abbr> have been so successful at caging the beast that generations of developers have never considered the threat or how it intersects with their interests.</p>
<p>This creates a tension: over the long term, <abbr title="Standards Development Organisations">SDOs</abbr> and the ecosystems can only succeed if they take on new problems that are <a href="https://infrequently.org/2020/06/platform-adjacency-theory/#katamari-capability">adjacent</a> to the current set, but the Working Groups they create are primed by their composition and history to avoid taking on substantial expansions of their scope. After all, a good v2 of a spec is one that fixes all the problems of v1 and introduces relatively few new ones.</p>
<p>To work around this restriction, functional <abbr title="Standards Development Organisations">SDOs</abbr> create incubation venues. These take different guises, but the core features are the same. Unlike chartered Working Groups, incubation groups are simple to create; no charter votes or large, up-front IP commitments. They also feature low bars to participation, can be easily shut down, and do not produce documents for formal standardisation, although they can produce &quot;Notes&quot; or other specification documents that Working Groups can take up.</p>
<p>Instead, they tend to have substantial contributor-only grants of IP, ad-hoc meeting and internal debate mechanisms, and attract only those interested in working on solutions in a new problem space. In functioning <abbr title="Standards Development Organisations">SDOs</abbr>, such &quot;fail-fast&quot; groups naturally become feeders for chartered Working Groups, iterating on problems and solutions at a rate which is not possible under the plodding bureaucracy of a chartered Working Groups's minuted and agenda-driven meeting cadence.</p>
<p>And that's why these sorts of groups are a first priority for sabotage by fifth columnists. The usual tactics deployed to subvert incubation include:</p>
<ul>
<li>Aspersions of bad faith by those working in incubation venues, either on the grounds that the groups are <em>&quot;amateur&quot;</em>, <em>&quot;not standards-track&quot;</em>,<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-tracking-6" id="fnref-tracking-6">6</a></sup> or <em>&quot;do not have the right people.&quot;</em></li>
<li>Avoidance of engagement in incubation groups, robbing them of timely feedback while creating a self-fulfilling <em>&quot;lack of expertise&quot;</em> critique.</li>
<li>Citing a high fraction failed designs within these groups as an indicator that they are not useful, obscuring the reality that the entire point of incubation is to fail fast and iterate furiously.<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-furious-intensity-7" id="fnref-furious-intensity-7">7</a></sup></li>
<li>Accuse those who implement incubated proposals of <em>&quot;not following the process&quot;</em>, <em>&quot;ignoring standards&quot;</em>, or <em>&quot;shipping whatever they want&quot;</em>; twisting the goals of those doing design in the open, in good faith, under the <abbr title="Standards Development Organisation">SDO</abbr>'s IP umbrella.</li>
<li>Demanding formalities akin to chartered Working Groups to slow the pace of design progress in incubation venues that are too successful to ignore.</li>
</ul>
<p>The fifth columnist also works behind the scenes to reduce the standing and reputation of incubation groups among the <abbr title="Standards Development Organisation">SDO</abbr>'s grandees, claiming that they represent a threat to the stability of the overall organisation. Because that constituency is largely divorced from the sausage-making, this sort of treachery works more often than it should, causing those who want to solve problems to burn time defending the existence of venues where real progress is being made.</p>
<h2 id="survivorship-bias-and-the-problem-of-big%2C-old-rooms" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#survivorship-bias-and-the-problem-of-big%2C-old-rooms">Survivorship Bias and The Problem of Big, Old Rooms</a></h2>
<p>The picture presented this far is of Working Groups meeting in <a href="https://strangerthings.fandom.com/wiki/The_Upside_Down">The Upside Down.</a> After all, it's only web developers who can provide a real test of a design, or even the legitimacy of a problem.</p>
<p>This problem becomes endemic in many groups, and entire <abbr title="Standards Development Organisations">SDOs</abbr> can become captured by the internal dramas and preferences of implementers, effectively locking customers out. Without more dynamic, fail-fast forums that enable coalitions of the willing to design and ship around obstructionists, working groups can lay exclusive claim to important technologies and retreat into irrelevance without paying a reputational cost.</p>
<p>The alternative — hard forking specifications — is a nuclear option. The fallout can easily blow back into the camp of those launching a fork, and the effort involved is stupendous. Given the limited near-term upside and unclear results, few are brave or foolish enough to consider forking to route around a single intransigent party.</p>
<p>This feeds the eclipse of an <abbr title="Standards Development Organisation">SDO</abbr>'s relevance because legitimacy deficits become toxic to the host only slowly. Risk of obsolescence can creep unnoticed until it's too late. As long as the ancient forms and traditions are followed, a decade or more can pass before the fecklessness of an important group rises to the notice of anyone with the power to provoke change. All the while, external observers will wonder why they must resort to increasingly tall piles of workarounds and transpilers. Some may even come to view deadening stasis, incompatibility, and waste as the natural state of affairs, declining to invest any further hope for change in the work of <abbr title="Standards Development Organisations">SDOs</abbr>. At this point, the fifth columnist has won.</p>
<p>One of the self-renewing arrows in the fifth column's quiver is the tendency of large and old working groups to indulge in survivorship bias.</p>
<p>Logically, there's no reason why folks whose designs won a lottery in the last round of market jousting<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-master-debaters-8" id="fnref-master-debaters-8">8</a></sup> should be gatekeepers regarding the next tranche of features. Proposing winning designs in the past is not, in itself, a reliable credential. And yet, many of these folks become embedded within working groups, sometimes for decades, holding sway by dint of years of service and interpersonal capital. Experience <em>can</em> be helpful, but only when it is directed to constructive engagement, and too many group chairs allow bad behaviour, verging on incivility, at the hands of <em>la vieille garde.</em> This, of course, actively discourages new and important work, and instead clears the ground for yet more navel-gazing.</p>
<p>This sort of in-group/out-group formation is natural in some sense, and even folks who have loathed each other from across a succession of identically drab conference rooms for years can find a sort of camaraderie in it. But the social lives of habitual TPAC and TC39 attendees are no reason to accept unproductive monopolies on progress; particularly when the folks in those rooms become unwitting dupes of fifth columnists, defending the honour of the group against those assailing it for not doing enough.</p>
<p>The dysfunctions of this dynamic mirrors those of lightly moderated email lists: small rooms of people all trying to solve the same problem can be incredibly productive, no matter how open. Large rooms with high alignment of aims can make progress if leadership is evident (e.g., strong moderation). What is reliably toxic are large, open rooms with a mix of &quot;old timers&quot; who are never moderated and &quot;newbies&quot; who have no social standing. Without either a clear destination or any effective means of making decisions, these sorts of venues become vitriolic over even the slightest things. As applied to working groups, without healthy norms and strong chairing, interpersonal dynamics of long-standing groups can make a mockery of the responsibilities documented in a charter. But it's unusual for anyone on the outside to get any the wiser. Who has time to decipher meeting minutes or decode in-group shorthands?</p>
<p>And so it is precisely <em>because</em> fifth columnists can hire old timers<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-cheap-and-cheerful-9" id="fnref-cheap-and-cheerful-9">9</a></sup> that they are able to pivot groups away from addressing pressing concerns to the majority of the ecosystem, particularly in the absence of functional incubation venues challenging sclerotic groups to move faster.</p>
<h2 id="marketing-gridlock-as-thoughtfulness" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#marketing-gridlock-as-thoughtfulness">Marketing Gridlock As Thoughtfulness</a></h2>
<p>One useful lens for discussing the fifth column problem is the now-common Political Science analysis of systems through <a href="https://sites.lsa.umich.edu/tsebelis/wp-content/uploads/sites/246/2015/03/decision_making_in_political_systems_1995_bjps.pdf">&quot;veto points&quot; or &quot;veto players&quot; (Tsebelis, '95; PDF):</a></p>
<blockquote>
<p>Policy stability is different from both government stability and regime stability. In fact ... they are inversely related: policy stability causes government or regime instability. This analysis is based on the concept of the veto player in different institutional settings.</p>
</blockquote>
<p>If we substitute <em>&quot;capability stability&quot;</em> for <em>&quot;policy stability&quot;</em> and <em>&quot;platform relevance&quot;</em> for <em>&quot;government/regime stability,&quot;</em> the situation becomes clear:</p>
<blockquote>
<p>Capability stability is different from platform relevance. In fact ... they are inversely related: capability stability causes platform irrelevance.</p>
</blockquote>
<p>Any platform that cannot <a href="https://infrequently.org/2020/06/platform-adjacency-theory/#katamari-capability">grow to incorporate new capabilities,</a> or change to address pressing problems, eventually suffers irrelevance, then collapse. And the availability of veto points to players entirely hostile to the success of the platform is, therefore, an existential risk<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-capability-stability-is-not-back-compat-10" id="fnref-capability-stability-is-not-back-compat-10">10</a></sup> — both to the platform and to the <abbr title="Standards Development Organisations">SDOs</abbr> that standardise it, not to mention the careers of developers invested in the platform.</p>
<p>This isn't hard to understand, so how does the enterprising fifth columnist cover their tracks? By claiming that they are not <em>opposed</em> to proposals, but that they <em>&quot;need work,&quot;</em> without either offering to do that work, develop counter-proposals, or make any commitment to ship any version of proposals in their own products. This works too often because a pattern of practice must develop before participants can see that blockage is not a one-off rant by a passionate engineer.</p>
<p>Participants are given wide berths, both because of the presumption of voluntarity implementations,<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-voluntary-for-me-but-not-for-thee-11" id="fnref-voluntary-for-me-but-not-for-thee-11">11</a></sup> and the social attitudes of standards-inclined developers. Most <abbr title="Standards Development Organisation">SDO</abbr> participants are community-minded and collaboration-oriented. It's troubling to imagine that someone would show up to such a gathering without an intent to work to solve problems, as that would amount to bad faith. But it has recurred frequently enough that we must accept it does happen. Having accepted its possibility, <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-u-turns-1">we must learn to spot the signs, remain on guard, and call it out as evidence accumulates.</a></p>
<p>The meta-goal is to ensure no action for developers, with delay to the point of irrelevance as a fallback position, so it is essential to the veto wielder that this delay be viewed as desirable in some other dimension. If this sounds similar to <em>&quot;but neighbourhood character!&quot;</em> arguments by NIMBYs offer, that's no accident. Without a valid argument to forestall efforts to solve pressing problems, the fifth column must appeal to latent, second-order values that are generally accepted by the assembled to pre-empt the first-order concern. This works a shocking fraction of the time.</p>
<p>It works all the better in committees with a strong internal identity. It's much easier to claim that external developers demanding solutions <em>&quot;just don't get it&quot;</em> when the group already views their role as <a href="https://infrequently.org/2018/06/effective-standards-work-part-2-threading-the-needle/#:~:text=Structurally%2C%20it%20is,enter%20with%20credibility.">self-styled bulwarks against bad ideas.</a></p>
<h3 id="when-is-a-%22consensus%22-not-consensus%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#when-is-a-%22consensus%22-not-consensus%3F">When Is A &quot;Consensus&quot; Not Consensus?</a></h3>
<p>The final, most pernicious, building block of Working Group decay is the introduction of easy vetoes via consensus decision-making. When vetoes are available to anyone in a large group at many points, the set of proposals that can be offered without a presumption of failure shrinks to a tiny set, in line with the findings of Tsebelis.</p>
<p>This is not a new problem in standards development, but the language gets muddy. I perceive two distinct versions:</p>
<ul>
<li><strong>Strong Consensus</strong> refers to working modes in which the assent of every participant is affirmatively required to move proposals forward.</li>
<li><strong>Weak Consensus</strong> are modes in which preferences are polled, but &quot;the sense of the room&quot; can carry a proposal forward over even strenuous objections by small minorities.</li>
</ul>
<p>Every long-term functional <abbr title="Standards Development Organisation">SDO</abbr> operates by some version of Weak Consensus. The <abbr title="Internet Engineering Task Force">IETF</abbr> bandies this about so often that the phrase <a href="https://www.ietf.org/runningcode/"><em>&quot;rough consensus and running code&quot;</em></a> is synonymous with the organisation.</p>
<p>But not every group within these <abbr title="Standards Development Organisations">SDOs</abbr> are chaired by folks willing to overrule objectors. In these situations, groups can revert to <em>de facto</em> strong consensus, which greatly multiplies the number of veto holders. Variations on this theme can be even less disciplined, with only an old guard having effective veto power, whilst newer participants may be more easily overturned.</p>
<p>Strong consensus is the camel's nose for long-term gridlock. Like unmoderated mailing lists, things can spiral without anyone quite knowing where the error was made. Small groups can start under strong consensus out of a sense of mutual respect, only to find it is nearly impossible to revoke a veto power once handed out. A sense of fair play may cause this right to be extended to each new participant, and as groups grow, affiliations change, and interests naturally diverge, it may belatedly dawn on those interested in progress that the very rooms where they once had so much luck driving things forward have become utterly dysfunctional. And under identical rules!</p>
<p>Having found the group no longer functions, delegates who have invested large portions of their careers to these spaces have a choice: they can acknowledge that it is not working and demand change, becoming incredibly unpopular amongst their closest peers in the process. Or they can keep their heads down and hope for the best, defending the honour of the group against attacks by &quot;outsiders&quot;. Don't they know whose these people <em>are</em>?</p>
<p>Once it sets in, strong consensus modes are devilish to unpick, often requiring a changing of the guard, both among group chairs and influential veto-wielders. Groups can lose internal cohesion and technical expertise in the process, heaping disincentive to rock even the most unproductive boats.</p>
<h2 id="defences-against-fifth-columns" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#defences-against-fifth-columns">Defences Against Fifth Columns</a></h2>
<p>The ways that web ecosystem <abbr title="Standards Development Organisations">SDOs</abbr> and their participants can guard against embrittlement and fracture from the leeching effects of fifth columns are straightforward, if difficult to pull off socially:</p>
<ul>
<li>
<p><strong>Seek out and remove strong consensus processes.</strong></p>
<p>The timeless wisdom of weak consensus is generally prescribed by process documents governing <abbr title="Standards Development Organisations">SDOs</abbr>, so the usual challenge is enforcement. The difficulty in shaking strong consensus practices is frequently compounded by the status of influential individuals from important working groups who prefer it. Regardless, the consequences of allowing strong consensus to fester in rooms big enough to justify chairing is dire, and it must be eliminated root and branch.</p>
</li>
<li>
<p><strong>Aggressively encourage <em>&quot;counterproposal or GTFO&quot;</em> culture.</strong></p>
<p>Fifth columnists thrive in creating ambiguity for the prospects of meaningful proposals while paying no cost for <em>&quot;just asking questions.&quot;</em> This should be actively discouraged, particularly among implementers, within the social compact of web <abbr title="Standards Development Organisations">SDOs</abbr>. The price for imposing delay must be higher than having vague <em>&quot;concerns&quot;</em>.</p>
</li>
<li>
<p><strong>Require Working Groups to list incubators they accept proposals from. Require they prove it.</strong></p>
<p>Many groups that fifth columnists exploit demonstrate a relative imperviousness to new ideas through a combination of social norms and studious ignorance. To break this pattern, <abbr title="Standards Development Organisations">SDOs</abbr> should require all re-charters include clear evidence of proposals coming from outside the group itself. Without such collateral, charters should be at risk.</p>
</li>
<li>
<p><strong>Defend incubators from process attacks.</strong></p>
<p>Far from being sideshows, incubation venues are the lifeblood of vibrant <abbr title="Standards Development Organisations">SDOs</abbr>. They must be encouraged, nurtured, and highlighted to the membership as essential to the success of the ecosystem and the organisation.</p>
<p>In the same vein, process shenanigans to destabilise successful incubators must be fended off; including but not limited to making them harder to join or create, efforts to deny their work products a seat in working group chartering, or tactics that make their internal operations more veto-centric.</p>
</li>
</ul>
<p>It takes a long time, but like the gravitational effects of a wandering planet out in the OORT cloud, the informational content of the fifth columnist's agenda eventually becomes legible by side effect. Because an anti-web agenda is easy to pass off under other cover, it requires a great number of observations to understand that this part of the committee <em>does not want the platform to evolve.</em> From that point forward, it becomes easier to understand the information being communicated as noise, rather than signal.</p>
<p>Once demonstrated, we must route around the damage, raising the cost of efforts to undermine the single most successful standards-based ecosystem of our lifetimes; one that I believe is worth defending from insider threats as well as external attack.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-failure-epochs-1" class="footnote-item"><p>The most substantial periods of institutional decrepitude in web standards are highly correlated with veto players (vendors with more than ~10% total share) walking away from efforts to push the web forward.</p>
<p>The most famous period of <abbr title="Standards Development Organisation">SDO</abbr> decay is probably the <abbr title="World Wide Web Consortium">W3C</abbr>'s troubled period after Microsoft disbanded the Internet Explorer team after <abbr title="Internet Explorer">IE</abbr> 6.0's triumphant release in 2001. Even if folks from Microsoft continued to go to meetings, there was nobody left to implement new or different designs and no product to launch them in.</p>
<p>Standards debate went from pitched battles over essential features of systems being actively developed to creative writing contests about futures it might be nice to have. Without the disciplining function of vendors shipping, working groups just become expensive and drab pantomimes.</p>
<p>With Microsoft circa 2002 casting the <abbr title="Internet Explorer">IE</abbr> team to the wind and pivoting hard to <a href="https://en.wikipedia.org/wiki/Extensible_Application_Markup_Language">XAML</a> and proprietary, Windows-centric technologies, along with the collapse of Netscape, the <abbr title="World Wide Web Consortium">W3C</abbr> was left rudderless, allowing it to drift into <a href="https://www.sitepoint.com/rip-xhtml-2/">failed XHTML escapades</a> that inspired revulsion among the remaining staffed engine projects.</p>
<p>This all came to a head over <a href="https://www.w3.org/2004/04/webapps-cdf-ws/papers/">proposed future directions</a> at 2004's <a href="https://www.w3.org/2004/04/webapps-cdf-ws/">Web Applications and Compound Document Workshop.</a> <a href="https://wiki.whatwg.org/wiki/W3C">WHATWG was founded in the explosion's crater,</a> and the rest is (contested) history.</p>
<p>The seeds of the next failure epoch were planted at the <a href="https://en.wikipedia.org/wiki/App_Store_(Apple)">launch of the iOS App Store in 2008</a>, where it first became clear that other &quot;browsers&quot; would be allowed on Cupertino's best-selling devices, but not if they included their own engines. Unlike the big-bang of Microsoft walking away from browsers for 3+ years, Apple's undermining of the <abbr title="World Wide Web Consortium">W3C</abbr>, <abbr title="Internet Engineering Task Force">IETF</abbr>, and <abbr title="European Computer Manufacturers Association, the home of JavaScript">ECMA</abbr> become visible only gradually as the total global market share of mobile devices accelerated. Apple also &quot;lost&quot; its early lead in the smartphone market share as Android ate up the low end's explosive growth. The result was a two-track mobile universe, where Apple retained nearly all influence and profits, whilst most new smartphone users encountered the predations of Samsung, HTC, LG, Xiaomi, and a hundred other cut-price brands.</p>
<p>Apple's internal debates about which platform for iOS was going to &quot;win&quot; may have been unsettled at the launch of the App Store<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-story-time-13" id="fnref-story-time-13">13</a></sup>, but shortly thereafter the fate of Safari and the web on iOS was sealed when Push Notifications appeared for native apps but not web apps.</p>
<p>Cupertino leveraged its monopoly on influence to destroy the web's chances, while Mozilla, Google, and others who should have spoken up remained silent. Whether that cowardice was borne of fear, hope, or ignorance hardly matters now. The <a href="https://infrequently.org/2024/10/platforms-are-competitions/">price of silence is now plain</a>, and the web so weakened that it may succumb entirely to the next threat; after all, it has no champions among the megacorps that have built their businesses on its back.</p>
<p>First among equals, Apple remains at the vanguard of efforts to suppress the web, spending vast sums to mislead web developers, regulators, legislators, and civil society. That last group uncomfortably includes <abbr title="Standards Development Organisations">SDOs</abbr>, and it's horrifying to see the gaslighting plan work while, in parallel, Cupertino <a href="https://www.gov.uk/government/news/cma-wins-appeal-in-apple-case">sues for delay</a> and offers easily disproven nonsense in rooms where knowing misrepresentation should carry sanction.</p>
<p>All this to preclude a competent version of the web on iPhones, either from Apple or (horrors!) from anyone else. Query why. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-failure-epochs-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-blocking-share-2" class="footnote-item"><p>The market share at which any browser obtains &quot;blocking share&quot; is not well theorized, but is demonstrably below 5% for previously dominant players, and perhaps higher for browsers or brands that never achieved market plurality status.</p>
<p>Browsers and engines which never gain share above about 10% are not considered &quot;relevant&quot; by most developers and can be born, live, and die entirely out of view of the mainstream. For other players, particularly across form-factors, the salience of any specific engine is more contextual. Contractual terms, tooling support, and even the personal experience of influential developers all play a role. This situation is not helped by major sites and CDNs — with the <a href="https://radar.cloudflare.com/reports/browser-market-share-2025-q1">partial exception of Cloudflare</a> — declining to share statistics on the mix of browsers their services see.</p>
<p>Regardless, web-wide market share below 2% for any specific version of any engine is generally accepted as irrelevance; the point at which developers no longer put in even minimal effort to continue to support a browser except with &quot;fallback&quot; experiences. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-blocking-share-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-w3c-as-hostage-3" class="footnote-item"><p>It's not an exaggeration to suggest that <a href="https://www.w3.org/">the <abbr title="World Wide Web Consortium">W3C</abbr></a>, <a href="https://www.ietf.org/"><abbr title="Internet Engineering Task Force">IETF</abbr></a>, and <a href="http://www.ecma-international.org/"><abbr title="European Computer Manufacturers Association, the home of JavaScript">ECMA</abbr></a> have been fundamentally undermined by Apple's <a href="https://open-web-advocacy.org/blog/apples-browser-engine-ban-persists-even-under-the-dma/">coercion regarding browser engines on iOS,</a> turning the entire organisation into a sort of <a href="https://en.wikipedia.org/wiki/Potemkin_village">Potempkin village</a> with semi-independent burgs taking shape on the outskirts through <a href="https://www.w3.org/community/">Community Groups</a> like the <a href="https://wicg.io/"><abbr title="Web Incubation Community Group at the W3C">WICG</abbr>,</a> which Apple regularly tries to tear down through procedural attacks it hopes the wider community will not trace back to the source.</p>
<p>When competitors cannot ship their best ideas, the venues where voluntary standards are codified lose both their role as patent-pooling accelerators for adoption, as well as their techno-social role as mediators and neutral ground.</p>
<p>The corporeal form continues long after the ghost leaves the body, but once the vivifying force of feature autonomy is removed, an <abbr title="Standards Development Organisation">SDO</abbr>'s roof only serves to collect skeletons, eventually compromising the organisation itself. On these grounds, self-aware versions of the <abbr title="World Wide Web Consortium">W3C</abbr>, <abbr title="Internet Engineering Task Force">IETF</abbr>, and <abbr title="European Computer Manufacturers Association, the home of JavaScript">ECMA</abbr> would have long ago ejected Apple from membership, but self-awareness is not their strong suit. And as long as the meetings continue and new drafts are published, it hardly deserves mention that the <abbr title="Standards Development Organisation">SDO</abbr>'s role in facilitating truly disruptive change will never again be roused. After all, the membership documents companies sign do not require them to refrain from shiving their competition; only that everyone keep their voices down and the tone civil.</p>
<p>What's truly sad is how few convening services, or reciting liturgies from the pews, seem disturbed their prayers will never again be heard. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-w3c-as-hostage-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-big-blue-4" class="footnote-item"><p>This is about the point where folks will come crawling out of the walls to tell stories about IBM or Rambus or Oracle or any of the codec sharks that have played the heel in standards at one point or another. Don't bother; I've got a pretty full file of those stories, and I can't repeat them here anyway. But if you do manage to blog one of them in an entertaining way without getting sued, please <a href="https://infrequently.org/about-me/">drop a line.</a> <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-big-blue-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-as-days-go-by-5" class="footnote-item"><p>You know, in case you're wondering what <abbr title="Cascading Style Sheets">CSS</abbr> WG was doing from '04-'21. <a href="https://infrequently.org/2021/04/progress-delayed/">I wonder what changed?</a> <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-as-days-go-by-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-tracking-6" class="footnote-item"><p>It's particularly disingenuous for fifth columnists to claim proposals they don't like are <em>&quot;not standards track&quot;</em> as they know full-well that the reason they aren't being advanced within chartered working groups is their own opposition.</p>
<p>The circularity is gobsmacking, but often works. This reduces pressure from credulous web developers. Excusemaking is only possible because other vendors fail to call bullshit. Apple, e.g., would not be getting away with snuffing out the mobile web's chances were it not for a cosy set of fellow travellers at Mozilla and Google. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-tracking-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-furious-intensity-7" class="footnote-item"><p>Internet APIs and protocols do not spring fully-formed from the head of Zeus.</p>
<p>Getting to good, or even good-enough, requires furious iteration, and that means testing and prodding at proposals. The only way to get miles under a proposal is to try things, and that's what incubation venues specialise in. It is not a sign of failure that many proposals change shape in response to feedback, or that certain evolutionary branches are abandoned altogether. Much the opposite.</p>
<p>It is only by trying, testing, iterating, and yes, abandoning many designs that we arrive at productive progress in web specs. Anyone who tells you differently is carrying water for fifth columnists and should be put on notice. They may not personally intend to undermine the web's future, but that's what treating iteration in design as failure does by proxy. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-furious-intensity-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-master-debaters-8" class="footnote-item"><p>Most Web API design processes cannot claim any kinship to the scientific method, although we have tried mightily <a href="https://infrequently.org/2015/08/doing-science-on-the-web/">to open a larger space for testing of alternative hypotheses within the Chromium project over the past decade.</a></p>
<p>Even so, much of the design work of APIs on the web platform is shaped by the specific and peculiar preferences of powerful individuals, many of whom are not and have never been working web developers. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-master-debaters-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-cheap-and-cheerful-9" class="footnote-item"><p>Hiring &quot;known quantities&quot; to do the wrangling within a Working Group you want to scupper is generally cheaper than doing constructive design work, so putting in-group old-timers on the payroll is a reliable way for fifth columnists to appear aligned with the goals of the majority while working against them in practice. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-cheap-and-cheerful-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-capability-stability-is-not-back-compat-10" class="footnote-item"><p>One rhetorical mode for those working to constrain the web platform's capabilities is to attempt to conflate any additions with <em>instability</em>, and specifically, the threat that sites that work today will stop working tomorrow. This is misdirection, as stability for the ecosystem is not a function of standards debates, but rather the self-interested actions of each vendor in the market.</p>
<p>When true browser competition is allowed, the largest disciplining force on vendor behaviour is incompatibility. Browsers that fail to load important web pages lose share to those that have better web compatibility. This is as close as you can get to an iron law of browser engineering, and every vendor knows that their own engine teams have spent gargantuan amounts of time and money to increase compatibility over the years.</p>
<p>Put more succinctly, <em><strong>backwards compatibility on the web is not seriously at risk from capability expansions</strong></em>. Proposals that would imperil back compat<sup class="footnote-ref"><a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fn-orderly-transitions-12" id="fnref-orderly-transitions-12">12</a></sup> are viewed as non-starters in all web standards venues, and <a href="https://en.wikipedia.org/wiki/WHATWG">major schisms</a> have formed over proposed, incompatible divergence, with the compatibility-minded winning nearly every skirmish.</p>
<p>No <abbr title="Standards Development Organisation">SDO</abbr> representative from these teams is ignorant of these facts, and so attempts to argue against solving important problems by invoking the spectre of <em>&quot;too much change, too fast&quot;</em> or <em>&quot;breaking the web&quot;</em> are sleights of hand.</p>
<p>They know that most web developers value stability and don't understand these background facts, creating space for a shell game in which the threat of too much change serves to obscure their own attempts at sabotage through inaction. Because web standards are voluntary and market share matters tremendously to every vendor, nothing that actually breaks the web will be allowed to ship. So armed, you can now call out this bait-and-switch wherever it appears. Doing so is important, as the power to muddy these waters stems from the relative ignorance of web developers. Educating them to the real power dynamics at work is our best bulwark against the fifth column. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-capability-stability-is-not-back-compat-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-voluntary-for-me-but-not-for-thee-11" class="footnote-item"><p>There's no surer sign of the blindness many <abbr title="Standards Development Organisation">SDO</abbr> participants exhibit toward the breakage of the voluntary implementation regime than that they extend deference on that basis <em>to Apple</em>.</p>
<p>Cupertino's <abbr title="Standards Development Organisation">SDO</abbr> delegates do not bear a heightened presumption that they will implement as soon as other ship. To the contrary, Apple have so thoroughly lowered expectations that nobody expects timely feedback on proposals, let alone implementation commitments. Even when Apple is the last holdout. Cupertino sullies the brands they force to use WebKit's worst-of-the-worst implementation. It has been going on so long that it is now simply accepted as the status quo.</p>
<p>This is entirely backwards, and Apple's representatives should, instead, be expected to provide implementation timelines for features shipped by other vendors. <a href="https://open-web-advocacy.org/blog/uk-regulators-final-verdict--apples-browser-engine-ban-harms-competition/#apple-google-search-deal">God knows they can afford it.</a></p>
<p>Until such time as Apple allows engine competition worldwide, it's only fair to expect (and demand) parity. Every Apple employee should feel the heat of shame every as they mutter <em>&quot;Apple does not comment on future product releases&quot;</em> while indefensibly harming the web. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-voluntary-for-me-but-not-for-thee-11" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-orderly-transitions-12" class="footnote-item"><p>The browser and web infrastructure community <em>have</em> implemented large transitions away from some regretted technologies, but the care and discipline needed to do this without breaking the web is the stuff of legend. Big ones that others should write long histories of are the <a href="https://web.dev/articles/appcache-removal">sunsetting of AppCache</a> and <a href="https://www.wired.com/2016/11/googles-chrome-hackers-flip-webs-security-model/">the move away from unencrypted network connections.</a></p>
<p>Both played out on the order of half a decade or more, took dozens of stakeholders to pull off, and were games of inches adding up to miles. New tools like <a href="https://developer.mozilla.org/en-US/docs/Web/API/Reporting_API">The Reporting API,</a> <a href="https://wicg.github.io/deprecation-reporting/">Deprecation Reports,</a> and <a href="https://developer.chrome.com/docs/web-platform/origin-trials#deprecation_trials">Reverse Origin Trials</a> had to be invented to augment the &quot;usual&quot; tool bag of <a href="https://source.chromium.org/chromium/chromium/src/+/main:services/metrics/ukm_api.md">anonymised analytics trawls,</a> developer outreach, <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/2LXKVWYkOus/m/gT-ZamfwAKsJ">new limits on unwanted behaviour</a>, and <a href="https://textslashplain.com/2021/10/14/moartls-non-secure-download-blocking/">nudging UI.</a></p>
<p>In both cases (among <a href="https://groups.google.com/a/chromium.org/g/blink-dev/search?q=%22intent%20to%20deprecate%22">many more small deprecations we have done over the years</a>), the care taken ensured that only a small fraction of the ecosystem was impacted at any moment, lowering the temperature and allowing for an orderly transition to better technology. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-orderly-transitions-12" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-story-time-13" class="footnote-item"><p>Your correspondent has heard different stories from folks who had reason to know about the period from '08-'10 when Apple pulled its foot off the gas with Safari.</p>
<p>Given the extreme compartmentalisation of Apple's teams, the strategic import of any decision, and the usual opacity of tech firms around funding levels (&quot;headcount&quot;) to even relatively senior managers, this is both frustrating and expected.</p>
<p>The earliest dating puts the death of the web as <em>&quot;Plan A&quot;</em> before Steve Jobs's <a href="https://en.wikipedia.org/wiki/IPhone_(1st_generation)">announcement of the iPhone at Macworld in June 2007</a>. The evidence offered for this view was that a bake off for system apps and the home screen launcher had already been lost by WebKit. Others suggest it wasn't until the success of the App Store in '09 and '10 that Apple began to pull away from the web as a top-tier platform. Either way, it was all over by early 2011 at the very latest.</p>
<p>WebKit would never again be asked to compete as a primary mobile app platform, and skeletal funding for Safari ensured it would never be allowed to break out of the OS's strategic straightjacket the way <abbr title="Internet Explorer">IE</abbr> 4-6 had. <a href="https://infrequently.org/2025/08/how-do-committees-fail-to-invent/#fnref-story-time-13" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Links? Links!</title>
    <link href="https://infrequently.org/2025/07/links/"/>
    <updated>2025-07-16T00:00:00Z</updated>
    <id>https://infrequently.org/2025/07/links/</id>
    <content type="html"><![CDATA[
      <!-- LTeX: language=en-GB -->
<p><a href="https://fberriman.com/">Frances</a> has urged me for years to collect resources for folks getting into performance and platform-oriented web development. The effort has always seemed daunting, but the lack of such a list came up again at work, prompting me to take on the side-quest amidst a different performance yak-shave. If that sounds like procrastination, well, you might very well think that. I couldn't possibly comment.</p>
<p>The result is a new <a href="https://infrequently.org/links/">links and resources page</a> page which you can find over in the navigation rail. It's part <a href="https://infrequently.org/links/#web-performance">list-of-things-I-keep-sending-people</a>, part <a href="https://infrequently.org/links/#fundamentals">background</a> <a href="https://infrequently.org/links/#posts-worth-bookmarking">reading</a>, and part <a href="https://infrequently.org/links/#blogs">blogroll.</a></p>
<p>The blogroll section also prompted me to create an <a href="https://infrequently.org/links/infrequently.org-links.opml" download="">OPML export <span style="font-family: share-button-combined;"></span></a>, which you can download or send directly to your feed reader of choice.</p>
<p>The page now contains more than 250 pointers to people and work that I view as important to a culture that is intentional about building a web worth wanting. Hopefully maintenance won't be onerous from here on in. The process of tracking down links to blogs and feeds is a slog, no matter how good the tooling. Very often, this involved heading to people's sites and reading the <code>view-source://</code></p>
<h2 id="fomo" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/07/links/#fomo">FOMO</a></h2>
<p>Having done this dozens of times on the sites of brilliant and talented web developers in a short period of time, a few things stood out.</p>
<p>First — and I cannot emphasise this enough — <a href="https://codepen.io/miocene/pen/WJRXVg"><em><strong>holy cow</strong></em>.</a></p>
<p>The things creative folks can do today with CSS, HTML, and SVG in good browsers is astonishing. If you want to be inspired about what's possible without dragging bloated legacy frameworks along, the work of <a href="https://codepen.io/thebabydino">Ana Tudor,</a> <a href="https://codepen.io/jh3y">Jhey,</a> <a href="https://codepen.io/miocene">Julia Miocene,</a> <a href="https://scroll-driven-animations.style/">Bramus,</a> <a href="https://nerdy.dev/">Adam,</a> and <a href="https://codepen.io/HejChristian/pen/VYwEVPO">so many others</a> can't help but raise your spirits. The CodePen community, in particular, is incredible, and I could (and have) spend hours just clicking through and dissecting clever uses of the platform from <a href="https://codepen.io/spark">the site's &quot;best of&quot; links.</a></p>
<p>Second, <em><strong><a href="https://www.11ty.dev/">11ty</a> and <a href="https://astro.build/">Astro</a> have won the hearts of frontend's best minds.</strong></em></p>
<p>It's not universal, but the overwhelming bulk of personal pages by the most talented frontenders are now built with SSGs that put them in total control. React, Next, and even Nuxt are absent from pages of the folks who really know what they're doing. This ought to be a strong signal to hiring managers looking to cut through the noise.</p>
<p>Next, <em><strong>when did RSS/Atom previews get so dang beautiful?</strong></em></p>
<p>The art and effort put into XSLT styling like <a href="https://www.ellyloel.com/feed.rss">Elly Loel's</a> is gobsmacking. I am verklempt that not only does my feed not look that good, my <em>site</em> doesn't look that polished.</p>
<p>Last, <em><strong>whimsy isn't dead.</strong></em></p>
<p>Webrings, <a href="https://leanrada.com/guestbook/">guestbooks,</a> ASCII art in comments, and every other fun and silly flourish are out there, going strong, just below the surface of the JavaScript-Industrial Complex's thinkfluencer hype recycling.</p>
<p>And it's wonderful.</p>
<p>My overwhelming feeling after composing this collection is gratitude. So many wonderful people are doing great things, based on values that put users first. Sitting with their work gives me hope, and I hope their inspiration can spark something similar for you.</p>

    ]]></content>
  </entry>
  <entry>
    <title>Conferences, Clarity, and Smokescreens</title>
    <link href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/"/>
    <updated>2025-06-27T00:00:00Z</updated>
    <id>https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/</id>
    <content type="html"><![CDATA[
      <!-- LTeX: language=en-GB -->
<p>Before saying anything else, I'd like to thank the organisers of <a href="https://jsnation.com/">JSNation</a> for inviting me to <a href="https://gitnation.com/contents/project-fugu-bringing-hardware-capabilities-to-the-web-safely">speak in Amsterdam.</a> I particularly appreciate the folks who were brave enough to disagree at the Q&amp;A sessions afterwards. Engaged debate about problems we can see and evidence we can measure makes our work better.</p>
<p>The <a href="https://circa.nl/en/">conference venue</a> was lovely, and speakers were more than well looked after. Many of the JSNation talks were of exactly the sort I'd hope to see as our discipline belatedly confronts a <a href="https://infrequently.org/2023/02/the-market-for-lemons/">lost decade,</a> particularly <a href="https://jeremias.codes/">Jeremias Menichelli's</a> <a href="https://gitnation.com/contents/the-new-defaults-of-the-modern-web">lighting talk.</a> It masterfully outlined how many of the hacks we have become accustomed to are no longer needed, even in <a href="https://infrequently.org/2025/06/the-ghost-of-christmas-past/">the worst contemporary engines.</a> <code>view-source://</code> on the <a href="https://modern-web-standards.netlify.app/">demo site he made</a> to see what I mean.</p>
<p><a href="https://bsky.app/profile/webx.bsky.social">Vinicius Dallacqua's</a> talk on <a href="https://developer.chrome.com/docs/web-platform/long-animation-frames">LoAF</a> was on-point, and the full JSNation line-up included knowledgeable and wise folks, including <a href="https://bsky.app/profile/thisisjofrank.bsky.social">Jo</a>, <a href="https://charliegerard.dev/">Charlie</a>, <a href="https://blog.tomayac.com/">Thomas</a>, <a href="https://www.tunetheweb.com/">Barry</a>, <a href="https://slides.nico.dev/250612-kitt-jsnation/">Nico</a>, and <a href="https://github.com/devnook">Eva</a>. There was also a strong set of accessibility talks from presenters I'm less familiar with, but whose topics were <a href="https://commission.europa.eu/strategy-and-policy/policies/justice-and-fundamental-rights/disability/union-equality-strategy-rights-persons-disabilities-2021-2030/european-accessibility-act_en">timely</a> and went deeper than the surface. They even <a href="https://gitnation.com/person/alex_russell">let me present</a> a <a href="https://infrequently.org/2024/08/caprock/">spicier topic</a> than I think they might have been initially comfortable with.</p>
<p>All-in-all, JSNation was a lovely time, in good company, with a strong bent toward doing a great job for users. Recommended.</p>
<p>Day 2<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-structure-1" id="fnref-structure-1">1</a></sup> — <a href="https://reactsummit.com/">React Summit 2025</a> — could not have been more different. While I was in a parallel framework authors meeting for much of the morning,<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-pain-is-a-great-teacher-2" id="fnref-pain-is-a-great-teacher-2">2</a></sup> I did attend talks in the afternoon, studied the <a href="https://reactsummit.com/schedule">schedule</a>, and went back through many more after the fact on <a href="https://www.youtube.com/live/aKfQ_ftodEg?si=kfTZ4eSOEwxpICTj">the stream.</a> Aside from <a href="https://bsky.app/profile/hux.pro">Xuan Huang's</a> talk on <a href="https://lynxjs.org/">Lynx</a> and <a href="https://lucamezzalira.com/">Luca Mezzalira's</a> talk on architecture, there was little in the program that challenged <a href="https://infrequently.org/2024/11/if-not-react-then-what/">frameworkist</a> dogma, and much that played to it.</p>
<p>This matters because conferences succeed by foregrounding the hot topics within a community. Agendas are curated to reflect the tides of debate in the zeitgeist, and can be read as a map of the narratives a community's leaders wish to see debated. My day-to-day consulting work, along with high-visibility industry data, shows that the React community is mired in a deep, measurable quality crisis. But attendees of React Summit who didn't already know wouldn't hear about it.</p>
<p>Near as I can tell, the schedule of <a href="https://reactsummit.com/">React Summit</a> mirrors the content of other recent and pending React conferences (<a href="https://appjs.co/#agenda">1</a>, <a href="https://reactnorway.com/#schedule">2</a>, <a href="https://reactnexus.com/#agenda">3</a>, <a href="https://reactalicante.es/#schedule">4</a>, <a href="https://youtu.be/p6auCiVoa3c?si=NhjMKIiYe0EDIJSw">5</a>, <a href="https://youtu.be/q4cF-ftxpbk?si=uXZdO4o2wsBPcvix">6</a>) in that these are not engineering conferences; they are marketing events.</p>
<p>How can we tell the difference? The short answer is also a question: <em>&quot;who are we building for?&quot;</em></p>
<p>The longer form requires distinguishing between <a href="https://en.wikipedia.org/wiki/Work_(human_activity)"><em>occupations</em></a> and <em>professions</em>.</p>
<h2 id="occupational-hazards" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#occupational-hazards">Occupational Hazards</a></h2>
<p>In a <a href="https://louisville.edu/law/library/special-collections/the-louis-d.-brandeis-collection/business-a-profession-chapter-1">1912 commencement address</a>, the great American jurist and antitrust reformer <a href="https://en.wikipedia.org/wiki/Louis_Brandeis">Louis Brandeis</a> hoped that a different occupation — business management — would aspire to service:</p>
<blockquote>
<p>The peculiar characteristics of a profession as distinguished from other occupations, I take to be these:</p>
<p><strong>First.</strong> A profession is an occupation for which the necessary preliminary training is intellectual in character, involving knowledge and to some extent learning, as distinguished from mere skill.</p>
<p><strong>Second.</strong> It is an occupation which is pursued largely for others and not merely for one's self.</p>
<p><strong>Third.</strong> It is an occupation in which the amount of financial return is not the accepted measure of success.</p>
</blockquote>
<p>In the same talk, Brandeis named engineering a discipline already worthy of a professional distinction. Most software development can't share the benefit of the nominative doubt, no matter how often &quot;engineer&quot; appears on CVs and business cards. If React Summit and Co. are anything to go by, frontend is mired in the same ethical tar that causes Wharton, Kellogg, and Stanford grads to experience midlife crises.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-or-not-3" id="fnref-or-not-3">3</a></sup></p>
<p>It may seem slanderous to compare React conference agendas to MBA curricula, but if anything it's letting the <a href="https://infrequently.org/2023/02/the-market-for-lemons/">lemon vendors</a> off too easily. Conferences crystallise consensus about which problems <em>matter</em>, and React Summit succeeded in projecting a clear perspective — namely that it's time to <a href="https://en.wikipedia.org/wiki/Template:Web_browsers_by_year#/media/File:BrowserUsageShare.png">party like it's 2013.</a></p>
<p>A patient waking from a decade-long coma would find the themes instantly legible. In no particular order: React is good because it is popular. There is no other way to evaluate framework choice, and that it's daft to try because &quot;<em>everyone knows React</em>&quot;.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-round-and-round-4" id="fnref-round-and-round-4">4</a></sup> Investments in React are simultaneously solid long-term choices, but also fragile machines in need of constant maintenance lest they wash away under the annual tax of breaking changes, toolchain instability, and changing solutions to problems React itself introduces. Form validation is not a solved problem, and in our glorious future, the <s>transpilers</s> compilers will save us.</p>
<p>Above all else, the consensus remains that <abbr title="Single Page Apps">SPAs</abbr> are unquestionably a good idea, and that React makes sense because you need complex data and state management abstractions to make transitions between app sections seem fluid in an <abbr title="Single Page App">SPA</abbr>. And if you're worried about the serially terrible performance of React on mobile, don't worry; for the low, low price of capitulating to App Store gatekeepers, React Native has you covered.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-wut-5" id="fnref-wut-5">5</a></sup></p>
<p>At no point would our theoretical patient risk learning that rephrasing everything in JSX is now optional thanks to <a href="https://custom-elements-everywhere.com/">React 19 finally unblocking interoperability</a> via Web Components.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-composition-6" id="fnref-composition-6">6</a></sup> Nor would they become aware that new platform APIs like <a href="https://developer.chrome.com/docs/web-platform/view-transitions/cross-document">cross-document View Transitions</a> and <a href="https://developer.chrome.com/docs/web-platform/navigation-api">the Navigation API</a> invalidate foundational premises of the architectures that React itself is justified on. They wouldn't even learn that React <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EventPhases/explainer.md">hasn't solved the one problem it was pitched to address.</a></p>
<p>Conspicuously missing from the various &quot;State Of&quot; talks was discussion of the pressing and pervasive <abbr title="User Experience">UX</abbr> quality issues that are rampant in the React ecosystem.</p>
<p></p><figure class="full_wide"><picture style="--lqip: 174299" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/cwv_pct.avif" alt="Per the 2024 Web Almanac, less than half of sites earn passing grades on mobile, where most users are." style="aspect-ratio: 1141 / 718" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>Per the 2024 Web Almanac, less than half of sites earn passing grades on mobile, where most users are.</figcaption>      </figure><p></p>
<p>We don't need to get distracted looking inside these results. Treating them as black boxes is enough. And at that level we can see that, in aggregate, <abbr title="JavaScript">JS</abbr>-centric stacks aren't positively correlated with delivering good user-experiences.</p>
<p></p><figure class="full_wide"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/frontend_sadness_index.avif" alt="2024's switch from FID to INP caused React (particularly Next and Gatsby) sites which already had low pass-rates to drop more than sites constructed on many other stacks." style="aspect-ratio: 1221 / 718" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>2024's switch from <abbr title="First Input Delay, as defined by Core Web Vitals">FID</abbr> to <abbr title="Interaction-to-Next Paint, as defined by Core Web Vitals">INP</abbr> caused React (particularly Next and Gatsby) sites which already had low pass-rates to drop more than sites constructed on many other stacks.</figcaption>      </figure><p></p>
<p>This implies that organisations adopting React do not contain the <a href="https://en.wikipedia.org/wiki/Variety_(cybernetics)">requisite variety</a> needed to manage the new complexity that comes from React ecosystem tools, practices, and community habits. Whatever the source, it is clearly a package deal. The result are systems that are <em>out of control</em> and behave in dynamically unstable ways relative to business goals.</p>
<p>The evidence that React-based stacks frequently fail to deliver good experiences is <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-failure-on-repeat-2">everywhere.</a> Weren't <em>&quot;fluid user experiences&quot;</em> the point of the <abbr title="JavaScript">JS</abbr>/<abbr title="Single Page App">SPA</abbr>/React boondoggle?<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-bait-and-switch-7" id="fnref-bait-and-switch-7">7</a></sup></p>
<p>We have witnessed high-cost, low-quality <abbr title="JavaScript">JS</abbr>-stack rewrites of otherwise functional <abbr title="HyperText Markup Language">HTML</abbr>-first sites ambush businesses with reduced revenue and higher costs for a decade. It is no less of a scandal for how pervasive it has become.</p>
<p>But good luck finding solutions to, or even acknowledgement of, that scandal on React conference agendas. The reality is that the more React spreads, the worse the results get despite the eye-watering sums spent on conversions away from functional &quot;legacy&quot; <abbr title="HyperText Markup Language">HTML</abbr>-first approaches. Many at React Summit were happy to make these points to me in private, but not on the main stage. The <abbr title="JavaScript">JS</abbr>-industrial-complex omertà is <em>intense.</em></p>
<p>No speaker I heard connected the dots between this crisis and the moves of the React team in response to <a href="https://web.dev/articles/vitals">the emergence of comparative quality metrics.</a> React Fiber (<em>née</em> &quot;Concurrent&quot;), React Server Components, the switch away from Create React App, and the React Compiler were discussed as logical next steps, rather than what they are: <a href="https://developers.google.com/search/docs/appearance/core-web-vitals">attempts to stay one step ahead of the law.</a> Everyone in the room was expected to use their employer's money to adopt all of these technologies, rather than reflect on why all of this has been uniquely necessary in the land of the Over Reactors.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-ground-zero-8" id="fnref-ground-zero-8">8</a></sup></p>
<p>The <a href="https://polotek.net/posts/the-frontend-treadmill/">treadmill is real,</a> but even at this late date, developers are expected to take promises of quality and productivity at face value, even as they wade through <em>another</em> swamp of <a href="https://www.youtube.com/live/aKfQ_ftodEg?si=pvM1Pej8RYl2Bwg9&amp;t=18498">configuration cruft,</a> <a href="https://www.youtube.com/live/aKfQ_ftodEg?si=awDeg45kLYkUqsko&amp;t=18965">bugs,</a> and upgrade toil.</p>
<p>React cannot fail, it can only be failed.</p>
<h2 id="overexposed" tabindex="-1"><a class="permalink" href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#overexposed">OverExposed</a></h2>
<p>And then there was the privilege bubble. Speaker after speaker stressed development speed, including the ability to ship to mobile and desktop from the same React code. The implications for complexity-management, user-experience, and access were less of a focus.</p>
<p>The most egregious example of the day came from <a href="https://evanbacon.dev/">Evan Bacon</a> in his talk about <a href="https://expo.dev/">Expo</a>, in which he presented Burger King's website as an example of a brand successfully shipping simultaneously to web and native from the same codebase. Here it is under WebPageTest.org's desktop setup:<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-4g-9" id="fnref-4g-9">9</a></sup></p>
<br style="display: none;" />
<wpt-filmstrip size="large" waterfall="true" breakdown="true" gif="true" interval="500ms">
      <wpt-test label="bk.com, first load, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250618_YiDc5D_3EP","url":"https://www.bk.com/","summary":"https://www.webpagetest.org/results.php?test=250618_YiDc5D_3EP","testUrl":"https://www.bk.com/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750236871,"testRuns":1,"testName":"250618_YiDc5D_3EP","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://www.bk.com/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.2552},{"start":"0.10","end":"0.25","density":0.4253},{"start":"0.25","density":0.3195}],"percentiles":{"p75":"0.27"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8366},{"start":800,"end":1800,"density":0.1192},{"start":1800,"density":0.0442}],"percentiles":{"p75":559}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.5617},{"start":1800,"end":3000,"density":0.2189},{"start":3000,"density":0.2194}],"percentiles":{"p75":2737}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.4556},{"start":2500,"end":4000,"density":0.2451},{"start":4000,"density":0.2993}],"percentiles":{"p75":4605}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.6814},{"start":75,"end":275,"density":0.2931},{"start":275,"density":0.0255}],"percentiles":{"p75":84}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.5491},{"start":200,"end":500,"density":0.3029},{"start":500,"density":0.148}],"percentiles":{"p75":340}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":218}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":4628}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":98}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":447}},"largest_contentful_paint_resource_type":{"fractions":{"text":0.3302,"image":0.6698}},"navigation_types":{"fractions":{"back_forward_cache":0.0014,"prerender":0.0225,"navigate":0.7868,"navigate_cache":0.1361,"reload":0.0292,"restore":0.0043,"back_forward":0.0196}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":20},"lastDate":{"year":2025,"month":6,"day":16}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/details/","checklist":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/breakdown/","domains":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/domains/","screenShot":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250618_YiDc5D_3EP/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/18/YiDc5D/3EP/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/18/YiDc5D/3EP/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/18/YiDc5D/3EP/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250618_YiDc5D_3EP&file=1_screen.jpg"},"breakdown":{"html":{"bytes":1145,"bytesUncompressed":2494,"requests":1},"js":{"bytes":3496795,"bytesUncompressed":15082904,"requests":13},"css":{"bytes":11739,"bytesUncompressed":57227,"requests":3},"image":{"bytes":406401,"bytesUncompressed":415256,"requests":23},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":265057,"bytesUncompressed":560160,"requests":4},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":196653,"bytesUncompressed":2172114,"requests":59}},"loadTime":5237,"docTime":5237,"fullyLoaded":12964,"firstPaint":5805,"firstContentfulPaint":5805,"firstMeaningfulPaint":6295,"lastVisualChange":9200,"visualComplete":9200,"visualComplete85":9100,"visualComplete90":9100,"visualComplete95":9100,"visualComplete99":9100,"SpeedIndex":7381,"TotalBlockingTime":254,"layoutShifts":[5235,8178],"lcps":[9142],"navigationStart":34,"fetchStart":18,"domLoading":910,"responseEnd":904,"domInteractive":1652,"domContentLoadedEventStart":5235,"domContentLoadedEventEnd":5235,"domComplete":5237,"unloadEventStart":909,"unloadEventEnd":909,"markAsMainFrame":909,"commitNavigationEnd":909,"loadEventStart":5237,"loadEventEnd":5237,"firstMeaningfulPaintCandidate":6295,"firstImagePaint":5927,"LargestTextPaint":8068,"LargestImagePaint":9142,"LargestContentfulPaint":9142,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":5800,"image":"filmstrip/ms_005800.jpg","VisuallyComplete":16},{"time":5900,"image":"filmstrip/ms_005900.jpg","VisuallyComplete":16},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":56},{"time":6400,"image":"filmstrip/ms_006400.jpg","VisuallyComplete":56},{"time":6500,"image":"filmstrip/ms_006500.jpg","VisuallyComplete":57},{"time":6600,"image":"filmstrip/ms_006600.jpg","VisuallyComplete":57},{"time":6700,"image":"filmstrip/ms_006700.jpg","VisuallyComplete":57},{"time":6900,"image":"filmstrip/ms_006900.jpg","VisuallyComplete":57},{"time":7000,"image":"filmstrip/ms_007000.jpg","VisuallyComplete":57},{"time":7100,"image":"filmstrip/ms_007100.jpg","VisuallyComplete":57},{"time":7200,"image":"filmstrip/ms_007200.jpg","VisuallyComplete":57},{"time":7300,"image":"filmstrip/ms_007300.jpg","VisuallyComplete":57},{"time":7500,"image":"filmstrip/ms_007500.jpg","VisuallyComplete":57},{"time":7600,"image":"filmstrip/ms_007600.jpg","VisuallyComplete":57},{"time":7700,"image":"filmstrip/ms_007700.jpg","VisuallyComplete":57},{"time":7900,"image":"filmstrip/ms_007900.jpg","VisuallyComplete":57},{"time":8000,"image":"filmstrip/ms_008000.jpg","VisuallyComplete":62},{"time":8200,"image":"filmstrip/ms_008200.jpg","VisuallyComplete":61},{"time":9100,"image":"filmstrip/ms_009100.jpg","VisuallyComplete":99},{"time":9200,"image":"filmstrip/ms_009200.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":122,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>As you might expect, putting 75% of the 3.5MB <abbr title="JavaScript">JS</abbr> payload (15MB unzipped) in the critical path does unpleasant things to the user experience, but none of the dizzying array of tools involved in constructing bk.com steered this team away from failure.<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-layers-of-fail-10" id="fnref-layers-of-fail-10">10</a></sup></p>
<p>The fact that Expo enables Burger King to ship a native app from the same codebase seems not to have prevented the overwhelming majority of users from <a href="https://treo.sh/sitespeed/www.bk.com#:~:text=%E2%86%92-,AUDIENCE,-Form%20Factors">visiting the site in browsers on their mobile devices,</a> where weaker mobile CPUs struggle mightily:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" interval="500ms">
      <wpt-test label="bk.com, first load, mobile, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250627_ZiDc7Q_4ES","url":"https://www.bk.com/","summary":"https://www.webpagetest.org/results.php?test=250627_ZiDc7Q_4ES","testUrl":"https://www.bk.com/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1751016139,"testRuns":1,"testName":"250627_ZiDc7Q_4ES","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://www.bk.com/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.3317},{"start":"0.10","end":"0.25","density":0.0287},{"start":"0.25","density":0.6397}],"percentiles":{"p75":"0.79"}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.3496},{"start":200,"end":500,"density":0.389},{"start":500,"density":0.2614}],"percentiles":{"p75":514}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.3757},{"start":2500,"end":4000,"density":0.2406},{"start":4000,"density":0.3837}],"percentiles":{"p75":5578}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":461}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.3778},{"start":75,"end":275,"density":0.534},{"start":275,"density":0.0882}],"percentiles":{"p75":139}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.7707},{"start":800,"end":1800,"density":0.1556},{"start":1800,"density":0.0737}],"percentiles":{"p75":749}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.3691},{"start":1800,"end":3000,"density":0.2883},{"start":3000,"density":0.3426}],"percentiles":{"p75":3691}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":329}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":6100}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":129}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.4976,"text":0.5024}},"navigation_types":{"fractions":{"back_forward":0.0194,"back_forward_cache":0.0142,"prerender":0.0131,"navigate":0.7278,"navigate_cache":0.1301,"reload":0.0955,"restore":0}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":29},"lastDate":{"year":2025,"month":6,"day":25}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/details/","checklist":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/breakdown/","domains":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/domains/","screenShot":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250627_ZiDc7Q_4ES&file=1_screen.jpg"},"breakdown":{"html":{"bytes":1140,"bytesUncompressed":2494,"requests":1},"js":{"bytes":3520402,"bytesUncompressed":15162796,"requests":13},"css":{"bytes":11739,"bytesUncompressed":57227,"requests":3},"image":{"bytes":267032,"bytesUncompressed":275882,"requests":16},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":265284,"bytesUncompressed":560160,"requests":4},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":259445,"bytesUncompressed":2143870,"requests":59}},"loadTime":8486,"docTime":8486,"fullyLoaded":30305,"firstPaint":15633,"firstContentfulPaint":15633,"lastVisualChange":28800,"visualComplete":28800,"visualComplete85":27300,"visualComplete90":27600,"visualComplete95":27600,"visualComplete99":28800,"SpeedIndex":19319,"TotalBlockingTime":7080,"layoutShifts":[8456,27498,28719],"lcps":[18775],"navigationStart":55,"fetchStart":25,"domLoading":875,"responseEnd":832,"domInteractive":1883,"domContentLoadedEventStart":8437,"domContentLoadedEventEnd":8437,"domComplete":8485,"unloadEventStart":859,"unloadEventEnd":859,"markAsMainFrame":863,"commitNavigationEnd":870,"loadEventStart":8485,"loadEventEnd":8485,"firstMeaningfulPaintCandidate":15633,"firstImagePaint":17025,"LargestTextPaint":18775,"LargestImagePaint":17025,"LargestContentfulPaint":18775,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":15700,"image":"filmstrip/ms_015700.jpg","VisuallyComplete":33},{"time":16700,"image":"filmstrip/ms_016700.jpg","VisuallyComplete":31},{"time":17100,"image":"filmstrip/ms_017100.jpg","VisuallyComplete":31},{"time":18800,"image":"filmstrip/ms_018800.jpg","VisuallyComplete":83},{"time":20300,"image":"filmstrip/ms_020300.jpg","VisuallyComplete":84},{"time":22000,"image":"filmstrip/ms_022000.jpg","VisuallyComplete":84},{"time":23900,"image":"filmstrip/ms_023900.jpg","VisuallyComplete":83},{"time":26500,"image":"filmstrip/ms_026500.jpg","VisuallyComplete":84},{"time":27300,"image":"filmstrip/ms_027300.jpg","VisuallyComplete":87},{"time":27400,"image":"filmstrip/ms_027400.jpg","VisuallyComplete":87},{"time":27500,"image":"filmstrip/ms_027500.jpg","VisuallyComplete":87},{"time":27600,"image":"filmstrip/ms_027600.jpg","VisuallyComplete":95},{"time":27700,"image":"filmstrip/ms_027700.jpg","VisuallyComplete":95},{"time":27800,"image":"filmstrip/ms_027800.jpg","VisuallyComplete":95},{"time":27900,"image":"filmstrip/ms_027900.jpg","VisuallyComplete":95},{"time":28000,"image":"filmstrip/ms_028000.jpg","VisuallyComplete":95},{"time":28100,"image":"filmstrip/ms_028100.jpg","VisuallyComplete":95},{"time":28200,"image":"filmstrip/ms_028200.jpg","VisuallyComplete":95},{"time":28300,"image":"filmstrip/ms_028300.jpg","VisuallyComplete":95},{"time":28400,"image":"filmstrip/ms_028400.jpg","VisuallyComplete":95},{"time":28500,"image":"filmstrip/ms_028500.jpg","VisuallyComplete":95},{"time":28600,"image":"filmstrip/ms_028600.jpg","VisuallyComplete":95},{"time":28700,"image":"filmstrip/ms_028700.jpg","VisuallyComplete":95},{"time":28800,"image":"filmstrip/ms_028800.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":318,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>The <a href="https://treo.sh/sitespeed/www.bk.com?formFactor=phone"><abbr title="Chrome User Experience Report">CrUX</abbr> data is damning:</a></p>
<br style="display: none;" />
<wpt-filmstrip filmstrip="false" crux="true">
      <wpt-test label="bk.com, first load, mobile, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250627_ZiDc7Q_4ES","url":"https://www.bk.com/","summary":"https://www.webpagetest.org/results.php?test=250627_ZiDc7Q_4ES","testUrl":"https://www.bk.com/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1751016139,"testRuns":1,"testName":"250627_ZiDc7Q_4ES","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://www.bk.com/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.3317},{"start":"0.10","end":"0.25","density":0.0287},{"start":"0.25","density":0.6397}],"percentiles":{"p75":"0.79"}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.3496},{"start":200,"end":500,"density":0.389},{"start":500,"density":0.2614}],"percentiles":{"p75":514}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.3757},{"start":2500,"end":4000,"density":0.2406},{"start":4000,"density":0.3837}],"percentiles":{"p75":5578}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":461}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.3778},{"start":75,"end":275,"density":0.534},{"start":275,"density":0.0882}],"percentiles":{"p75":139}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.7707},{"start":800,"end":1800,"density":0.1556},{"start":1800,"density":0.0737}],"percentiles":{"p75":749}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.3691},{"start":1800,"end":3000,"density":0.2883},{"start":3000,"density":0.3426}],"percentiles":{"p75":3691}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":329}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":6100}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":129}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.4976,"text":0.5024}},"navigation_types":{"fractions":{"back_forward":0.0194,"back_forward_cache":0.0142,"prerender":0.0131,"navigate":0.7278,"navigate_cache":0.1301,"reload":0.0955,"restore":0}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":29},"lastDate":{"year":2025,"month":6,"day":25}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/details/","checklist":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/breakdown/","domains":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/domains/","screenShot":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250627_ZiDc7Q_4ES/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/27/ZiDc7Q/4ES/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250627_ZiDc7Q_4ES&file=1_screen.jpg"},"breakdown":{"html":{"bytes":1140,"bytesUncompressed":2494,"requests":1},"js":{"bytes":3520402,"bytesUncompressed":15162796,"requests":13},"css":{"bytes":11739,"bytesUncompressed":57227,"requests":3},"image":{"bytes":267032,"bytesUncompressed":275882,"requests":16},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":265284,"bytesUncompressed":560160,"requests":4},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":259445,"bytesUncompressed":2143870,"requests":59}},"loadTime":8486,"docTime":8486,"fullyLoaded":30305,"firstPaint":15633,"firstContentfulPaint":15633,"lastVisualChange":28800,"visualComplete":28800,"visualComplete85":27300,"visualComplete90":27600,"visualComplete95":27600,"visualComplete99":28800,"SpeedIndex":19319,"TotalBlockingTime":7080,"layoutShifts":[8456,27498,28719],"lcps":[18775],"navigationStart":55,"fetchStart":25,"domLoading":875,"responseEnd":832,"domInteractive":1883,"domContentLoadedEventStart":8437,"domContentLoadedEventEnd":8437,"domComplete":8485,"unloadEventStart":859,"unloadEventEnd":859,"markAsMainFrame":863,"commitNavigationEnd":870,"loadEventStart":8485,"loadEventEnd":8485,"firstMeaningfulPaintCandidate":15633,"firstImagePaint":17025,"LargestTextPaint":18775,"LargestImagePaint":17025,"LargestContentfulPaint":18775,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":15700,"image":"filmstrip/ms_015700.jpg","VisuallyComplete":33},{"time":16700,"image":"filmstrip/ms_016700.jpg","VisuallyComplete":31},{"time":17100,"image":"filmstrip/ms_017100.jpg","VisuallyComplete":31},{"time":18800,"image":"filmstrip/ms_018800.jpg","VisuallyComplete":83},{"time":20300,"image":"filmstrip/ms_020300.jpg","VisuallyComplete":84},{"time":22000,"image":"filmstrip/ms_022000.jpg","VisuallyComplete":84},{"time":23900,"image":"filmstrip/ms_023900.jpg","VisuallyComplete":83},{"time":26500,"image":"filmstrip/ms_026500.jpg","VisuallyComplete":84},{"time":27300,"image":"filmstrip/ms_027300.jpg","VisuallyComplete":87},{"time":27400,"image":"filmstrip/ms_027400.jpg","VisuallyComplete":87},{"time":27500,"image":"filmstrip/ms_027500.jpg","VisuallyComplete":87},{"time":27600,"image":"filmstrip/ms_027600.jpg","VisuallyComplete":95},{"time":27700,"image":"filmstrip/ms_027700.jpg","VisuallyComplete":95},{"time":27800,"image":"filmstrip/ms_027800.jpg","VisuallyComplete":95},{"time":27900,"image":"filmstrip/ms_027900.jpg","VisuallyComplete":95},{"time":28000,"image":"filmstrip/ms_028000.jpg","VisuallyComplete":95},{"time":28100,"image":"filmstrip/ms_028100.jpg","VisuallyComplete":95},{"time":28200,"image":"filmstrip/ms_028200.jpg","VisuallyComplete":95},{"time":28300,"image":"filmstrip/ms_028300.jpg","VisuallyComplete":95},{"time":28400,"image":"filmstrip/ms_028400.jpg","VisuallyComplete":95},{"time":28500,"image":"filmstrip/ms_028500.jpg","VisuallyComplete":95},{"time":28600,"image":"filmstrip/ms_028600.jpg","VisuallyComplete":95},{"time":28700,"image":"filmstrip/ms_028700.jpg","VisuallyComplete":95},{"time":28800,"image":"filmstrip/ms_028800.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":318,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>This sort of omnishambles is what folks mean when they say that <a href="https://www.jonoalderson.com/conjecture/javascript-broke-the-web-and-called-it-progress/"><em>&quot;JavaScript broke the web and called it progress&quot;.</em></a></p>
<p></p><figure><picture style="--lqip: -8413" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/traces/250627_ZiDc7Q_4ES/runs/1/firstView/timeline.gif" alt="Is waiting 30 seconds for a loading spinner bad?<br>Asking for an industry." style="aspect-ratio: 520 / 680" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Is waiting 30 seconds for a loading spinner bad?<br />Asking for an industry.</figcaption>      </figure><p></p>
<p>The other poster child for Expo is Bluesky, a site that also serves web and React Native from the same codebase. It's so bewilderingly laden with React-ish excesses that their engineering choices qualify as gifts-in-kind to Elon Musk and Mark Zuckerberg:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" end="visual" interval="500ms">
      <wpt-test label="Pinafore.social, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDc5F_2SX","url":"https://pinafore.social/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDc5F_2SX","testUrl":"https://pinafore.social/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750922263,"testRuns":1,"testName":"250626_ZiDc5F_2SX","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://pinafore.social/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.822},{"start":"0.10","end":"0.25","density":0.0772},{"start":"0.25","density":0.1008}],"percentiles":{"p75":"0.03"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.931},{"start":800,"end":1800,"density":0.052},{"start":1800,"density":0.017}],"percentiles":{"p75":130}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.9733},{"start":1800,"end":3000,"density":0.0167},{"start":3000,"density":0.01}],"percentiles":{"p75":398}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.9884},{"start":200,"end":500,"density":0.0088},{"start":500,"density":0.0028}],"percentiles":{"p75":48}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.8994},{"start":2500,"end":4000,"density":0.0301},{"start":4000,"density":0.0705}],"percentiles":{"p75":1116}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.6459},{"start":75,"end":275,"density":0.2738},{"start":275,"density":0.0803}],"percentiles":{"p75":123}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":28},"lastDate":{"year":2025,"month":6,"day":24}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDc5F_2SX/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDc5F/2SX/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDc5F/2SX/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDc5F/2SX/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDc5F_2SX&file=1_screen.jpg"},"breakdown":{"html":{"bytes":16160,"bytesUncompressed":54887,"requests":2},"js":{"bytes":389209,"bytesUncompressed":1267122,"requests":99},"css":{"bytes":17629,"bytesUncompressed":59782,"requests":16},"image":{"bytes":69526,"bytesUncompressed":86240,"requests":24},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":0,"bytesUncompressed":0,"requests":0},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":1246,"bytesUncompressed":4056,"requests":2}},"loadTime":1797,"docTime":1797,"fullyLoaded":10256,"firstPaint":732,"firstContentfulPaint":732,"firstMeaningfulPaint":732,"lastVisualChange":700,"visualComplete":700,"visualComplete85":700,"visualComplete90":700,"visualComplete95":700,"visualComplete99":700,"SpeedIndex":700,"TotalBlockingTime":0,"layoutShifts":[],"lcps":[732],"navigationStart":659,"fetchStart":34,"domLoading":667,"responseEnd":664,"domInteractive":1076,"domContentLoadedEventStart":1076,"domContentLoadedEventEnd":1076,"domComplete":1796,"unloadEventStart":666,"unloadEventEnd":666,"markAsMainFrame":666,"commitNavigationEnd":667,"firstMeaningfulPaintCandidate":732,"InteractiveTime":1076,"loadEventStart":1796,"loadEventEnd":1796,"LargestTextPaint":732,"LargestContentfulPaint":732,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":700,"image":"filmstrip/ms_000700.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":37,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="Elk.zone, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDc17_24Z","url":"https://elk.zone/toot.cafe/@slightlyoff","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDc17_24Z","testUrl":"https://elk.zone/toot.cafe/@slightlyoff","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750918141,"testRuns":1,"testName":"250626_ZiDc17_24Z","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDc17_24Z/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDc17/24Z/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDc17/24Z/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDc17/24Z/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDc17_24Z&file=1_screen.jpg"},"breakdown":{"html":{"bytes":9005,"bytesUncompressed":22865,"requests":1},"js":{"bytes":1348181,"bytesUncompressed":5685413,"requests":207},"css":{"bytes":48258,"bytesUncompressed":240810,"requests":12},"image":{"bytes":941623,"bytesUncompressed":945672,"requests":15},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":59223,"bytesUncompressed":108704,"requests":1},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":50353,"bytesUncompressed":374716,"requests":13}},"loadTime":1833,"docTime":1833,"fullyLoaded":29959,"firstPaint":1459,"firstContentfulPaint":1459,"firstMeaningfulPaint":3297,"lastVisualChange":5400,"visualComplete":5400,"visualComplete85":3300,"visualComplete90":3500,"visualComplete95":5000,"visualComplete99":5200,"SpeedIndex":3435,"TotalBlockingTime":168,"layoutShifts":[3413,3568],"lcps":[5010],"navigationStart":772,"fetchStart":64,"domLoading":781,"responseEnd":778,"domInteractive":1386,"domContentLoadedEventStart":1833,"domContentLoadedEventEnd":1833,"domComplete":1833,"unloadEventStart":779,"unloadEventEnd":779,"markAsMainFrame":780,"commitNavigationEnd":780,"firstMeaningfulPaintCandidate":3297,"loadEventStart":1833,"loadEventEnd":1833,"firstImagePaint":3297,"InteractiveTime":4121,"LargestTextPaint":3297,"LargestImagePaint":5010,"LargestContentfulPaint":5010,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":1400,"image":"filmstrip/ms_001400.jpg","VisuallyComplete":1},{"time":3300,"image":"filmstrip/ms_003300.jpg","VisuallyComplete":87},{"time":3400,"image":"filmstrip/ms_003400.jpg","VisuallyComplete":87},{"time":3500,"image":"filmstrip/ms_003500.jpg","VisuallyComplete":91},{"time":3600,"image":"filmstrip/ms_003600.jpg","VisuallyComplete":91},{"time":3700,"image":"filmstrip/ms_003700.jpg","VisuallyComplete":90},{"time":4200,"image":"filmstrip/ms_004200.jpg","VisuallyComplete":91},{"time":4400,"image":"filmstrip/ms_004400.jpg","VisuallyComplete":94},{"time":5000,"image":"filmstrip/ms_005000.jpg","VisuallyComplete":98},{"time":5100,"image":"filmstrip/ms_005100.jpg","VisuallyComplete":98},{"time":5200,"image":"filmstrip/ms_005200.jpg","VisuallyComplete":99},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":84,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="Bsky.app, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcGE_24F","url":"https://bsky.app/profile/infrequently.org","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcGE_24F","testUrl":"https://bsky.app/profile/infrequently.org","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750918139,"testRuns":1,"testName":"250626_ZiDcGE_24F","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcGE_24F&file=1_screen.jpg"},"breakdown":{"html":{"bytes":2684,"bytesUncompressed":6195,"requests":1},"js":{"bytes":2166759,"bytesUncompressed":7441480,"requests":4},"css":{"bytes":2778,"bytesUncompressed":9529,"requests":1},"image":{"bytes":2784185,"bytesUncompressed":2784185,"requests":75},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":352240,"bytesUncompressed":352240,"requests":1},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":53354,"bytesUncompressed":244530,"requests":24}},"loadTime":5281,"docTime":5281,"fullyLoaded":14905,"firstPaint":2703,"firstContentfulPaint":2703,"firstMeaningfulPaint":5440,"lastVisualChange":9800,"visualComplete":9800,"visualComplete85":8900,"visualComplete90":8900,"visualComplete95":8900,"visualComplete99":8900,"SpeedIndex":7702,"TotalBlockingTime":1322,"layoutShifts":[6296],"lcps":[8950],"navigationStart":126,"fetchStart":108,"domLoading":938,"responseEnd":933,"domInteractive":956,"domContentLoadedEventStart":4748,"domContentLoadedEventEnd":4748,"domComplete":5280,"unloadEventStart":938,"unloadEventEnd":938,"markAsMainFrame":938,"commitNavigationEnd":938,"firstMeaningfulPaintCandidate":5440,"loadEventStart":5280,"loadEventEnd":5280,"firstImagePaint":8490,"InteractiveTime":9780,"LargestTextPaint":8490,"LargestImagePaint":8950,"LargestContentfulPaint":8950,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2700,"image":"filmstrip/ms_002700.jpg","VisuallyComplete":2},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":0},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":21},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":25},{"time":6700,"image":"filmstrip/ms_006700.jpg","VisuallyComplete":26},{"time":7200,"image":"filmstrip/ms_007200.jpg","VisuallyComplete":40},{"time":8500,"image":"filmstrip/ms_008500.jpg","VisuallyComplete":56},{"time":8700,"image":"filmstrip/ms_008700.jpg","VisuallyComplete":57},{"time":8900,"image":"filmstrip/ms_008900.jpg","VisuallyComplete":99},{"time":9800,"image":"filmstrip/ms_009800.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":128,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>Why is Bluesky so slow? A huge, steaming pile of critical-path <abbr title="JavaScript">JS</abbr>, same as Burger King:</p>
<br style="display: none;" />
<wpt-filmstrip filmstrip="false" waterfall="true" breakdown="true">
      <wpt-test label="Bsky.app, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcGE_24F","url":"https://bsky.app/profile/infrequently.org","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcGE_24F","testUrl":"https://bsky.app/profile/infrequently.org","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750918139,"testRuns":1,"testName":"250626_ZiDcGE_24F","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcGE_24F/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcGE/24F/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcGE_24F&file=1_screen.jpg"},"breakdown":{"html":{"bytes":2684,"bytesUncompressed":6195,"requests":1},"js":{"bytes":2166759,"bytesUncompressed":7441480,"requests":4},"css":{"bytes":2778,"bytesUncompressed":9529,"requests":1},"image":{"bytes":2784185,"bytesUncompressed":2784185,"requests":75},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":352240,"bytesUncompressed":352240,"requests":1},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":53354,"bytesUncompressed":244530,"requests":24}},"loadTime":5281,"docTime":5281,"fullyLoaded":14905,"firstPaint":2703,"firstContentfulPaint":2703,"firstMeaningfulPaint":5440,"lastVisualChange":9800,"visualComplete":9800,"visualComplete85":8900,"visualComplete90":8900,"visualComplete95":8900,"visualComplete99":8900,"SpeedIndex":7702,"TotalBlockingTime":1322,"layoutShifts":[6296],"lcps":[8950],"navigationStart":126,"fetchStart":108,"domLoading":938,"responseEnd":933,"domInteractive":956,"domContentLoadedEventStart":4748,"domContentLoadedEventEnd":4748,"domComplete":5280,"unloadEventStart":938,"unloadEventEnd":938,"markAsMainFrame":938,"commitNavigationEnd":938,"firstMeaningfulPaintCandidate":5440,"loadEventStart":5280,"loadEventEnd":5280,"firstImagePaint":8490,"InteractiveTime":9780,"LargestTextPaint":8490,"LargestImagePaint":8950,"LargestContentfulPaint":8950,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2700,"image":"filmstrip/ms_002700.jpg","VisuallyComplete":2},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":0},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":21},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":25},{"time":6700,"image":"filmstrip/ms_006700.jpg","VisuallyComplete":26},{"time":7200,"image":"filmstrip/ms_007200.jpg","VisuallyComplete":40},{"time":8500,"image":"filmstrip/ms_008500.jpg","VisuallyComplete":56},{"time":8700,"image":"filmstrip/ms_008700.jpg","VisuallyComplete":57},{"time":8900,"image":"filmstrip/ms_008900.jpg","VisuallyComplete":99},{"time":9800,"image":"filmstrip/ms_009800.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":128,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>Again, we don't need to look deeply into the black box to understand that there's something rotten about the compromises involved in choosing React Native + Expo + React Web. This combination clearly prevents teams from effectively managing performance or even adding offline resilience via Service Workers. Pinafore and Elk manage to get both right, providing great <abbr title="Progressive Web App">PWA</abbr> experiences while being built on a comparative shoestring. It's possible to build a great social <abbr title="Single Page App">SPA</abbr> experience, but maybe just not with React:</p>
<p></p><figure class="full_wide"><picture style="--lqip: 524067" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/traces/pinafore-vs-elk-vs-bsky-first-load.gif" alt="If we're going to get out of this mess, we need to stop conflating failure with success. The <em>entire point</em> of this tech was to deliver better user experiences, and so the essential job of management is to ask: does it?" style="aspect-ratio: 904 / 256" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>If we're going to get out of this mess, we need to stop conflating failure with success. The <em>entire point</em> of this tech was to deliver better user experiences, and so the essential job of management is to ask: does it?</figcaption>      </figure><p></p>
<p>The unflattering comparisons are everywhere when you start looking. <a href="https://tannerlinsley.com/">Tanner Linsley's</a> talk on TanStack (not yet online) was, in essence, a victory lap. It promised high quality web software and better time-to-market, leaning on popularity contest results and unverifiable, untested claims about productivity to pitch the assembled. To say that this mode of argument is methodologically unsound is an understatement. Rejecting it is necessary if we're going to do engineering rather that marketing.</p>
<p></p><figure class="full_wide"><a href="https://tanstack.com/" alt="Popularity is not an accepted unit of engineering quality measurement." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/stars-in-your-eyes.avif" alt="Popularity is not an accepted unit of engineering quality measurement." style="aspect-ratio: 1674 / 316" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Popularity is not an accepted unit of engineering quality measurement.</figcaption>      </figure><p></p>
<p>The TanStack website <a href="https://tanstack.com/stats/npm">cites this social proof</a> as an argument for why their software is great, but the proof of the pudding is in the eating:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" end="lcp" interval="100ms" id="dev-sites">
      <wpt-test label="astro.build, LCP, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcZF_9A7","url":"https://astro.build/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcZF_9A7","testUrl":"https://astro.build/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750974194,"testRuns":1,"testName":"250626_ZiDcZF_9A7","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://astro.build/"},"metrics":{"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.9876},{"start":200,"end":500,"density":0.0087},{"start":500,"density":0.0036}],"percentiles":{"p75":41}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.9739},{"start":2500,"end":4000,"density":0.0151},{"start":4000,"density":0.011}],"percentiles":{"p75":823}},"navigation_types":{"fractions":{"restore":0.0062,"back_forward":0.0205,"back_forward_cache":0.0815,"prerender":0.0291,"navigate":0.7314,"navigate_cache":0.1122,"reload":0.019}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.6202},{"start":75,"end":275,"density":0.3383},{"start":275,"density":0.0415}],"percentiles":{"p75":101}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":142}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":376}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":35}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":133}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.0078,"text":0.9922}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.9847},{"start":"0.10","end":"0.25","density":0.0067},{"start":"0.25","density":0.0086}],"percentiles":{"p75":"0.00"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.9126},{"start":800,"end":1800,"density":0.0653},{"start":1800,"density":0.0221}],"percentiles":{"p75":359}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.9504},{"start":1800,"end":3000,"density":0.0311},{"start":3000,"density":0.0185}],"percentiles":{"p75":826}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":28},"lastDate":{"year":2025,"month":6,"day":24}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcZF_9A7/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcZF/9A7/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcZF/9A7/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcZF/9A7/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcZF_9A7&file=1_screen.jpg"},"breakdown":{"html":{"bytes":42370,"bytesUncompressed":270911,"requests":2},"js":{"bytes":11147,"bytesUncompressed":28882,"requests":9},"css":{"bytes":18071,"bytesUncompressed":108410,"requests":2},"image":{"bytes":17838,"bytesUncompressed":18543,"requests":3},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":181544,"bytesUncompressed":181544,"requests":2},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":0,"bytesUncompressed":0,"requests":0}},"loadTime":1818,"docTime":1818,"fullyLoaded":1947,"firstPaint":1574,"firstContentfulPaint":1574,"firstMeaningfulPaint":1574,"lastVisualChange":1700,"visualComplete":1700,"visualComplete85":1700,"visualComplete90":1700,"visualComplete95":1700,"visualComplete99":1700,"SpeedIndex":1688,"TotalBlockingTime":23,"layoutShifts":[],"lcps":[1574],"navigationStart":90,"fetchStart":67,"domLoading":779,"responseEnd":951,"domInteractive":1514,"domContentLoadedEventStart":1618,"domContentLoadedEventEnd":1618,"domComplete":1817,"unloadEventStart":779,"unloadEventEnd":779,"markAsMainFrame":779,"commitNavigationEnd":779,"firstMeaningfulPaintCandidate":1574,"firstImagePaint":1574,"loadEventStart":1817,"loadEventEnd":1818,"LargestTextPaint":1574,"LargestContentfulPaint":1574,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":1400,"image":"filmstrip/ms_001400.jpg","VisuallyComplete":2},{"time":1600,"image":"filmstrip/ms_001600.jpg","VisuallyComplete":8},{"time":1700,"image":"filmstrip/ms_001700.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":47,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="hotwired.dev, LCP, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcDF_9A4","url":"https://hotwired.dev/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcDF_9A4","testUrl":"https://hotwired.dev/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750974203,"testRuns":1,"testName":"250626_ZiDcDF_9A4","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://hotwired.dev/"},"metrics":{"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.9201},{"start":800,"end":1800,"density":0.0542},{"start":1800,"density":0.0257}],"percentiles":{"p75":417}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.9846},{"start":200,"end":500,"density":0.0116},{"start":500,"density":0.0038}],"percentiles":{"p75":40}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":139}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":270}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":222}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.651},{"start":75,"end":275,"density":0.3056},{"start":275,"density":0.0434}],"percentiles":{"p75":95}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.9402},{"start":"0.10","end":"0.25","density":0},{"start":"0.25","density":0.0598}],"percentiles":{"p75":"0.00"}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.9684},{"start":1800,"end":3000,"density":0.019},{"start":3000,"density":0.0126}],"percentiles":{"p75":754}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.9725},{"start":2500,"end":4000,"density":0.0161},{"start":4000,"density":0.0114}],"percentiles":{"p75":1121}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":391}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.6737,"text":0.3263}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":28},"lastDate":{"year":2025,"month":6,"day":24}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcDF_9A4/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcDF/9A4/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcDF/9A4/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcDF/9A4/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcDF_9A4&file=1_screen.jpg"},"breakdown":{"html":{"bytes":3511,"bytesUncompressed":9040,"requests":1},"js":{"bytes":1817,"bytesUncompressed":3645,"requests":2},"css":{"bytes":3600,"bytesUncompressed":14407,"requests":1},"image":{"bytes":75676,"bytesUncompressed":98279,"requests":10},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":54032,"bytesUncompressed":54032,"requests":2},"video":{"bytes":3876510,"bytesUncompressed":1015288,"requests":3},"other":{"bytes":9080,"bytesUncompressed":30692,"requests":2}},"loadTime":4090,"docTime":4090,"fullyLoaded":4617,"firstPaint":1385,"firstContentfulPaint":1385,"firstMeaningfulPaint":1385,"lastVisualChange":7600,"visualComplete":2200,"visualComplete85":1300,"visualComplete90":1300,"visualComplete95":1400,"visualComplete99":1600,"SpeedIndex":1355,"TotalBlockingTime":0,"layoutShifts":[],"lcps":[1676],"navigationStart":49,"fetchStart":39,"domLoading":779,"responseEnd":740,"domInteractive":837,"domContentLoadedEventStart":1558,"domContentLoadedEventEnd":1561,"domComplete":4090,"unloadEventStart":745,"unloadEventEnd":745,"markAsMainFrame":746,"commitNavigationEnd":778,"firstMeaningfulPaintCandidate":1385,"InteractiveTime":1561,"firstImagePaint":1576,"loadEventStart":4090,"loadEventEnd":4092,"LargestTextPaint":1385,"LargestImagePaint":1676,"LargestContentfulPaint":1676,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":1300,"image":"filmstrip/ms_001300.jpg","VisuallyComplete":93},{"time":1400,"image":"filmstrip/ms_001400.jpg","VisuallyComplete":96},{"time":1500,"image":"filmstrip/ms_001500.jpg","VisuallyComplete":97},{"time":1600,"image":"filmstrip/ms_001600.jpg","VisuallyComplete":99},{"time":1700,"image":"filmstrip/ms_001700.jpg","VisuallyComplete":99},{"time":1800,"image":"filmstrip/ms_001800.jpg","VisuallyComplete":99},{"time":1900,"image":"filmstrip/ms_001900.jpg","VisuallyComplete":99},{"time":2000,"image":"filmstrip/ms_002000.jpg","VisuallyComplete":99},{"time":2100,"image":"filmstrip/ms_002100.jpg","VisuallyComplete":99},{"time":2200,"image":"filmstrip/ms_002200.jpg","VisuallyComplete":100},{"time":2300,"image":"filmstrip/ms_002300.jpg","VisuallyComplete":99},{"time":2400,"image":"filmstrip/ms_002400.jpg","VisuallyComplete":99},{"time":2500,"image":"filmstrip/ms_002500.jpg","VisuallyComplete":100},{"time":2600,"image":"filmstrip/ms_002600.jpg","VisuallyComplete":99},{"time":2700,"image":"filmstrip/ms_002700.jpg","VisuallyComplete":99},{"time":2800,"image":"filmstrip/ms_002800.jpg","VisuallyComplete":100},{"time":2900,"image":"filmstrip/ms_002900.jpg","VisuallyComplete":99},{"time":3000,"image":"filmstrip/ms_003000.jpg","VisuallyComplete":99},{"time":3100,"image":"filmstrip/ms_003100.jpg","VisuallyComplete":100},{"time":3200,"image":"filmstrip/ms_003200.jpg","VisuallyComplete":99},{"time":3300,"image":"filmstrip/ms_003300.jpg","VisuallyComplete":99},{"time":3400,"image":"filmstrip/ms_003400.jpg","VisuallyComplete":100},{"time":3500,"image":"filmstrip/ms_003500.jpg","VisuallyComplete":99},{"time":3600,"image":"filmstrip/ms_003600.jpg","VisuallyComplete":99},{"time":3700,"image":"filmstrip/ms_003700.jpg","VisuallyComplete":100},{"time":3800,"image":"filmstrip/ms_003800.jpg","VisuallyComplete":99},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":99},{"time":4000,"image":"filmstrip/ms_004000.jpg","VisuallyComplete":100},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":99},{"time":4200,"image":"filmstrip/ms_004200.jpg","VisuallyComplete":99},{"time":4300,"image":"filmstrip/ms_004300.jpg","VisuallyComplete":100},{"time":4400,"image":"filmstrip/ms_004400.jpg","VisuallyComplete":99},{"time":4500,"image":"filmstrip/ms_004500.jpg","VisuallyComplete":99},{"time":4600,"image":"filmstrip/ms_004600.jpg","VisuallyComplete":100},{"time":4700,"image":"filmstrip/ms_004700.jpg","VisuallyComplete":99},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":99},{"time":4900,"image":"filmstrip/ms_004900.jpg","VisuallyComplete":100},{"time":5000,"image":"filmstrip/ms_005000.jpg","VisuallyComplete":99},{"time":5100,"image":"filmstrip/ms_005100.jpg","VisuallyComplete":99},{"time":5200,"image":"filmstrip/ms_005200.jpg","VisuallyComplete":100},{"time":5300,"image":"filmstrip/ms_005300.jpg","VisuallyComplete":99},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":99},{"time":5500,"image":"filmstrip/ms_005500.jpg","VisuallyComplete":100},{"time":5600,"image":"filmstrip/ms_005600.jpg","VisuallyComplete":99},{"time":5700,"image":"filmstrip/ms_005700.jpg","VisuallyComplete":99},{"time":5800,"image":"filmstrip/ms_005800.jpg","VisuallyComplete":100},{"time":5900,"image":"filmstrip/ms_005900.jpg","VisuallyComplete":99},{"time":6000,"image":"filmstrip/ms_006000.jpg","VisuallyComplete":99},{"time":6100,"image":"filmstrip/ms_006100.jpg","VisuallyComplete":100},{"time":6200,"image":"filmstrip/ms_006200.jpg","VisuallyComplete":99},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":99},{"time":6500,"image":"filmstrip/ms_006500.jpg","VisuallyComplete":99},{"time":7000,"image":"filmstrip/ms_007000.jpg","VisuallyComplete":100},{"time":7500,"image":"filmstrip/ms_007500.jpg","VisuallyComplete":99},{"time":7600,"image":"filmstrip/ms_007600.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":52,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="11ty.dev, LCP, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcAS_9A2","url":"https://11ty.dev/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcAS_9A2","testUrl":"https://11ty.dev/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750974137,"testRuns":1,"testName":"250626_ZiDcAS_9A2","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcAS_9A2/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcAS/9A2/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcAS/9A2/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcAS/9A2/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcAS_9A2&file=1_screen.jpg"},"breakdown":{"html":{"bytes":36643,"bytesUncompressed":150133,"requests":2},"js":{"bytes":13076,"bytesUncompressed":42224,"requests":2},"css":{"bytes":9870,"bytesUncompressed":37124,"requests":1},"image":{"bytes":15142,"bytesUncompressed":15142,"requests":2},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":21588,"bytesUncompressed":21588,"requests":2},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":0,"bytesUncompressed":0,"requests":0}},"loadTime":2166,"docTime":2166,"fullyLoaded":2397,"firstPaint":2016,"firstContentfulPaint":2016,"firstMeaningfulPaint":2016,"lastVisualChange":5500,"visualComplete":5500,"visualComplete85":2100,"visualComplete90":2100,"visualComplete95":2100,"visualComplete99":2300,"SpeedIndex":2137,"TotalBlockingTime":0,"layoutShifts":[1975],"lcps":[2016],"navigationStart":74,"redirectStart":65,"domLoading":1608,"responseEnd":1730,"domInteractive":1980,"domContentLoadedEventStart":2045,"domContentLoadedEventEnd":2045,"domComplete":2165,"redirectEnd":808,"fetchStart":808,"unloadEventStart":1606,"unloadEventEnd":1606,"markAsMainFrame":1607,"commitNavigationEnd":1607,"firstMeaningfulPaintCandidate":2016,"firstImagePaint":2153,"loadEventStart":2166,"loadEventEnd":2166,"LargestTextPaint":2016,"LargestImagePaint":2538,"LargestContentfulPaint":2016,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2100,"image":"filmstrip/ms_002100.jpg","VisuallyComplete":97},{"time":2200,"image":"filmstrip/ms_002200.jpg","VisuallyComplete":98},{"time":2300,"image":"filmstrip/ms_002300.jpg","VisuallyComplete":99},{"time":2600,"image":"filmstrip/ms_002600.jpg","VisuallyComplete":99},{"time":2700,"image":"filmstrip/ms_002700.jpg","VisuallyComplete":99},{"time":2800,"image":"filmstrip/ms_002800.jpg","VisuallyComplete":99},{"time":2900,"image":"filmstrip/ms_002900.jpg","VisuallyComplete":99},{"time":3000,"image":"filmstrip/ms_003000.jpg","VisuallyComplete":99},{"time":3100,"image":"filmstrip/ms_003100.jpg","VisuallyComplete":99},{"time":3200,"image":"filmstrip/ms_003200.jpg","VisuallyComplete":99},{"time":3300,"image":"filmstrip/ms_003300.jpg","VisuallyComplete":99},{"time":3400,"image":"filmstrip/ms_003400.jpg","VisuallyComplete":99},{"time":3500,"image":"filmstrip/ms_003500.jpg","VisuallyComplete":99},{"time":3600,"image":"filmstrip/ms_003600.jpg","VisuallyComplete":99},{"time":3700,"image":"filmstrip/ms_003700.jpg","VisuallyComplete":99},{"time":3800,"image":"filmstrip/ms_003800.jpg","VisuallyComplete":99},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":99},{"time":4000,"image":"filmstrip/ms_004000.jpg","VisuallyComplete":99},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":99},{"time":4200,"image":"filmstrip/ms_004200.jpg","VisuallyComplete":99},{"time":4300,"image":"filmstrip/ms_004300.jpg","VisuallyComplete":99},{"time":4400,"image":"filmstrip/ms_004400.jpg","VisuallyComplete":99},{"time":4500,"image":"filmstrip/ms_004500.jpg","VisuallyComplete":99},{"time":4600,"image":"filmstrip/ms_004600.jpg","VisuallyComplete":99},{"time":4700,"image":"filmstrip/ms_004700.jpg","VisuallyComplete":99},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":99},{"time":4900,"image":"filmstrip/ms_004900.jpg","VisuallyComplete":99},{"time":5000,"image":"filmstrip/ms_005000.jpg","VisuallyComplete":99},{"time":5100,"image":"filmstrip/ms_005100.jpg","VisuallyComplete":99},{"time":5200,"image":"filmstrip/ms_005200.jpg","VisuallyComplete":99},{"time":5300,"image":"filmstrip/ms_005300.jpg","VisuallyComplete":99},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":99},{"time":5500,"image":"filmstrip/ms_005500.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":85,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="expo.dev, LCP, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDcVG_9A1","url":"https://expo.dev/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDcVG_9A1","testUrl":"https://expo.dev/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750974088,"testRuns":1,"testName":"250626_ZiDcVG_9A1","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://expo.dev/"},"metrics":{"navigation_types":{"fractions":{"reload":0.0177,"restore":0.012,"back_forward":0.015,"back_forward_cache":0,"prerender":0.0238,"navigate":0.9314,"navigate_cache":0}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.4979},{"start":75,"end":275,"density":0.4201},{"start":275,"density":0.082}],"percentiles":{"p75":138}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.9481},{"start":"0.10","end":"0.25","density":0.0441},{"start":"0.25","density":0.0078}],"percentiles":{"p75":"0.06"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8182},{"start":800,"end":1800,"density":0.1399},{"start":1800,"density":0.042}],"percentiles":{"p75":666}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.824},{"start":1800,"end":3000,"density":0.1104},{"start":3000,"density":0.0656}],"percentiles":{"p75":1492}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.7891},{"start":2500,"end":4000,"density":0.0666},{"start":4000,"density":0.1443}],"percentiles":{"p75":2146}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":377}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.8324,"text":0.1676}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.9099},{"start":200,"end":500,"density":0.0601},{"start":500,"density":0.03}],"percentiles":{"p75":101}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":633}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":177}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":597}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":28},"lastDate":{"year":2025,"month":6,"day":24}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDcVG_9A1/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDcVG/9A1/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDcVG/9A1/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDcVG/9A1/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDcVG_9A1&file=1_screen.jpg"},"breakdown":{"html":{"bytes":51580,"bytesUncompressed":241303,"requests":4},"js":{"bytes":1526053,"bytesUncompressed":5037620,"requests":42},"css":{"bytes":45774,"bytesUncompressed":262448,"requests":3},"image":{"bytes":405463,"bytesUncompressed":424344,"requests":24},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":88912,"bytesUncompressed":88912,"requests":2},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":1705,"bytesUncompressed":2314,"requests":25}},"loadTime":8409,"docTime":8409,"fullyLoaded":13679,"firstPaint":2322,"firstContentfulPaint":2322,"firstMeaningfulPaint":2322,"lastVisualChange":14000,"visualComplete":14000,"visualComplete85":13900,"visualComplete90":14000,"visualComplete95":14000,"visualComplete99":14000,"SpeedIndex":5015,"TotalBlockingTime":579,"layoutShifts":[2244,3437],"lcps":[3307],"navigationStart":119,"fetchStart":101,"domLoading":760,"responseEnd":1139,"domInteractive":1772,"domContentLoadedEventStart":3236,"domContentLoadedEventEnd":3236,"domComplete":8403,"unloadEventStart":760,"unloadEventEnd":760,"markAsMainFrame":760,"commitNavigationEnd":760,"firstImagePaint":2322,"firstMeaningfulPaintCandidate":2322,"loadEventStart":8408,"loadEventEnd":8430,"LargestTextPaint":2322,"LargestImagePaint":3307,"LargestContentfulPaint":3307,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2300,"image":"filmstrip/ms_002300.jpg","VisuallyComplete":44},{"time":2400,"image":"filmstrip/ms_002400.jpg","VisuallyComplete":43},{"time":3300,"image":"filmstrip/ms_003300.jpg","VisuallyComplete":53},{"time":3500,"image":"filmstrip/ms_003500.jpg","VisuallyComplete":80},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":80},{"time":8600,"image":"filmstrip/ms_008600.jpg","VisuallyComplete":61},{"time":8700,"image":"filmstrip/ms_008700.jpg","VisuallyComplete":61},{"time":8800,"image":"filmstrip/ms_008800.jpg","VisuallyComplete":75},{"time":8900,"image":"filmstrip/ms_008900.jpg","VisuallyComplete":78},{"time":9000,"image":"filmstrip/ms_009000.jpg","VisuallyComplete":82},{"time":13600,"image":"filmstrip/ms_013600.jpg","VisuallyComplete":73},{"time":13700,"image":"filmstrip/ms_013700.jpg","VisuallyComplete":78},{"time":13800,"image":"filmstrip/ms_013800.jpg","VisuallyComplete":81},{"time":13900,"image":"filmstrip/ms_013900.jpg","VisuallyComplete":89},{"time":14000,"image":"filmstrip/ms_014000.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":170,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
      <wpt-test label="tanstack.com, LCP, desktop, 9Mbps connection">        <script type="text/json" dir="/2025/06/conferences-clarity-and-smokescreens/traces/">          {"id":"250626_ZiDc15_99Z","url":"https://tanstack.com/","summary":"https://www.webpagetest.org/results.php?test=250626_ZiDc15_99Z","testUrl":"https://tanstack.com/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":0,"completed":1750974112,"testRuns":1,"testName":"250626_ZiDc15_99Z","optimizedImages":true,"crux":{"key":{"formFactor":"DESKTOP","url":"https://tanstack.com/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.8526},{"start":"0.10","end":"0.25","density":0.1066},{"start":"0.25","density":0.0408}],"percentiles":{"p75":"0.06"}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.362},{"start":200,"end":500,"density":0.4048},{"start":500,"density":0.2332}],"percentiles":{"p75":478}},"largest_contentful_paint_image_resource_load_duration":{"percentiles":{"p75":362}},"largest_contentful_paint_resource_type":{"fractions":{"image":0.9863,"text":0.0137}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8444},{"start":800,"end":1800,"density":0.1275},{"start":1800,"density":0.0281}],"percentiles":{"p75":624}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.8634},{"start":1800,"end":3000,"density":0.0865},{"start":3000,"density":0.0501}],"percentiles":{"p75":1282}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.9192},{"start":2500,"end":4000,"density":0.0466},{"start":4000,"density":0.0341}],"percentiles":{"p75":1402}},"largest_contentful_paint_image_element_render_delay":{"percentiles":{"p75":306}},"largest_contentful_paint_image_resource_load_delay":{"percentiles":{"p75":137}},"largest_contentful_paint_image_time_to_first_byte":{"percentiles":{"p75":597}},"navigation_types":{"fractions":{"navigate_cache":0,"reload":0.0513,"restore":0.0106,"back_forward":0.0147,"back_forward_cache":0,"prerender":0.0514,"navigate":0.872}},"round_trip_time":{"histogram":[{"start":0,"end":75,"density":0.5577},{"start":75,"end":275,"density":0.3871},{"start":275,"density":0.0553}],"percentiles":{"p75":116}}},"collectionPeriod":{"firstDate":{"year":2025,"month":5,"day":28},"lastDate":{"year":2025,"month":6,"day":24}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/details/","checklist":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/breakdown/","domains":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/domains/","screenShot":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/250626_ZiDc15_99Z/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/25/06/26/ZiDc15/99Z/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/25/06/26/ZiDc15/99Z/1_connection.png","checklist":"https://www.webpagetest.org/result/25/06/26/ZiDc15/99Z/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=250626_ZiDc15_99Z&file=1_screen.jpg"},"breakdown":{"html":{"bytes":73085,"bytesUncompressed":449896,"requests":14},"js":{"bytes":1143834,"bytesUncompressed":3754835,"requests":25},"css":{"bytes":18203,"bytesUncompressed":116235,"requests":3},"image":{"bytes":1009812,"bytesUncompressed":1052894,"requests":185},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":285972,"bytesUncompressed":285972,"requests":3},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":36413,"bytesUncompressed":83646,"requests":6}},"loadTime":7806,"docTime":7806,"fullyLoaded":11286,"firstPaint":2729,"firstContentfulPaint":2729,"firstMeaningfulPaint":2729,"lastVisualChange":14400,"visualComplete":14400,"visualComplete85":5200,"visualComplete90":5200,"visualComplete95":5200,"visualComplete99":5300,"SpeedIndex":4159,"TotalBlockingTime":366,"layoutShifts":[3451],"lcps":[4236],"navigationStart":79,"fetchStart":61,"domLoading":846,"responseEnd":859,"domInteractive":2705,"domContentLoadedEventStart":2871,"domContentLoadedEventEnd":2871,"domComplete":7806,"unloadEventStart":806,"unloadEventEnd":806,"markAsMainFrame":806,"commitNavigationEnd":846,"firstImagePaint":2729,"firstMeaningfulPaintCandidate":2729,"loadEventStart":7806,"loadEventEnd":7808,"LargestTextPaint":2729,"LargestImagePaint":4236,"LargestContentfulPaint":4236,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":2800,"image":"filmstrip/ms_002800.jpg","VisuallyComplete":31},{"time":2900,"image":"filmstrip/ms_002900.jpg","VisuallyComplete":31},{"time":3000,"image":"filmstrip/ms_003000.jpg","VisuallyComplete":31},{"time":3100,"image":"filmstrip/ms_003100.jpg","VisuallyComplete":31},{"time":3200,"image":"filmstrip/ms_003200.jpg","VisuallyComplete":31},{"time":3300,"image":"filmstrip/ms_003300.jpg","VisuallyComplete":34},{"time":3400,"image":"filmstrip/ms_003400.jpg","VisuallyComplete":35},{"time":3500,"image":"filmstrip/ms_003500.jpg","VisuallyComplete":36},{"time":3600,"image":"filmstrip/ms_003600.jpg","VisuallyComplete":40},{"time":3700,"image":"filmstrip/ms_003700.jpg","VisuallyComplete":44},{"time":3800,"image":"filmstrip/ms_003800.jpg","VisuallyComplete":49},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":53},{"time":4000,"image":"filmstrip/ms_004000.jpg","VisuallyComplete":48},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":48},{"time":4200,"image":"filmstrip/ms_004200.jpg","VisuallyComplete":49},{"time":4300,"image":"filmstrip/ms_004300.jpg","VisuallyComplete":49},{"time":4400,"image":"filmstrip/ms_004400.jpg","VisuallyComplete":46},{"time":4500,"image":"filmstrip/ms_004500.jpg","VisuallyComplete":49},{"time":4600,"image":"filmstrip/ms_004600.jpg","VisuallyComplete":51},{"time":4700,"image":"filmstrip/ms_004700.jpg","VisuallyComplete":59},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":63},{"time":4900,"image":"filmstrip/ms_004900.jpg","VisuallyComplete":68},{"time":5000,"image":"filmstrip/ms_005000.jpg","VisuallyComplete":76},{"time":5100,"image":"filmstrip/ms_005100.jpg","VisuallyComplete":84},{"time":5200,"image":"filmstrip/ms_005200.jpg","VisuallyComplete":96},{"time":5300,"image":"filmstrip/ms_005300.jpg","VisuallyComplete":99},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":99},{"time":5500,"image":"filmstrip/ms_005500.jpg","VisuallyComplete":99},{"time":5600,"image":"filmstrip/ms_005600.jpg","VisuallyComplete":99},{"time":5700,"image":"filmstrip/ms_005700.jpg","VisuallyComplete":99},{"time":5800,"image":"filmstrip/ms_005800.jpg","VisuallyComplete":99},{"time":5900,"image":"filmstrip/ms_005900.jpg","VisuallyComplete":99},{"time":6000,"image":"filmstrip/ms_006000.jpg","VisuallyComplete":99},{"time":6100,"image":"filmstrip/ms_006100.jpg","VisuallyComplete":99},{"time":6200,"image":"filmstrip/ms_006200.jpg","VisuallyComplete":99},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":99},{"time":6400,"image":"filmstrip/ms_006400.jpg","VisuallyComplete":99},{"time":6500,"image":"filmstrip/ms_006500.jpg","VisuallyComplete":99},{"time":6600,"image":"filmstrip/ms_006600.jpg","VisuallyComplete":99},{"time":6700,"image":"filmstrip/ms_006700.jpg","VisuallyComplete":99},{"time":6800,"image":"filmstrip/ms_006800.jpg","VisuallyComplete":99},{"time":6900,"image":"filmstrip/ms_006900.jpg","VisuallyComplete":99},{"time":7000,"image":"filmstrip/ms_007000.jpg","VisuallyComplete":99},{"time":7100,"image":"filmstrip/ms_007100.jpg","VisuallyComplete":99},{"time":7200,"image":"filmstrip/ms_007200.jpg","VisuallyComplete":99},{"time":7300,"image":"filmstrip/ms_007300.jpg","VisuallyComplete":99},{"time":7400,"image":"filmstrip/ms_007400.jpg","VisuallyComplete":99},{"time":7500,"image":"filmstrip/ms_007500.jpg","VisuallyComplete":99},{"time":7600,"image":"filmstrip/ms_007600.jpg","VisuallyComplete":99},{"time":7700,"image":"filmstrip/ms_007700.jpg","VisuallyComplete":99},{"time":7800,"image":"filmstrip/ms_007800.jpg","VisuallyComplete":99},{"time":8000,"image":"filmstrip/ms_008000.jpg","VisuallyComplete":99},{"time":8500,"image":"filmstrip/ms_008500.jpg","VisuallyComplete":99},{"time":9000,"image":"filmstrip/ms_009000.jpg","VisuallyComplete":99},{"time":9500,"image":"filmstrip/ms_009500.jpg","VisuallyComplete":99},{"time":10000,"image":"filmstrip/ms_010000.jpg","VisuallyComplete":99},{"time":10500,"image":"filmstrip/ms_010500.jpg","VisuallyComplete":99},{"time":11000,"image":"filmstrip/ms_011000.jpg","VisuallyComplete":99},{"time":11500,"image":"filmstrip/ms_011500.jpg","VisuallyComplete":99},{"time":12000,"image":"filmstrip/ms_012000.jpg","VisuallyComplete":99},{"time":12500,"image":"filmstrip/ms_012500.jpg","VisuallyComplete":99},{"time":13000,"image":"filmstrip/ms_013000.jpg","VisuallyComplete":99},{"time":14000,"image":"filmstrip/ms_014000.jpg","VisuallyComplete":99},{"time":14400,"image":"filmstrip/ms_014400.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":400,"height":199,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":400,"height":199}},"filmstripImageAspectRatio":"400 / 199","gifImageData":{"format":"gif","width":408,"height":312,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":174,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":408,"height":312}},"gifImageAspectRatio":"408 / 312"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>The contrast grows stark as we push further outside the privilege bubble. Here are the same sites, using the same network configuration as before, but with the <abbr title="Central Processing Unit">CPU</abbr> emulation modelling a cheap Android instead:</p>
<p></p><figure class="full_wide"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/traces/dev-sites-mobile-first-load.gif" alt="An absolute rout. The main difference? The amount of JS each site sends, which is a direct reflection of values and philosophy." style="aspect-ratio: 904 / 360" class="full_wide preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>An absolute rout. The main difference? The amount of <abbr title="JavaScript">JS</abbr> each site sends, which is a direct reflection of values and philosophy.</figcaption>      </figure><p></p>
<table class="summary" style="margin: auto; min-width: 100%;" id="kbs-and-tbt">  
  <thead>
    <tr>
      <th>Site</th>
      <th>Wire JS</th>
      <th>Decoded JS</th>
      <th>TBT (ms)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>astro.build</td>
      <td>11.1 kB</td>
      <td>28.9 kB</td>
      <td>23</td>
    </tr>
    <tr>
      <td>hotwired.dev</td>
      <td>1.8 kB</td>
      <td>3.6 kB</td>
      <td>0</td>
    </tr>
    <tr>
      <td>11ty.dev</td>
      <td>13.1 kB</td>
      <td>42.2 kB</td>
      <td>0</td>
    </tr>
    <tr>
      <td>expo.dev</td>
      <td>1,526.1 kB</td>
      <td>5,037.6 kB</td>
      <td>578</td>
    </tr>
    <tr>
      <td>tanstack.com</td>
      <td>1,143.8 kB</td>
      <td>3,754.8 kB</td>
      <td>366</td>
    </tr>
  </tbody>
</table>
<p>Yes, these websites target developers on fast machines. So what? The choices they make speak to the values of their creators. And those values shine through the fog of marketing when we use objective quality measures. The same sorts of engineers who care to shave a few bytes of <abbr title="JavaScript">JS</abbr> for users on fast machines will care about the lived <abbr title="User Experience">UX</abbr> quality of their approach all the way down the wealth curve. The opposite also holds.</p>
<p>It is my long experience that cultures that claim <em>&quot;it's fine&quot;</em> to pay for a lot of <abbr title="JavaScript">JS</abbr> up-front to gain (unquantified) benefits in another dimension almost never check to see if either side of the trade comes up good.</p>
<p><a href="https://www.baldurbjarnason.com/2022/programming-is-a-pop-culture/">Programming-as-pop-culture</a> is oppositional to the rigour required of engineering. We need to collectively recalibrate when the folks talking loudest about &quot;scale&quot; and &quot;high quality&quot; and &quot;delivery speed&quot; — without metrics or measurement — continually plop out crappy experiences but are given huge megaphones anyway.</p>
<p>There were some bright spots at React Summit, though. A few brave souls tried to sneak perspective in through the side door, and I applaud their efforts:</p>
<p></p><figure class="full_wide"><a href="https://www.youtube.com/live/aKfQ_ftodEg?si=nzFPQUbv1WfB_I4u&t=8498" alt="If the Q&A sessions after my talk are any indication, Luca faced serious risk of being ignored as a heretic for putting this on a slide." target="_blank"><picture style="--lqip: -521501" class="preview">      <img src="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/heresy.avif" alt="If the Q&A sessions after my talk are any indication, Luca faced serious risk of being ignored as a heretic for putting this on a slide." style="aspect-ratio: 1551 / 737" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>If the Q&amp;A sessions after my talk are any indication, Luca faced serious risk of being ignored as a heretic for putting this on a slide.</figcaption>      </figure><p></p>
<p>If frontend aspires to be a profession<sup class="footnote-ref"><a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fn-dont-at-me-11" id="fnref-dont-at-me-11">11</a></sup> — <a href="https://heydonworks.com/article/pride-shame-and-accessibility/">something we do for others, not just ourselves</a> — then we need a culture that <a href="https://deming.org/explore/fourteen-points/">can learn to use statistical methods for measuring quality</a> and reject the sorts of marketing that still dominates the React discourse.</p>
<p>And if that means we have to jettison React along the way, <a href="https://infrequently.org/2024/11/if-not-react-then-what/">so be it.</a></p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-structure-1" class="footnote-item"><p>For attendees, JSNation and React Summit were separate events, although one could buy <a href="https://jsnation.com/#tickets">passes that provided access to both</a>. My impression is that many did. As they were in the same venue, this may have simplified some logistics for the organisers, and it was a good way to structure content for adjacent, but not strictly overlapping, communities of interest. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-structure-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-pain-is-a-great-teacher-2" class="footnote-item"><p>Again, my thanks to the organisers for letting me sit in on this meeting. As with much of my work, my goal was to learn about what's top of mind to the folks solving problems for developers in order to prioritise work on the Web Platform.</p>
<p>Without giving away confidences from a closed-door meeting, I'll just say that it was refreshing to hear framework authors tell us that they need better <abbr title="HyperText Markup Language">HTML</abbr> elements and that JSX's default implementations are scaling exactly as poorly ecosystem-wide as theory and my own experience suggest. This is down to React's devil-may-care attitude to memory.</p>
<p>It's not unusual to see heavy GC stalls on the client as a result of Facebook's always-wrong assertion that browsers are magical and that <abbr title="Central Processing Unit">CPU</abbr> costs don't matter. But memory is a tricksy issue, and it it's a limiting factor on the server too.</p>
<p>Lots to chew on from those hours, and I thank the folks who participated for their candour, which was likely made easier since nobody from the React team deigned to join. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-pain-is-a-great-teacher-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-or-not-3" class="footnote-item"><p>Or worse, don't.</p>
<p>Luckily, some who experience the tug of conscience punch out and write about it. Any post-McKinsey tell-all will do, but <a href="https://en.wikipedia.org/wiki/Anand_Giridharadas">Anand Giridharadas</a> is particularly good value for money in the genre. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-or-not-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-round-and-round-4" class="footnote-item"><p>Circular logic is a constant in discussions with frameworkists. A few classics of the genre that got dusted off in conversations over the conference:</p>
<ul>
<li>
<p><em>&quot;The framework makes us more productive.&quot;</em></p>
<p>Oh? And what's the objective evidence for that productivity gain?</p>
<p>Surely, if it's large as frameworkists claim, economists would have noted the effects in aggregate statistics. But we have not seen that. Indeed, there's no credible evidence that we are seeing anything more than the bog-stock gains from learning in any technical field. The combinatorial complexity of <abbr title="JavaScript">JS</abbr> frameworks may, in itself, reduce those gains; we don't know, so we can't make claims either way.</p>
<p>Nobody's running real studies that compare proficient <abbr title="HyperText Markup Language">HTML</abbr>&amp;<abbr title="Cascading Style Sheets">CSS</abbr> or jQuery developers to React developers under objective criteria. In the place of research, <em>personal</em> progression is frequently cited as evidence for <em>collective</em> gains, which is obviously nonsensical.</p>
<p>Indeed, it's just <a href="https://www.baldurbjarnason.com/2025/trusting-your-own-judgement-on-ai/">gossip.</a></p>
</li>
<li>
<p><em>&quot;But we can hire for the framework.&quot;</em><br /><br /><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...we-need-to-be-able-to-hire-easily%22">😮 <strong><em>sigh</em></strong> 😮‍💨</a></p>
</li>
<li>
<p><em>&quot;The problem isn't React, it's the developers.&quot;</em></p>
<p>Hearing this self-accusation offered <em>at a React conference</em> was truly surreal.</p>
<p>In a room free of discussions about real engineering constraints, victim-blaming casts a shadow of next-level cluelessness. But frameworkists soldier on, no matter the damage it does to their argument. Volume and repetition seem key to pressing this line with a straight face.</p>
</li>
</ul>
 <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-round-and-round-4" class="footnote-backref">⇐</a></li>
<li id="fn-wut-5" class="footnote-item"><p>A frequently missed consequence of regulators scrutinising Apple's shocking (lack of) oversight of its app store has been Apple relaxing restrictions on iOS <abbr title="Progressive Web Apps">PWAs</abbr>. Previously, <abbr title="Progressive Web App">PWA</abbr> submissions were rejected often enough to warn businesses away. But that's over now. To reach app stores on Windows, iOS, and Android, you need is a cromulent website and <a href="https://www.pwabuilder.com/">PWABuilder</a>.</p>
<p>For most developers, the entire <em>raison d'être</em> for React Native is kaput; entirely overcome by events. Not that you'd hear about it at an assemblage of Over Reactors. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-wut-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-composition-6" class="footnote-item"><p>Instead of describing React's exclusive ownership of subtrees of the DOM, along with the introduction of a proprietary, brittle, and hard-to-integrate parallel lifecycle as a totalising framework that demands bespoke integration effort, the marketing term &quot;composability&quot; was substituted to describe the feeling of giving everything over to JSX-flavoured angle brackets every time a utility is needed. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-composition-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-bait-and-switch-7" class="footnote-item"><p>It has been nearly a decade since the failure of React to reliably deliver better user experiences gave rise to the <a href="https://infrequently.org/2018/09/the-developer-experience-bait-and-switch/">&quot;Developer Experience&quot; bait-and-switch.</a> <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-bait-and-switch-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ground-zero-8" class="footnote-item"><p><a href="https://gitnation.com/contents/the-state-of-react-and-the-community-in-2025">Mark Erikson's talk</a> was ground-zero for this sort of obfuscation. At the time of writing, the recording isn't up yet, but I'll update this post with analysis when it is. I don't want to heavily critique from my fallible memory. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-ground-zero-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-4g-9" class="footnote-item"><p><a href="https://www.webpagetest.org/">WPT</a> continues to default desktop tests to a configuration that throttles to 5Mbps up, 1Mbps down, with 28ms of <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr> latency added to each packet. All tests in this post use a somewhat faster configuration (9Mbps up and down) but with 170ms <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr> to better emulate usage from marginal network locations and the effects of full pipes. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-4g-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-layers-of-fail-10" class="footnote-item"><p><a href="https://infrequently.org/2024/08/object-lesson/#fn-receipts-1">I read the bundles</a> so you don't have to.</p>
<p>So what's in the main, 2.7MB (12.5MB unzipped) bk.com bundle? What follows is a stream-of-consciousness rundown as I read the pretty-printed text top-to-bottom. At the time of writing, it appears to include:</p>
<ul>
<li>
<p>A sea of <abbr title="JavaScript">JS</abbr> objects allocated by the output of a truly cursed &quot;<abbr title="Cascading Style Sheets">CSS</abbr>-in-<abbr title="JavaScript">JS</abbr>&quot; system. As a reminder, &quot;<abbr title="Cascading Style Sheets">CSS</abbr>-in-<abbr title="JavaScript">JS</abbr>&quot; systems with so-called &quot;runtimes&quot; are the slowest possible way to provide styling to web UI. An ominous start.</p>
</li>
<li>
<p>React Native Reanimated (no, I'm not linking to it), which generates <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame">rAF</a>-based animations on the web in The Year of Our Lord 2025, a full five years after Safari finally dragged its ass into the 2010s and <a href="https://caniuse.com/web-animation">implemented</a> the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API">Web Animation API</a>.</p>
<p>As a result, React Native Renaimated is Jank City.</p>
<p>Jank Town. George Clinton and the Parliment Jankidellic. DJ Janky Jeff. Janky Jank and the Janky Bunch. Ole Jankypants. The Undefeated Heavyweight Champion of Jank.</p>
<p>You get the idea; it drops frames.</p>
</li>
<li>
<p>Redefinitions of the built-in <abbr title="Cascading Style Sheets">CSS</abbr> colour names, because at no point traversing the towering inferno of build tools was it possible to know that this web-targeted artefact would be deployed to, you know, browsers.</p>
</li>
<li>
<p>But this makes some sense, because the build includes React Native Web, which is exactly what it sounds like: a set of React components that emulate the web. This allows RN project to provide a subset of the layout that browsers are natively capable of, but it does not include many of the batteries that the web includes for free.</p>
<p>Which really tells you everything you need to know about how teams get into this sort of mess.</p>
</li>
<li>
<p><strong>Huge</strong> amounts of code duplication via inline strings that include the text of functions <em>right next to the functions themselves</em>.</p>
<p>Yes, you're reading that right: some part of this toolchain is <em>doubling up the code in the bundle</em>, presumably for the benefit of a native debugger. Bro, do you even sourcemap?</p>
<p>At this point it feels like I'm repeating myself, but none of this is necessary on the web, and none of the (many, many) compiler passes saw fit to eliminate this waste in a web-targeted build artefact.</p>
</li>
<li>
<p><em>Another</em> redefinition of the built-in <abbr title="Cascading Style Sheets">CSS</abbr> colour names and values. In browsers that support them natively. I feel like I'm taking crazy pills.</p>
</li>
<li>
<p>A full copy of React, which is almost 10x larger than it needs to be in order to support legacy browsers and React Native.</p>
</li>
<li>
<p><s>Tens</s> Hundreds of thousands of lines of auto-generated schema validation structures and repeated, useless getter functions for data <em>that will never be validated on the client</em>. How did this ungodly cruft get into the bundle? One guess, and it rhymes with &quot;schmopallo&quot;.</p>
</li>
<li>
<p>Of course, no bundle this disastrous would be complete without <em>multiple copies</em> of polyfills for widely supported <abbr title="JavaScript">JS</abbr> features like <code>Object.assign()</code>, class private fields, generators, spread, async iterators, and much more.</p>
</li>
<li>
<p><em>Inline'd WASM code</em>, appearing as a gigantic <abbr title="JavaScript">JS</abbr> array. No, this is not a joke.</p>
</li>
<li>
<p>A copy of Lottie. Obviously.</p>
</li>
<li>
<p>What looks to be the entire AWS Amplify SDK. So much for tree-shaking.</p>
</li>
<li>
<p>A userland implementation of elliptic curve cryptography primitives that are natively supported in every modern browser via Web Crypto.</p>
</li>
<li>
<p>Inline'd SVGs, but not as strings. No, that would be too efficient. They're inlined <em>as React components</em>.</p>
</li>
<li>
<p>A copy of the app's Web App Manifest, inline, as a string. You cannot make this up.</p>
</li>
</ul>
<p>Given all of this high-cost, low-quality output, it might not surprise you to learn that the browser's <a href="https://developer.chrome.com/docs/devtools/coverage">coverage tool</a> reports that more than 75% of functions are totally unused after loading and clicking around a bit. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-layers-of-fail-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-dont-at-me-11" class="footnote-item"><p>I'll be the first to point out that what Brandeis is appealing to is distinct from credentialing. As a state-school dropout, that difference matters to me very personally, and it has not been edifying to see credentialism (in the form of <a href="https://www.sandofsky.com/lambda-school/">dubious boot camps</a>) erode both the content and form of learning in &quot;tech&quot; over the past few years.</p>
<p>The term &quot;professional&quot; continues to leave me uncomfortable for many of the affective connotations it now carries. But I do believe we should all aspire to do our work in a way that is compatible with Brandeis' description of a profession. To do otherwise is to endanger any hope of self-respect and even our social licence to operate. <a href="https://infrequently.org/2025/06/conferences-clarity-and-smokescreens/#fnref-dont-at-me-11" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Safari at WWDC &#39;25: The Ghost of Christmas Past</title>
    <link href="https://infrequently.org/2025/06/the-ghost-of-christmas-past/"/>
    <updated>2025-06-13T00:00:00Z</updated>
    <id>https://infrequently.org/2025/06/the-ghost-of-christmas-past/</id>
    <content type="html"><![CDATA[
      <p>At Apple's annual <s>developer</s> marketing conference, <a href="https://webkit.org/blog/16993/news-from-wwdc25-web-technology-coming-this-fall-in-safari-26-beta/">the Safari team announced a sizeable set of features</a> that will be available in a few months. Substantially all of them are already shipped in leading-edge browsers. Here's the list, prefixed by the year that these features shipped to stable in Chromium:</p>
<ul>
<li><a href="https://chromestatus.com/feature/5119617865613312"><time datetime="2023-05">2023</time></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API">WebGPU</a></li>
<li><a href="https://caniuse.com/link-icon-svg"><time datetime="2020-02">2020</time></a>: SVG Favicons</li>
<li><a href="https://blog.adobe.com/en/publish/2023/10/10/hdr-explained"><time datetime="2023-08">2023</time></a>: HDR Images</li>
<li><a href="https://chromestatus.com/feature/5124922471874560"><time datetime="2024-05">2024</time></a>: <a href="https://css-tricks.com/css-anchor-positioning-guide/">CSS Anchor Positioning</a></li>
<li><a href="https://caniuse.com/mdn-css_properties_text-wrap_pretty"><time datetime="2023-09">2023</time></a>: <a href="https://developer.chrome.com/blog/css-text-wrap-pretty">CSS <code>text-wrap: pretty</code></a></li>
<li><a href="https://chromestatus.com/feature/5112558941634560"><time datetime="2025-06">2025</time></a>: CSS <code>progress()</code> function</li>
<li><a href="https://chromestatus.com/feature/6752840701706240"><time datetime="2023-07">2023</time></a>: <a href="https://developer.chrome.com/docs/css-ui/scroll-driven-animations">Scroll-driven Animations</a> (finally!!!)</li>
<li><a href="https://caniuse.com/trusted-types"><time datetime="2020-05">2020</time></a>: <a href="https://web.dev/articles/trusted-types">Trusted Types</a></li>
<li><a href="https://caniuse.com/mdn-api_urlpattern"><time datetime="2021-20">2021</time></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API">URL Pattern API</a></li>
<li><a href="https://chromestatus.com/feature/5101778518147072"><time datetime="2025-01">early 2025</time></a>: <a href="https://developer.chrome.com/docs/identity/webauthn-signal-api">WebAuthN Signal API</a></li>
<li><a href="https://chromestatus.com/feature/6284708426022912"><time datetime="2020-10">2020</time></a>: WritableStreams for the <a href="https://developer.chrome.com/docs/capabilities/web-apis/file-system-access">File System APIs</a></li>
<li><a href="https://chromestatus.com/feature/5091020593430528"><time datetime="2023-12">late 2023</time></a>: Scroll Margin for <a href="https://css-tricks.com/an-explanation-of-how-the-intersection-observer-watches/">Intersection Observers</a></li>
<li><a href="https://chromestatus.com/feature/4728308937523200"><time datetime="2025-03">2025</time></a>: CSS Logical Overflow (<code>overflow-block</code> and <code>overflow-inline</code>)</li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/d5e6d59db47cbfd7edbc58ce86428b555aab15b6"><time datetime="2024-02">2024</time></a>: CSS <code>align-self</code> and <code>justify-self</code> in absolute positioning</li>
<li><a href="https://chromestatus.com/feature/5087324181102592"><time datetime="2025-03">2025</time></a>: a subset of <a href="https://v8.dev/features/explicit-resource-management">Explicit JavaScript Resource Management</a></li>
<li><a href="https://caniuse.com/webcodecs"><time datetime="2021-09">2021</time></a>: <code>AudioEncoder</code> &amp; <code>AudioDecoder</code> for WebCodecs</li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/ea5f6f226e217c636c65dbfb36f75b37a40db813"><time datetime="2020-04">2020</time></a>: <code>RTCEncodedAudioFrame</code> &amp; <code>RTCEncodedVideoFrame</code> serialisation</li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/c4b07273cbf3cec20c51699a0a6821bba729484e"><time datetime="2024-06">2024</time></a>: <code>RTCEncodedAudioFrame</code> &amp; <code>RTCEncodedVideoFrame</code> constructors</li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/0da2dad23bdedd6c6023852bf754681d54284785"><time datetime="2018-02">2018</time></a>: PCM format support in MediaRecorder</li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/06765494ed8bdfc335628c409450c23aa79ad2a7"><time datetime="2017-01">2017</time></a>: <code>ImageCapture.grabFrame()</code></li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/layout/svg/layout_svg_container.cc;l=246;drc=fc7fe3f8c697adee1f13a48b962b231b9200add4;bpv=0;bpt=1"><time datetime="2017">2017(?)</time></a>: SVG <code>pointer-events=&quot;bounding-box&quot;</code></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/dns-prefetch"><time datetime="2015-10">2015</time></a>: <code>&lt;link rel=dns-prefetch&gt;</code></li>
</ul>
<p>In many cases, these features were available to developers even earlier via the Origin Trials mechanism. <a href="https://developer.chrome.com/origintrials/#/view_trial/118219490218475521">WebGPU</a>, e.g., <a href="https://chromestatus.com/feature/6213121689518080">ran trials for a year,</a> allowing developers to try the in-development feature on live sites in Chrome and Edge as early as September 2021.</p>
<p>There <em>are</em> features that Apple appears to be leading on in this release, but it's not clear that they will become available in Safari before Chromium-based browsers launch them, given that the announcement is about a beta:</p>
<ul>
<li><a href="https://chromestatus.com/feature/5166035265650688">Digital Credentials API</a>: currently in <a href="https://chromestatus.com/feature/5166035265650688">Chromium OT</a>.</li>
<li><a href="https://css-tricks.com/exploring-the-css-contrast-color-function-a-second-time/">CSS <code>contrast-color()</code></a></li>
<li><a href="https://caniuse.com/?search=margin-trim"><code>margin-trim: block inline</code></a> extends a neat Safari-only feature in useful ways.</li>
<li>Apple's <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Audio_codecs#alac_apple_lossless_audio_codec">ALAC format</a> for MediaRecorder.</li>
<li><a href="https://w3c.github.io/mediacapture-output/#dom-mediadevices-selectaudiooutput">Audio Output Devices API</a>. <a href="https://issues.chromium.org/issues/372214870">In progress</a> in Chromium, but no launch scheduled.</li>
</ul>
<p>The announced support for CSS image <code>crossorigin()</code> and <code>referrerpolicy()</code> modifiers has an unclear relationship to other browsers, judging by the <a href="https://wpt.fyi/">wpt.fyi</a> <a href="https://wpt.fyi/results/css/css-values/urls?label=master&amp;label=experimental&amp;aligned">tests.</a></p>
<p>On balance, this is a lot of catch-up with sparse sprinklings of leadership. This makes sense, because Safari is in usually in last place when it comes to feature completeness:</p>
<p></p><figure class="full_wide"><a href="https://webstatus.dev/stats?startDate=2015-01-01&endDate=2025-06-10" alt="A graph of features missing from only one engine. Over the past decade, Safari and WebKit have consistently brought up the caboose." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2025/06/the-ghost-of-christmas-past/missing-features.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2025/06/the-ghost-of-christmas-past/missing-features.webp" alt="A graph of features missing from only one engine. Over the past decade, Safari and WebKit have consistently brought up the caboose." style="aspect-ratio: 1575 / 580" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>A graph of features missing from only one engine. Over the past decade, Safari and WebKit have consistently brought up the caboose.</figcaption>      </figure><p></p>
<p>And <em>that</em> is important because Apple's <a href="https://webventures.rejh.nl/blog/2024/history-of-safari-show-stoppers/">incredibly shoddy</a> <a href="https://webventures.rejh.nl/blog/2025/safe-area-inset-bottom-does-not-update/">work</a> impacts every single browser on iOS.</p>
<p>You might recall that Apple <a href="https://open-web-advocacy.org/blog/apple-dma-changes/">was required by the EC to enable browser engine choice</a> for EU citizens under the <a href="https://eur-lex.europa.eu/eli/reg/2022/1925/oj/eng">Digital Markets Act</a>. Cupertino, per usual, was <a href="https://open-web-advocacy.org/blog/its-official-apple-kills-web-apps-in-the-eu/">extremely chill about it,</a> threatening to <a href="https://infrequently.org/2024/02/home-screen-advantage/">end PWAs entirely</a> and offering <a href="https://issues.chromium.org/hotlists/5909213">APIs that are inadequate</a> or <a href="https://issues.chromium.org/issues/418007760">broken.</a></p>
<p>And those are just the technical obstacles that Apple has put up. The <a href="https://developer.apple.com/contact/request/download/web_browser_engine.pdf">proposed contractual terms (pdf)</a> are so obviously onerous that no browser vendor could ever accept them, and are transparently disallowed under the DMA's plain language. But respecting the plain language of the law <a href="https://cafetechinenglish.substack.com/p/a-simple-comma-will-cost-apple-billion">isn't Apple's bag.</a></p>
<p>All of this is to say that Apple is not going to allow better browsers on iOS without a fight, and it remains dramatically behind the best engines in performance, security, and features. Meanwhile, we now know that Apple is likely skimming something like $19BN <em>per year</em> in pure profit from it's <a href="https://www.bloomberg.com/news/articles/2024-05-01/google-s-payments-to-apple-reached-20-billion-in-2022-cue-says">$20+BN/yr of revenue from its deal with Google.</a> That's a <strong>90+%</strong> profit rate, which is only reduced by the paltry amount it re-invests into WebKit and Safari.</p>
<p>So to recap: Apple's Developer Relations folks want you to be grateful to Cupertino for unlocking access to features that <em>Apple has been the singular obstacle to.</em></p>
<p>And they want to you ignore the fact that for the past decade it has hobbled the web while skimming obscene profits from the ecosystem.</p>
<p>Don't fall for it. Ignore the gaslighting. Apple could 10x the size of the WebKit team without causing the CFO to break a sweat, and there are plenty of great browser engineers on the market today. Suppressing the web is a choice — Apple's choice — and not one that we need to feel gratitude toward.</p>

    ]]></content>
  </entry>
  <entry>
    <title>If Not React, Then What?</title>
    <link href="https://infrequently.org/2024/11/if-not-react-then-what/"/>
    <updated>2024-11-29T00:00:00Z</updated>
    <id>https://infrequently.org/2024/11/if-not-react-then-what/</id>
    <content type="html"><![CDATA[
      <p>Over the past decade, my work has centred on partnering with teams to build <a href="https://web.dev/articles/ps-on-the-web">ambitious products for the web</a> across both desktop and mobile. This has provided a ring-side seat to a sweeping variety of teams, products, and technology stacks across more than 100 engagements.</p>
<p>While I'd <em>like</em> to be spending most of this time working through improvements to <a href="https://developer.chrome.com/docs/capabilities/fugu-showcase">web APIs,</a> the majority of time spent with partners goes to <a href="https://infrequently.org/2024/08/object-lesson/">remediating performance and accessibility issues</a> caused by “modern” frontend frameworks and the culture surrounding them. Today, these issues are most pronounced in React-based stacks.</p>
<p>This is disquieting because <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-why-not-1">React is legacy technology,</a> but it continues to appear in greenfield applications.</p>
<p>Surprisingly, some continue to insist that React is “modern.” Perhaps we can square the circle if we understand “modern” to apply to React in the way it applies to art. Neither demonstrate contemporary design and construction. They are not built for current needs and do not meet contemporary performance standards, but pose as expensive <em>objets</em> harkening back to an earlier era's antiquated methods.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#the-rule-of-least-client-side-complexity">The Rule Of Least Client-Side Complexity</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#ok%2C-but-what%2C-then%3F">OK, But What, Then?</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#and-nothing-of-value-was-lost">And Nothing Of Value Was Lost</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#vignettes">Vignettes</a><ul><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#informational">Informational</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#e-commerce">E-Commerce</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#media">Media</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#social">Social</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#productivity">Productivity</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#other-application-classes">Other Application Classes</a></li></ul></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22but...%22">&quot;But...&quot;</a><ul><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...we-need-to-move-fast%22">&quot;...we need to move fast&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...it-works-for-facebook%22">&quot;...it works for Facebook&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...our-teams-already-know-react%22">&quot;...our teams already know React&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...we-need-to-be-able-to-hire-easily%22">&quot;...we need to be able to hire easily&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...everyone-has-fast-phones-now%22">&quot;...everyone has fast phones now&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...react-is-industry-standard%22">&quot;...React is industry-standard&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...the-ecosystem...%22">&quot;...the ecosystem...&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...next.js-can-be-fast-(enough)%22">&quot;...Next.js can be fast (enough)&quot;</a></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...react-native!%22">&quot;...React Native!&quot;</a></li></ul></li><li><a href="https://infrequently.org/2024/11/if-not-react-then-what/#references">References</a></li></ul></nav>
<p>In the hope of steering the <em>next</em> team away from the rocks, I've found myself penning <a href="https://infrequently.org/2023/02/the-market-for-lemons/">advocacy pieces</a> and <a href="https://infrequently.org/series/performance-inequality/">research into the state of play</a>, as well as <a href="https://www.youtube.com/watch?v=0XwWVjQOmyg&amp;list=PLjnstNlepBvOxZeta4-yAFDllxfW-A5EC&amp;index=8">giving talks</a> to alert managers and developers of the dangers of today's frontend orthodoxy.</p>
<p>In short, nobody should start a new project in the 2020s based on React. Full stop.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-why-not-1" id="fnref-why-not-1">1</a></sup></p>
<h2 id="the-rule-of-least-client-side-complexity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#the-rule-of-least-client-side-complexity">The Rule Of Least Client-Side Complexity</a></h2>
<p>Code that runs on the server can be fully costed. Performance and availability of server-side systems are under the control of the provisioning organisation, and latency can be actively managed.</p>
<p>Code that runs on the client, by contrast, is running on The Devil's Computer.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-the-devils-computer-2" id="fnref-the-devils-computer-2">2</a></sup> Almost nothing about the latency, client resources, or even API availability are under the developer's control.</p>
<p>Client-side web development is perhaps best conceived of as <em>influence-oriented programming</em>. Once code has left the datacentre, all a web developer can do is send <a href="https://piccalil.li/blog/a-handful-of-reasons-javascript-wont-be-available/">thoughts and prayers.</a></p>
<p>As a direct consequence, an unreasonably effective strategy is to send less code. Declarative forms generate more functional UI per byte sent. In practice, this means favouring HTML and CSS over JavaScript, as they degrade gracefully and feature higher compression ratios. These improvements in resilience and reductions in costs are beneficial in compounding ways over a site's lifetime.</p>
<p>Stacks based on React, Angular, and other legacy-oriented, desktop-focused JavaScript frameworks generally take the opposite bet. These ecosystems pay lip service to the controls necessary for preventing horrific <a href="https://infrequently.org/2024/08/object-lesson/#fn-receipts-1">proliferations of unnecessary client-side cruft.</a> The predictable consequence are NPM-amalgamated bundles full of redundancies like <code>core-js</code>, <code>lodash</code>, <code>underscore</code>, polyfills for browsers that no longer exist, userland ECC libraries, <code>moment.js</code>, and a hundred other horrors.</p>
<p>This culture is so out of hand that it seems 2024's React developers are constitutionally unable to build chatbots without including all of these 2010s holdovers, plus at least one chonky MathML or TeX library in the critical path to display an <code>&lt;input&gt;</code>. A tiny fraction of query responses need to display formulas — and yet.</p>
<p>Tech leads and managers need to break this spell. Ownership has to be created over decisions affecting the client. In practice, this means forbidding React in new work.</p>
<h2 id="ok%2C-but-what%2C-then%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#ok%2C-but-what%2C-then%3F">OK, But What, Then?</a></h2>
<p>This question comes in two flavours that take some work to tease apart:</p>
<ul>
<li>
<p>The narrow form:</p>
<p><em>&quot;Assuming we have a well-qualified need for client-side rendering, what specific technologies would you recommend instead of React?&quot;</em></p>
</li>
<li>
<p>The broad form:</p>
<p><em>&quot;Our product stack has bet on React and the various mythologies that the cool kids talk about on React-centric podcasts. You're asking us to rethink the whole thing. Which silver bullet should we adopt instead?&quot;</em></p>
</li>
</ul>
<p>Teams that have grounded their product decisions appropriately can work through the narrow form by running objective bake offs. Building multiple small PoCs to determine each approach's scaling factors and limits can even be a great deal of fun.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-ballot-stuffing-3" id="fnref-ballot-stuffing-3">3</a></sup> It's the rewarding side of real engineering; trying out new materials under well-understood constraints to improve outcomes.</p>
<p>Just the prep work to run bake offs tends to generate value.</p>
<p>In most teams, constraints on tech stack decisions have materially shifted since they were last examined. For some, identifying use-cases reveals a reality that's vastly different than managers and tech leads expect. Gathering data on these factors allows for first-pass cuts about stack choices, winnowing quickly to a smaller set of options to run bake offs for.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-cut-lines-4" id="fnref-cut-lines-4">4</a></sup></p>
<p>But the teams we spend the most time with don't have good reasons to stick with client-side rendering in the first place.</p>
<p>Many folks asking <em>&quot;if not React, then what?&quot;</em> think they're asking in the narrow form but are grappling with the broader version. A shocking fraction of decent, well-meaning product managers and engineers haven't thought through the whys and wherefores of their architectures, opting instead to go with what's popular in a responsibility fire brigade.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-buck-passing-5" id="fnref-buck-passing-5">5</a></sup></p>
<p>For some, provocations to abandon React induce an unmoored feeling; a suspicion that they might not understand the world any more.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-off-brand-therapy-6" id="fnref-off-brand-therapy-6">6</a></sup></p>
<p>Teams in this position are working through the epistemology of their values and decisions.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-shortcuts-7" id="fnref-shortcuts-7">7</a></sup> How can they know their technology choices are better than the alternatives? Why should they pick one stack over another?</p>
<p>Many need help deciding which end of the telescope to use when examining frontend challenges because <em>frameworkism</em> has become the dominant creed of our discourse.</p>
<p>Frameworkism insists that all problems will be solved if teams just framework hard enough. This is non-sequitur, if not entirely backwards. In practice, <strong>the only thing that makes web experiences good is caring about the user experience</strong> — specifically, the experience of folks at the margins. Technologies come and go, but what always makes the difference is giving a toss about the user.</p>
<p>In less vulgar terms, the struggle is to convince managers and tech leads that they need to <a href="https://www.gov.uk/guidance/government-design-principles">start with user needs.</a> Or as <a href="https://public.digital/">Public Digital</a> puts it, <em><a href="https://public.digital/pd-insights/blog/2018/10/internet-era-ways-of-working#:~:text=1.%20Design%20for%20user%20needs%2C%20not%20organisational%20convenience">&quot;design for user needs, not organisational convenience&quot;</a></em></p>
<p>The essential component of this mindset shift is replacing hopes based on promises with constraints based on <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">research and evidence.</a> This aligns with what it means to commit wanton acts of engineering, because engineering is the practice of designing solutions for users and society under known constraints.</p>
<p>The opposite of engineering is imagining that constraints do not exist, or do not apply to <em>your</em> product. The shorthand for this is <a href="https://archive.org/details/on-bullshit-by-harry-frankfurt">“bullshit.”</a></p>
<p>Ousting an engrained practice of bullshitting does not come easily. Frameworkism preaches that the way to improve user experiences is to adopt more (or different) tooling from within the framework's ecosystem. This provides adherents with something to do that looks plausibly like engineering, but isn't.</p>
<p>It can even become a totalising commitment; solutions to user problems outside the framework's expanded cinematic universe are unavailable to the frameworkist. Non-idiomatic patterns that unlock wins for users are bugs to be squashed, not insights to be celebrated. Without data or evidence to counterbalance the bullshit artist's assertions, who's to say they're wrong? So frameworkists root out and devalue practices that generate objective criteria in decision-making. Orthodoxy unmoored from measurement predictably spins into <a href="https://styled-components.com/">absurdity.</a> Eventually, heresy carries heavy sanctions.</p>
<p>And it's all nonsense.</p>
<p>Realists do not wallow in abstraction-induced hallucinations about user experiences; they measure them. Realism requires <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">reckoning with the world as it is,</a> not as we wish it to be. In that way, realism is the opposite of frameworkism.</p>
<p>The most effective tools for breaking the spell are techniques that give managers a user-centred view of system performance. This can take the form of <a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Rum-vs-Synthetic">RUM data,</a> such as <a href="https://web.dev/articles/vitals">Core Web Vitals</a> (<a href="https://cruxvis.withgoogle.com/">check yours now!</a>), or lab results from well-configured test-benches (e.g., <a href="https://webpagetest.org/">WPT</a>). Instrumenting critical user journeys and talking through business goals are quick follow-ups that enable teams to seize the momentum and formulate business cases for change.</p>
<p>RUM and bench data sources are essential antidotes to frameworkism because they provide data-driven baselines to argue from, creating a shared observable reality. Instead of accepting the next increment of framework investment on faith, teams armed with data can weigh up the costs of fad chasing versus likely returns.</p>
<h2 id="and-nothing-of-value-was-lost" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#and-nothing-of-value-was-lost">And Nothing Of Value Was Lost</a></h2>
<p>Prohibiting the spread of React (and other frameworkist totems) by policy is both an incredible cost savings and a helpful way to reorient teams towards delivery for users. However, better results only arrive once frameworkism itself is eliminated from decision-making. It's no good to spend the windfall from avoiding one sort of mistake on errors within the same category.</p>
<p>A general answer to the broad form of the problem has several parts:</p>
<ul>
<li>
<p><strong>User focus</strong></p>
<p>Decision-makers must accept that they are directly accountable for the results of their engineering choices. Either systems work well for users,<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-success-through-quality-8" id="fnref-success-through-quality-8">8</a></sup> including those at the margins, or they don't. Systems that do not perform must be replaced. No sacred cows, only problems to be solved with the appropriate application of constraints.</p>
</li>
<li>
<p><strong>Evidence</strong></p>
<p>The essential shared commitment between management and engineering is a dedication to realism. Better evidence must win.</p>
</li>
<li>
<p><strong>Guardrails</strong></p>
<p>Policies must be implemented to ward off hallucinatory frameworkist assertions about how better experiences are delivered. Good examples of this include the UK Government Digital Service's <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">requirement that services be built using progressive enhancement techniques.</a></p>
<p>Organisations can tweak guidance as appropriate — e.g., creating an escalation path for exceptions — but the important thing is to set a baseline. Evidence boiled down into policy has power.</p>
</li>
<li>
<p><strong>Bake Offs</strong></p>
<p>No new system should be deployed without a clear list of critical user journeys. Those journeys embody what we users do most frequently, and once those definitions are in hand, teams can do bake offs to test how well various systems deliver given the constraints of the expected marginal user.</p>
</li>
</ul>
<p>All of this casts the product manager's role in stark relief. Instead of suggesting an endless set of experiments to run (poorly), they must define a product thesis and commit to defining success as improving services for <em>users</em>. This will be uncomfortable. It's also the job. Graciously accept the resignations of PMs who decide managing products is not in their wheelhouse.</p>
<h2 id="vignettes" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#vignettes">Vignettes</a></h2>
<p>To see how realism and frameworkism differ in practice, it's helpful to work a few examples. As background, recall that our rubric<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-rubrics-9" id="fnref-rubrics-9">9</a></sup> for choosing technologies is based on the number of incremental updates to primary data in a session. Some classes of app, like editors, feature long sessions and many incremental updates where a local data model can be helpful in supporting timely application of updates, <em>but this is the exception</em>.</p>
<p></p><figure class="full_wide"><picture style="--lqip: -521501" class="preview">      <img src="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.avif" alt="Sites with short average sessions cannot afford much JS up-front." style="aspect-ratio: 1000 / 455" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>Sites with short average sessions cannot afford much JS up-front.</figcaption>      </figure><p></p>
<p>It's only in these exceptional instances that SPA architectures should be considered.</p>
<p><picture style="--lqip: 524196" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/11/if-not-react-then-what/spa-decision-tree.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/11/if-not-react-then-what/spa-decision-tree.png" alt="Very few sites will meet the qualifications to be built as an SPA" style="aspect-ratio: 1281 / 1450" class="full_wide preview" decoding="async" loading="lazy" />      </picture></p>
<p>And only when an SPA architecture is required should tools designed to support optimistic updates against a local data model — including &quot;frontend frameworks&quot; and &quot;state management&quot; tools — ever become part of a site's architecture.</p>
<p><strong>The choice isn't between JavaScript frameworks, it's whether SPA-oriented tools should be entertained <em>at all</em>.</strong></p>
<p>For most sites, the answer is clearly <em>&quot;no&quot;.</em></p>
<p>We can examine broad classes of site to understand why this is true:</p>
<h3 id="informational" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#informational">Informational</a></h3>
<p>Sites built to inform should almost always be built using semantic HTML with optional <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">progressive enhancement as necessary.</a></p>
<p>Static site generation tools like Hugo, Astro, 11ty, and Jekyll work well for many of these cases. Sites that have content that changes more frequently should look to &quot;classic&quot; CMSes or tools like WordPress to generate HTML and CSS.</p>
<p>Blogs, marketing sites, company home pages, and public information sites should minimise client-side JavaScript to the greatest extent possible. They should never be built using frameworks that are designed to enable SPA architectures.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-no-ssr-doesnt-count-10" id="fnref-no-ssr-doesnt-count-10">10</a></sup></p>
<h4 id="why-semantic-markup-and-optional-progressive-enhancement-are-the-right-choice" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#why-semantic-markup-and-optional-progressive-enhancement-are-the-right-choice">Why Semantic Markup and Optional Progressive Enhancement Are The Right Choice</a></h4>
<p>Informational sites have short sessions and server-owned application data models; that is, the source of truth for what's displayed on the page is always the server's to manage and own. This means that there is no need for a client-side data model abstraction or client-side component definitions that might be updated from such a data model.</p>
<blockquote>
<p><strong>Note</strong>: many informational sites include productivity components as distinct sub-applications, which can be evaluated independently. For example, CMSes such as Wordpress are comprised of two distinct surfaces; post editors that are low-traffic but high-interactivity, and published pages, which are high-traffic, low-interactivity viewers. Progressive enhancement should be considered for both, but is an absolute must for reader views which do not feature long sessions.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-rubrics-9" id="fnref-rubrics-9:1">9:1</a></sup></p>
</blockquote>
<h3 id="e-commerce" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#e-commerce">E-Commerce</a></h3>
<p>E-commerce sites should be built using server-generated semantic HTML and progressive enhancement.</p>
<p></p><figure class="full_wide"><a href="https://treo.sh/sitespeed/www.amazon.com/vs/www.walmart.com/vs/www.wayfair.com?metrics=lcp%2Cr&formFactor=phone" alt="A large and stable performance gap between Amazon and its React-based competitors demonstrates how poorly SPA architectures perform in e-commerce applications. More than 70% of Walmart's traffic is mobile, making their bet on Next.js particularly problematic for the business." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2024/11/if-not-react-then-what/amazon-walmart-wayfair.avif" alt="A large and stable performance gap between Amazon and its React-based competitors demonstrates how poorly SPA architectures perform in e-commerce applications. More than 70% of Walmart's traffic is mobile, making their bet on Next.js particularly problematic for the business." style="aspect-ratio: 1823 / 1290" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>A large and stable performance gap between Amazon and its React-based competitors demonstrates how poorly SPA architectures perform in e-commerce applications. More than 70% of Walmart's traffic is mobile, making their bet on Next.js particularly problematic for the business.</figcaption>      </figure><p></p>
<p>Many tools are available to support this architecture. Teams building e-commerce experiences should prefer stacks that deliver <em>no JavaScript by default</em>, and buttress that with controls on client-side script to prevent <a href="https://wpostats.com/">regressions in material business metrics.</a></p>
<h4 id="why-progressive-enhancement-is-the-right-choice" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#why-progressive-enhancement-is-the-right-choice">Why Progressive Enhancement Is The Right Choice</a></h4>
<p>The general form of e-commerce sites has been stable for more than 20 years:</p>
<ul>
<li>Landing pages with current offers and a search function for finding products.</li>
<li>Search results pages which allow for filtering and comparison of products.</li>
<li>Product-detail pages that host media about products, ratings, reviews, and recommendations for alternatives.</li>
<li>Cart management, checkout, and account management screens.</li>
</ul>
<p>Across all of these page types, a pervasive login and cart status widget will be displayed. Sometimes this widget, and the site's logo, are the <em>only</em> consistent elements.</p>
<p>Long experience demonstrates very little shared data across these page types, highly variable session lengths, and a need for fresh content (e.g., prices) from the server. The best way to reduce latency in e-commerce sites is to optimise for lightweight, server-generated pages. Aggressive caching, image optimisation, and page-weight reduction strategies all help.</p>
<h3 id="media" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#media">Media</a></h3>
<p>Media consumption sites vary considerably in session length and data update potential. Most should <em>start</em> as progressively-enhanced markup-based experiences, adding complexity over time as product changes warrant it.</p>
<h4 id="why-progressive-enhancement-and-islands-may-be-the-right-choice" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#why-progressive-enhancement-and-islands-may-be-the-right-choice">Why Progressive Enhancement and Islands May Be The Right Choice</a></h4>
<p>Many interactive elements on media consumption sites can be modelled as distinct islands of interactivity (e.g., comment threads). Many of these components present independent data models and can therefore be constructed as progressively-enhanced Web Components within a larger (static) page.</p>
<h4 id="when-an-spa-may-be-appropriate" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#when-an-spa-may-be-appropriate">When An SPA May Be Appropriate</a></h4>
<p>This model breaks down when media playback must continue across media browsing (think &quot;mini-player&quot; UIs). A fundamental limitation of today's web platform is that it is not possible to preserve some elements from a page across top-level navigations. Sites that must support features like this should consider using SPA technologies while setting strict guardrails for the allowed size of client-side JS per page.</p>
<p>Another reason to consider client-side logic for a media consumption app is offline playback. Managing a local (Service Worker-backed) media cache requires application logic and a way to synchronise information with the server.</p>
<p>Lightweight SPA-oriented frameworks may be appropriate here, along with connection-state resilient data systems such as <a href="https://zero.rocicorp.dev/">Zero</a> or <a href="https://github.com/yjs/yjs">Y.js</a>.</p>
<h3 id="social" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#social">Social</a></h3>
<p>Social media apps feature significant variety in session lengths and media capabilities. Many present infinite-scroll interfaces and complex post editing affordances. These are natural dividing lines in a design that align well with session depth and client-vs-server data model locality.</p>
<h4 id="why-progressive-enhancement-may-be-the-right-choice" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#why-progressive-enhancement-may-be-the-right-choice">Why Progressive Enhancement May Be The Right Choice</a></h4>
<p>Most social media experiences involve a small, fixed number of actions on top of a server-owned data model (&quot;liking&quot; posts, etc.) as well as distinct update phase for new media arriving at an interval. This model works well with a hybrid approach as is found in <a href="https://hotwired.dev/">Hotwire</a> and many <a href="https://htmx.org/">HTMX applications.</a></p>
<h4 id="when-an-spa-may-be-appropriate-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#when-an-spa-may-be-appropriate-1">When An SPA May Be Appropriate</a></h4>
<p>Islands of deep interactivity may make sense in social media applications, and aggressive client-side caching (e.g., for draft posts) may aid in building engagement. It may be helpful to think of these as unique app sections with distinct needs from the main site's role in displaying content.</p>
<p>Offline support may be another reason to download a snapshot of user data to the client. This should be as part of an approach that builds resilience against flaky networks. Teams in this situation should consider a Service Worker-based, multi-page apps with <a href="https://developer.chrome.com/docs/workbox/faster-multipage-applications-with-streams">&quot;stream stitching&quot;.</a> This allows sites to stick with HTML, while enabling offline-first logic and synchronisation. Because offline support is so invasive to an architecture, this requirement must be identified up-front.</p>
<blockquote>
<p><strong>Note</strong>: Many assume that SPA-enabling tools and frameworks are required to build compelling Progressive Web Apps that work well offline. <em>This is not the case.</em> PWAs can be built using stream-stitching architectures that apply the <a href="https://github.com/thepassle/swtl">equivalent of server-side templating to data on the client,</a> within a Service Worker.</p>
<p>With the advent of <a href="https://developer.chrome.com/docs/web-platform/view-transitions/cross-document">multi-page view transitions</a>, MPA architecture PWAs can present fluid transitions between user states without heavyweight JavaScript bundles clogging up the main thread. It may take several more years for the framework community to digest the implications of these technologies, but they are available <em>today</em> and work exceedingly well, both as foundational architecture pieces and as progressive enhancements.</p>
</blockquote>
<h3 id="productivity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#productivity">Productivity</a></h3>
<p>Document-centric productivity apps may be the hardest class to reason about, as collaborative editing, offline support, and lightweight &quot;viewing&quot; modes with full document fidelity are hard product requirements.</p>
<p>Triage-oriented experiences (e.g. email clients) are also prime candidates for the potential benefits of SPA-based technology. But as with all SPAs, the ability to deliver a better experience hinges both on session depth and up-front payload cost. It's easy to lose this race, as this blog <a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/">has examined in the past.</a></p>
<p>Editors of all sorts are a natural fit for local data models and SPA-based architectures to support modifications to them. However, the endemic complexity of these systems ensures that performance will remain a constant struggle. As a result, teams building applications in this style should consider strong performance guardrails, identify critical user journeys up-front, and ensure that instrumentation is in place to ward off unpleasant performance surprises.</p>
<h4 id="why-spas-may-be-the-right-choice" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#why-spas-may-be-the-right-choice">Why SPAs May Be The Right Choice</a></h4>
<p>Editors frequently feature many updates to the same data (e.g., for every keystroke or mouse drag). Applying updates optimistically and only informing the server asynchronously of edits can deliver a superior experience across long editing sessions.</p>
<p>However, teams should be aware that editors may also perform double duty as viewers and that the weight of up-front bundles may not be reasonable for both cases. Worse, it can be hard to tease viewing sessions apart from heavy editing sessions at page load time.</p>
<p>Teams that succeed in these conditions build extreme discipline about the modularity, phasing, and order of delayed package loading based on user needs (e.g., only loading editor components users need when they require them). Teams that get stuck tend to fail to apply controls over which team members can approve changes to critical-path payloads.</p>
<h3 id="other-application-classes" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#other-application-classes">Other Application Classes</a></h3>
<p>Some types of apps are intrinsically interactive, focus on access to <a href="https://developer.chrome.com/docs/capabilities">local device hardware,</a> or center on manipulating media types that HTML doesn't handle intrinsically. Examples include <a href="https://www.onshape.com/en/features/drawings">3D CAD systems</a>, <a href="https://vscode.dev/">programming editors</a>, <a href="https://www.xbox.com/en-US/play">game streaming services</a>, <a href="https://proxx.app/">web-based games</a>, <a href="https://squoosh.app/">media-editing</a>, and <a href="https://webmidijs.org/showcase/">music-making systems.</a> These constraints often make client-side JavaScript UIs a natural fit, but each should be evaluated critically:</p>
<ul>
<li>What are the critical user journeys?</li>
<li>How long will average sessions be?</li>
<li>Do many updates to the same data take place in a session?</li>
<li>What metrics will we track to ensure that performance remains acceptable?</li>
<li>How will we place tight controls on critical-path script and other resources?</li>
</ul>
<p>Success in these app classes is possible on the web, but extreme care is required.</p>
<blockquote>
<p><strong>A Word On Enterprise Software</strong>: Some of the worst performance disasters I've helped remediate are from a category we can think of, generously, as &quot;enterprise line-of-business apps&quot;. Dashboards, worfklow systems, corporate chat apps, that sort of thing.</p>
<p>Teams building these excruciatingly slow apps often assert that <em>&quot;startup performance isn't important because people start our app in the morning and keep it open all day&quot;</em>. At the limit, this can be true, but what this attempted deflection obscures is that performance is <em>cultural</em>. Teams that fail to define and measure critical user journeys (include loading) <em>always</em> fail to manage post-load interactivity too.</p>
<p>The old saying <em>&quot;how you do anything is how you do everything&quot;</em> is never more true than in software usability.</p>
<p>One consequence of cultures that fail to <a href="https://www.gov.uk/guidance/government-design-principles#first">put the user first</a> are products whose usability is so poor that attributes which <em>didn't</em> matter at the time of sale (like performance) become reasons to switch.</p>
<p>If you've ever had the distinct displeasure of using Concur or Workday, you'll understand what I mean. Challengers win business from them not by being wonderful, but simply by being usable. These incumbents are powerless to respond because their problems are now rooted deeply in the behaviours they rewarded through hiring and promotion along the way. The resulting management blindspot becomes a self-reinforcing norm that no single leader can shake.</p>
<p>This is why it's caustic to product success and brand value to allow a culture of disrespect towards users in favour of venerating developers (e.g., &quot;DX&quot;). The only antidote is to stamp it out wherever it arises by demanding user-focused realism in decision making.</p>
</blockquote>
<h2 id="%22but...%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22but...%22">&quot;But...&quot;</a></h2>
<p>To get unstuck, managers and tech leads that become wedded to frameworkism have to work through a series of easily falsified rationales offered by Over Reactors in service of their chosen ideology. Note, as you read, that none of these protests put the user experience front-and-centre. This admission by omission is a reliable property of the conversations these sketches are drawn from.</p>
<h3 id="%22...we-need-to-move-fast%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...we-need-to-move-fast%22">&quot;...we need to move fast&quot;</a></h3>
<p>This chestnut should be answered with the question: <em>&quot;for how long?&quot;</em></p>
<p>The dominant outcome of fling-stuff-together-with-NPM, feels-fine-on-my-$3K-laptop development is to get teams stuck in the mud much sooner than anyone expects.</p>
<p>From major accessibility defects to brand-risk levels of lousy performance, the consequence of this approach has been crossing my desk every week for a decade. The one thing I can tell you that all of these teams and products have in common is that <em>they are not moving faster</em>.</p>
<p>Brands you've heard of and websites you used <em>this week</em> have come in for help, which we've dutifully provided. The general prescription is <em>&quot;spend a few weeks/months unpicking this Gordian knot of JavaScript.&quot;</em></p>
<p>The time spent in remediation <em>does</em> fix the revenue and accessibility problems that JavaScript exuberance cause, but teams are dead in the water while they belatedly add ship gates and bundle size controls and processes to prevent further regression.</p>
<p>This necessary, painful, and expensive remediation generally comes at the worst time and with little support, owing to the JavaScript-industrial-complex's omerta. Managers trapped in these systems experience a sinking realisation that choices made in haste are not so easily revised. Complex, inscrutable tools introduced in the &quot;move fast&quot; phase are now systems that teams must dedicate time to learn, understand deeply, and affirmatively operate. All the while the pace of feature delivery is dramatically reduced.</p>
<p>This isn't what managers <em>think</em> they're signing up for when accepting <em>&quot;but we need to move fast!&quot;</em></p>
<p>But let's take the assertion at face value and assume a team that <em>won't</em> get stuck in the ditch (🤞): the idea embedded in this statement is, roughly, that there <em>isn't</em> time to do it right (so React?), but there <em>will be</em> time to do it over.</p>
<p>This is in direct opposition to identifying <a href="https://en.wikipedia.org/wiki/Product-market_fit">product-market-fit</a>. After all, the way to find who will want your product is to <a href="https://startupljackson.com/post/83244692828/html-first">make it as widely available as possible, <em>then</em> to add UX flourishes.</a></p>
<p>Teams I've worked with are frequently astonished to find that removing barriers to use opens up new markets and <a href="https://blog.chriszacharias.com/page-weight-matters">leads to growth in parts of a world they had under-valued.</a></p>
<p>Now, if you're selling <a href="https://en.wikipedia.org/wiki/Veblen_good">Veblen goods,</a> by all means, prioritise anything but accessibility. But in literally every other category, the returns to quality can be best understood as clarity of product thesis. A low-quality experience — which is what is being proposed when React is offered as an expedient — is a drag on the core growth argument for your service. And if the goal is scale, rather than exclusivity, building for legacy desktop browsers that Microsoft won't even sell you at the cost of harming the experience <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">for the majority of the world's users</a> is a strategic error.</p>
<h3 id="%22...it-works-for-facebook%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...it-works-for-facebook%22">&quot;...it works for Facebook&quot;</a></h3>
<p>To a statistical certainty, you aren't making Facebook. Your problems likely look nothing like Facebook's early 2010s problems, and even if they did, following their lead <a href="http://okayfail.com/garden/youre-not-facebook-why-use-their-tools.html">is a <em>terrible</em> idea.</a></p>
<p>And these tools <a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&amp;url=https%3A%2F%2Fwww.facebook.com%2F&amp;identifier=url&amp;device=PHONE&amp;periodStart=0&amp;periodEnd=-1&amp;display=p75s"><em>aren't even working for Facebook</em></a> (or <a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&amp;url=https%3A%2F%2Fwww.instagram.com%2F&amp;identifier=url&amp;device=PHONE&amp;periodStart=0&amp;periodEnd=-1&amp;display=p75s">IG</a>, or <a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&amp;url=https%3A%2F%2Fwww.threads.com%2F&amp;identifier=url&amp;device=PHONE&amp;periodStart=0&amp;periodEnd=-1&amp;display=p75s">Threads</a>). They just happen to be a monopoly in various social categories and can afford to light money on fire. If that doesn't describe your situation, it's best not to over index on narratives premised on Facebook's perceived success.</p>
<h3 id="%22...our-teams-already-know-react%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...our-teams-already-know-react%22">&quot;...our teams already know React&quot;</a></h3>
<p>React developers <em>are web developers</em>. They have to operate in a world of CSS, HTML, JavaScript, and DOM. It's inescapable. This means that React is the most fungible layer in the stack. Moving between templating systems (which is what JSX is) is what web developers have done fluidly for more than 30 years. Even folks with deep expertise in, say, Rails and ERB, can easily knock out Django or Laravel or WordPress or 11ty sites. There are differences, sure, but every web developer is a polyglot.</p>
<p>React knowledge is also not particularly valuable. Any team familiar with React's...baroque...conventions can easily master Preact, Stencil, Svelte, Lit, FAST, Qwik, or any of a dozen faster, smaller, reactive client-side systems that demand less mental bookkeeping.</p>
<h3 id="%22...we-need-to-be-able-to-hire-easily%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...we-need-to-be-able-to-hire-easily%22">&quot;...we need to be able to hire easily&quot;</a></h3>
<p>The tech industry has just seen many of the most talented, empathetic, and user-focused engineers I know laid off for no reason other than their management couldn't figure out that there would be some mean reversion post-pandemic. Which is to say, there's a fire sale on talent right now, and you can ask for <em>whatever skills you damn well please</em> and get good returns.</p>
<p>If you cannot attract folks who know web standards and fundamentals, reach out. I'll help you formulate recs, recruiting materials, hiring rubrics, and promotion guides to value these folks the way you should: unreasonably effective collaborators that will do incredible good for your products at a fraction of the cost of solving the next problem the React community is finally acknowledging that React caused.</p>
<h4 id="resumes-aren't-murder%2Fsuicide-pacts" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#resumes-aren't-murder%2Fsuicide-pacts">Resumes Aren't Murder/Suicide Pacts</a></h4>
<p>But <em>even if</em> you decide you want to run interview loops to filter for React knowledge, that's not a good reason to use it! Anyone who can master the dark thicket of build tools, typescript foibles, and the million little ways that JSX's fork of HTML and JavaScript syntax trips folks up is <em>absolutely</em> good enough to work in a different system.</p>
<p>Heck, they're <em>already</em> working in an ever-shifting maze of faddish churn. <a href="https://polotek.net/posts/the-frontend-treadmill/">The treadmill is real,</a> which means that the question isn't <em>&quot;will these folks be able to hit the ground running?&quot;</em> (answer: no, they'll spend weeks learning your specific setup regardless), it's <em>&quot;what technologies will provide the highest ROI over the life of our team?&quot;</em></p>
<p>Given the extremely high costs of React and other frameworkist prescriptions, the odds that this calculus will favour the current flavour of the week over the lifetime of even a single project are vanishingly small.</p>
<h4 id="the-bootcamp-thing" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#the-bootcamp-thing">The Bootcamp Thing</a></h4>
<p>It makes me nauseous to hear managers denigrate talented engineers, and there seems to be a rash of it going around. The idea that folks who come out of bootcamps — folks who just <em>paid to learn whatever was on the syllabus</em> — aren't able or willing to pick up some alternative stack is bollocks.</p>
<p>Bootcamp grads might be junior, and they are generally steeped in varying strengths of frameworkism, but they're not stupid. They want to do a good job, and it's management's job to define what that is. Many new grads might know React, but they'll learn a dozen other tools along the way, and React is by far <a href="https://joshcollinsworth.com/blog/antiquated-react#frameworks-arent-as-hard-to-learn-anymore">the most (unnecessarily) complex of the bunch.</a> The idea that folks who have mastered the horrors of <code>useMemo</code> and friends can't take on board <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components">DOM lifecycle methods</a> or <a href="https://www.youtube.com/watch?v=cCOL7MC4Pl0">the event loop</a> or modern CSS is <em>insulting</em>. It's unfairly stigmatising and limits the organisation's potential.</p>
<p>In other words, definitionally atrocious management.</p>
<h3 id="%22...everyone-has-fast-phones-now%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...everyone-has-fast-phones-now%22">&quot;...everyone has fast phones now&quot;</a></h3>
<p>For more than a decade, the core premise of frameworkism has been that client-side resources are cheap (or are getting increasingly inexpensive) and that it is, therefore, reasonable to trade some end-user performance for developer convenience.</p>
<p>This has been an absolute debacle. Since at least 2012, the rise of mobile falsified this contention, <a href="https://infrequently.org/series/performance-inequality/">and (as this blog has meticulously catalogued) we are only <em>just</em> starting to turn the corner.</a></p>
<p>Frameworkist assertion that <em>&quot;everyone has fast phones&quot;</em> is many things, but first and foremost it's an admission that the folks offering it don't know what they're talking about — and they hope you don't either.</p>
<p>No business trying to make it on the web can afford what they're selling, and you are under no obligation to offer your product as sacrifice to a false god.</p>
<h3 id="%22...react-is-industry-standard%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...react-is-industry-standard%22">&quot;...React is industry-standard&quot;</a></h3>
<p>This is, at best, a comforting fiction.</p>
<p>At worst, it's a knowing falsity that serves to omit the variability in React-based stacks because, you see, React isn't one thing. It's more of a lifestyle, complete with choices to make about React itself (function components or class components?) languages and compilers (typescript or nah?), package managers and dependency tools (npm? yarn? pnpm? turbo?), bundlers (webpack? esbuild? swc? rollup?), meta-tools (vite? turbopack? nx?), &quot;state management&quot; tools (redux? mobx? apollo? something that actually <em>manages</em> state?) and so on and so forth. And that's before we discuss plugins to support different CSS transpilation, among other optional side-quests frameworkists insist are necessary.</p>
<p>Across more than 100 consulting engagements, I've never seen two identical React setups, save smaller cases where the defaults of <a href="https://create-react-app.dev/docs/getting-started/">Create React App</a> were unchanged. CRA itself changed dramatically over the years before <a href="https://react.dev/blog/2025/02/14/sunsetting-create-react-app">finally being removed from the React docs as the best way to get started.</a></p>
<p>There's nothing standard about any of this. It's all change, all the time, and anyone who tells you differently is not to be trusted.</p>
<h4 id="the-bare-(assertion)-minimum" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#the-bare-(assertion)-minimum">The Bare (Assertion) Minimum</a></h4>
<p>Hopefully, if you've made it this far, you'll forgive a digression into how the <em>&quot;React is industry standard&quot;</em> misdirection became so embedded.</p>
<p>Given the overwhelming evidence that this stuff <a href="https://treo.sh/sitespeed/www.instagram.com?formFactor=phone&amp;mapMetric=r&amp;metrics=lcp%2Cr">isn't even working</a> on the sites of the <a href="https://treo.sh/sitespeed/www.airbnb.com?formFactor=phone&amp;mapMetric=r&amp;metrics=lcp%2Cr">titular React poster children,</a> how did we end up with React in so many nooks and crannies of contemporary frontend?</p>
<p>Pushy know-it-alls, that's how. Frameworkists have a way of hijacking every conversation with assertions like <em>&quot;virtual DOM is fast&quot;</em> without ever understanding anything about how browsers work, let alone the GC costs of their (extremely chatty) alternatives. This same ignorance allows them to confidently assert that React is &quot;fine&quot; when cheaper alternatives exist in every dimension.</p>
<p>These are not serious people. You do not have to entertain arguments offered without evidence. But you <em>do</em> have to oppose them and create data-driven structures that put users first. The long-term costs of these errors are enormous, as witnessed by the parade of teams needing our help to achieve minimally decent performance using stacks that were supposed to be &quot;performant&quot; (sic).</p>
<h3 id="%22...the-ecosystem...%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...the-ecosystem...%22">&quot;...the ecosystem...&quot;</a></h3>
<p>Which part, exactly? Be <em>extremely</em> specific. Which packages are so valuable, yet wedded entirely to React, that a team should not entertain alternatives? Do they <em>really</em> not work with <a href="https://preactjs.com/">Preact</a>? How much money is <em>exactly</em> the right amount to burn to use these libraries? Because that's the debate.</p>
<p>Even if you get the benefits of &quot;the ecosystem&quot; at Time 0, why do you think that will continue to pay out at T+1? Or T+N?</p>
<p>Every library presents a separate, stochastic risk of abandonment. Even the <a href="https://create-react-app.dev/">most heavily used systems</a> fall out of favour with the JavaScript-industrial-complex's in-crowd. This strands teams in the same position they'd have been in if they accepted ownership of more of the stack up-front, but with less experience and agency. Is that a good trade? Does your boss agree?</p>
<p>And <a href="https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b">how's that &quot;CSS-in-JS&quot; adventure working out?</a> Still writing class components, or did you have a big forced (and partial) migration that's still creating headaches?</p>
<p>The truth is that every single package that is part of a repo's <code>devDependencies</code> is, or will be, fully owned by the consumer of the package. The only bulwark against uncomfortable surprises is to consider NPM dependencies a high-interest loan <a href="https://en.wikipedia.org/wiki/Collateral_(finance)">collateralized</a> by future engineering capacity.</p>
<p>The best way to prevent these costs spiralling out of control is to fully examine and approve <em>each and every dependency</em> for UI tools and build systems. If your team is not comfortable agreeing to own, patch, and improve every single one of those systems, they should not be part of your stack.</p>
<h3 id="%22...next.js-can-be-fast-(enough)%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...next.js-can-be-fast-(enough)%22">&quot;...Next.js can be fast (enough)&quot;</a></h3>
<p>Do you feel lucky, punk? Do you?</p>
<p>You'll have to be lucky to <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-failure-on-repeat-2">beat the odds.</a></p>
<p>Sites built with Next.js perform materially worse than those from HTML-first systems like <a href="https://www.11ty.dev/">11ty</a>, <a href="https://astro.build/">Astro</a>, et al.</p>
<p>It simply does not scale, and the fact that it drags React behind it like a ball and chain is a double demerit. The <a href="https://fediverse.zachleat.com/@zachleat/111524558114433017">chonktastic default payload</a> of delay-loaded JS in any Next.js site will compete with ads and other business-critical deferred content for bandwidth, and that's before custom components and routes are added. <em>Even when using React Server Components</em>. Which is to say, Next.js is a fast way to lose a lot of money while getting <a href="https://thenewstack.io/opennext-gets-closer-to-making-next-js-truly-portable/">locked in to a VC-backed startup's proprietary APIs.</a></p>
<p>Next.js starts bad and only gets worse from a <a href="https://fediverse.zachleat.com/@zachleat/111524558114433017">shocking baseline.</a> No wonder the only Next sites that seem to perform well are those that enjoy overwhelmingly wealthy user bases, hand-tuning assistance from Vercel, or both.</p>
<p>So, do you feel lucky?</p>
<h3 id="%22...react-native!%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#%22...react-native!%22">&quot;...React Native!&quot;</a></h3>
<p>React Native is a good way to make a slow app that <a href="https://www.sitepoint.com/react-native-apps-performance-tips/">requires constant hand-tuning</a> and an <em>excellent</em> way to make <a href="https://treo.sh/sitespeed/bsky.app/vs/twitter.com/vs/elk.zone?formFactor=phone&amp;metrics=lcp%2Cr">a terrible website.</a> It has also been <a href="https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a">abandoned by it's poster children.</a></p>
<p>Companies that want to deliver compelling mobile experiences into app stores from the same codebase as their website are better served investigating <a href="https://developer.chrome.com/docs/android/trusted-web-activity">Trusted Web Activities</a> and <a href="https://www.pwabuilder.com/">PWABuilder.</a> If those don't work, <a href="https://capacitorjs.com/">Capacitor</a> and <a href="https://cordova.apache.org/">Cordova</a> can deliver similar benefits. These approaches make most native capabilities available, but centralise UI investment on the web side, providing visibility and control via a single execution path. This, in turn, reduces duplicate optimisation and accessibility headaches.</p>
<h2 id="references" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/11/if-not-react-then-what/#references">References</a></h2>
<p>These are essential guides for frontend realism. I recommend interested tech leads, engineering managers, and product managers digest them all:</p>
<ul>
<li><a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">&quot;Building a robust frontend using progressive enhancement&quot;</a> from the UK's Government Digital Service.</li>
<li><a href="https://muan.co/posts/javascript">&quot;JavaScript dos and donts&quot;</a> by Github alumnus Mu-An Chiou.</li>
<li><a href="https://crukorg.github.io/engineering-guidebook/docs/frontend/choosing_your_stack/">&quot;Choosing Your Stack&quot;</a> from Cancer Research UK</li>
<li><a href="https://alexsexton.com/blog/2014/11/the-monty-hall-rewrite">&quot;The Monty Hall Rewrite&quot;</a> by Alex Sexton, which breaks down the essential ways that a failure to run an honest bake off harms decision-making.</li>
<li><a href="https://joshcollinsworth.com/blog/antiquated-react">&quot;Things you forgot (or never knew) because of React&quot;</a> by Josh Collinsworth, which enunciates just how baroque and parochial React's culture has become.</li>
<li><a href="https://polotek.net/posts/the-frontend-treadmill/">&quot;The Frontend Treadmill&quot;</a> by Marco Rogers explains the costs of frameworkism better than I ever could.</li>
<li><a href="https://kellanem.com/notes/new-tech">&quot;Questions for a new technology&quot;</a> by Kellan Elliott-McCrea and Glyph's <a href="https://blog.glyph.im/2024/07/against-innovation-tokens.html">&quot;Against Innovation Tokens&quot;</a>. Together, they set a well-focused lens for thinking about how frameworkism is antithetical to functional engineering culture.</li>
</ul>
<p>These pieces are from teams and leaders that have succeeded in outrageously effective ways by applying the realist tenants of <em>looking around for themselves</em> and <em>measuring.</em> I wish you the same success.</p>
<div class="thanks">
<p>Thanks to <a href="https://muan.co/">Mu-An Chiou</a>, <a href="https://www.hasanhaja.com/">Hasan Ali</a>, <a href="https://joshcollinsworth.com/">Josh Collinsworth</a>, <a href="https://www.delarre.net/">Ben Delarre</a>, <a href="https://sylormiller.com/">Katie Sylor-Miller</a>, and <a href="https://mary.my.id/">Mary</a> for their feedback on drafts of this post.</p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-why-not-1" class="footnote-item"><p>Why not React? <a href="https://www.zachleat.com/web/react-criticism/">Dozens of reasons,</a> but a shortlist must include:</p>
<ul>
<li><strong>React is legacy technology.</strong> It was built for a world where IE 6 still had measurable share, and it shows.
<ul>
<li>React's synthetic event system and hard-coded element list are a direct consequence of IE's limitations. Independently, these create portability and performance hazards. Together, they become a driver of lock-in.</li>
<li>No contemporary framework contains equivalents because <em>no other framework is fundamentally designed around the need to support IE</em>.</li>
<li>It's beating a dead horse, but <a href="https://support.microsoft.com/en-us/office/which-browsers-work-with-microsoft-365-for-the-web-and-microsoft-365-add-ins-ad1303e0-a318-47aa-b409-d3a5eb44e452">Microsoft's own flagship apps do not support IE</a>. <a href="https://learn.microsoft.com/en-us/lifecycle/products/internet-explorer-11">You cannot buy support for IE.</a> It has even been <a href="https://techcommunity.microsoft.com/blog/windows-itpro-blog/internet-explorer-11-desktop-app-retirement-faq/2366549">forcibly removed from Windows 10 machines</a> and <a href="https://gs.statcounter.com/browser-market-share/desktop/worldwide">has not appeared above the noise</a> in global browser market share stats for <a href="https://gs.statcounter.com/browser-market-share/desktop/worldwide/2020">more than 4 years.</a> <br /><br />New projects will never encouter IE, and it's vanishingly unlikely that existing applications need to support it — which is helpful, because nobody can securely test on it anyway.</li>
</ul>
</li>
<li><strong>Virtual DOM <a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead">was <em>never</em> fast.</a></strong>
<ul>
<li>React was forced to <a href="https://web.archive.org/web/diff/20140613075553/20150403030402/http://facebook.github.io/react/">back away</a> from misleading performance claims almost immediately.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-ignorance-or-malice-11" id="fnref-ignorance-or-malice-11">11</a></sup></li>
<li>In addition to being unnecessary to achieve reactivity, React's diffing model and poor support for dataflow management conspire to <a href="https://www.eventbrite.com/engineering/a-story-of-a-react-re-rendering-bug/">regularly generate</a> extra main-thread work in the critical path. The &quot;solution&quot; is to <a href="https://www.joshwcomeau.com/react/why-react-re-renders/">learn (and zealously apply)</a> a set of <a href="https://alexsidorenko.com/blog/react-render-usememo">extremely baroque</a>, React-specific solutions to problems React itself causes.</li>
<li>The only (positive) contribution to performance that React's doubled-up work model can, in theory, provide is a structured lifecycle that helps programmers avoid <a href="https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing#avoid_forced_synchronous_layouts">reading back style and layout information at the moments when it's most expensive.</a></li>
<li>In practice, React does not prevent forced layouts and is not able to even warn about them. Unsurprisingly, every React app that crosses my desk is littered with layout thrashing bugs.</li>
<li>The only defensible performance claims Reactors make for their work-doubling system are phrased as a trade; e.g. <em>&quot;CPUs are fast enough now that we can afford to do work twice for developer convenience.&quot;</em>
<ul>
<li>Except they aren't. CPUs stopped getting faster about the same time as Reactors began to perpetuate this myth. This did not stop them from <a href="https://httparchive.org/reports/techreport/comparison?median-weight-over-time=js&amp;tech=ALL%2CReact%2CAngular&amp;geo=ALL&amp;rank=Top+1M#report-content">pouring JS into the ecosystem</a> as though the old trends had held, with <a href="https://infrequently.org/2024/08/object-lesson/">predictably disasterous results</a>
<picture style="width: 100%; margin: 10px 0px;">
<a target="_new" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png">
<img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png" alt="Sales volumes of the high-end devices that continues to get faster stagnated over the past decade. Meanwhile, the low end exploded in volume whole remaining stubbornly fixed in performance." decoding="async" loading="lazy" style="width: 100%; border: 5px solid white; aspect-ratio: 608 / 343;" /></a>
</picture></li>
<li>It isn't even necessary to do all the work twice to get reactivity! Every other reactive component system from the past decade is significantly more efficient, <a href="https://bundlephobia.com/scan-results?packages=react,react-dom,preact,lit,svelte,vue,solid-js,lwc">weighs less on the wire,</a> and preserves the advantages of reactivitiy <em>without</em> creating horrible &quot;re-render debugging&quot; hunts that take weeks away from getting things done.</li>
</ul>
</li>
</ul>
</li>
<li><strong>React's thought leaders have been wrong about <a href="https://infrequently.org/series/performance-inequality/">frontend's constraints for more than a decade.</a></strong>
<ul>
<li>Why would you trust them now? <a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&amp;url=https%3A%2F%2Fm.facebook.com%2F&amp;identifier=origin&amp;device=PHONE&amp;periodStart=0&amp;periodEnd=-1&amp;display=p75s">Their own websites</a> perform <a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&amp;url=https%3A%2F%2Fwww.instagram.com%2F&amp;identifier=origin&amp;device=PHONE&amp;periodStart=0&amp;periodEnd=-1&amp;display=p75s">poorly</a> in the real world.</li>
</ul>
</li>
<li><strong>The money you'll save can be measured in truck-loads.</strong>
<ul>
<li>Teams that correctly cabin complexity to the server side can avoid paying inflated salaries to begin with.</li>
<li>Teams that <em>do</em> build SPAs can more easily control the costs of those architectures by starting with a cheaper baseline and building a <a href="https://infrequently.org/2022/05/performance-management-maturity/">mature performance culture</a> into their organisations from the start.</li>
</ul>
</li>
<li>Not for nothing, but avoiding React will insulate your team from the assertion-heavy, data-light React discourse.</li>
</ul>
<p>Why pick a slow, backwards-looking framework whose architecture is compromised to serve legacy browsers when smaller, faster, better alternatives with all of the upsides (and none of the downsides) have been production-ready and successful <em>for years</em>? <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-why-not-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-devils-computer-2" class="footnote-item"><p>Frontend web development, like other types of client-side programming, is under-valued by &quot;generalists&quot; who do not respect just how <em>freaking hard</em> it is to deliver fluid, interactive experiences on devices you don't own and can't control. Web development turns this up to eleven, presenting a wicked effective compression format for UIs (HTML &amp; CSS) but forces experiences to load at runtime across high-latency, narrowband connections. To low-end devices. With no control over which browser will execute the code.</p>
<p>And yet, browsers and web developers frequently collude to deliver outstanding interactivity under these conditions. Often enough, that &quot;generalists&quot; don't give a second thought to the miracle of HTML-centric Wikipedia and MDN articles loading consistently quickly, as they gleefully clog those narrow pipes with JavaScript payloads so large that they can't possibly deliver similarly good experiences. All because they neither understand nor respect client-side constraints.</p>
<p>It's enough to make thoughtful engineers tear their hair out. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-the-devils-computer-2" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-the-devils-computer-2:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ballot-stuffing-3" class="footnote-item"><p>Tom Stoppard's classic quip that <em>&quot;it's not the voting that's democracy; it's the counting&quot;</em> chimes with the importance of impartial and objective criteria for judging the results of bake offs.</p>
<p>I've witnessed more than my fair share of stacked-deck proof-of-concept pantomimes, often inside large organisations with tremendous resources and managers who say all the right things. But honesty demands more than lip service.</p>
<p>Organisations looking for a complicated way to excuse pre-ordained outcomes should skip the charade. It will only make good people cynical and increase resistance. Teams that want to set bales of benajmins on fire because of frameworkism shouldn't be afraid to say what they want.</p>
<p>They were going to get it anyway; warts and all. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-ballot-stuffing-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-cut-lines-4" class="footnote-item"><p>An example of easy cut lines for teams considering contemporary development might be browser support versus bundle size.</p>
<p>In 2024, no new application will need to support IE or even legacy versions of Edge. They are not a measurable part of the ecosystem. This means that tools that took the design constraints imposed by IE as a given can be discarded from consideration. The extra client-side weight they require to service IE's quirks makes them uncompetitive from a bundle size perspective.</p>
<p>This eliminates React, Angular, and Ember from consideration without a single line of code being written; a tremendous savings of time and effort.</p>
<p>Another example is lock-in. Do systems support interoperability across tools and frameworks? Or will porting to a different system require a total rewrite? A decent proxy for this choice is Web Components support.</p>
<p>Teams looking to avoid lock-in can remove frameworks from consideration that do not support Web Components as both an export and import format. This will still leave many contenders, and management can rest assured they will not leave the team high-and-dry.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-reversability-14" id="fnref-reversability-14">14</a></sup> <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-cut-lines-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-buck-passing-5" class="footnote-item"><p>The stories we hear when interviewing members of these teams have an unmistakable buck-passing flavour. Engineers will claim (without evidence) that React is a great<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-or-whatever-13" id="fnref-or-whatever-13">13</a></sup> choice for their blog/e-commerce/marketing-microsite because <em>&quot;it needs to be interactive&quot;</em> — by which they mean it has a Carousel and maybe a menu and some parallax scrolling. None of this is an argument for React <em>per se</em>, but it can sound plausible to managers who trust technical staff about technical matters.</p>
<p>Others claim that <em>&quot;it's an SPA&quot;</em>. But <em>should</em> it be a Single Page App? Most are unprepared to answer that question for the simple reason they haven't thought it through.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-rubrics-9" id="fnref-rubrics-9:2">9:2</a></sup></p>
<p>For their part, contemporary product managers seem to spend a great deal of time doing things that do not have any relationship to managing the essential qualities of their products.</p>
<p>Most need help making sense of <a href="https://cruxvis.withgoogle.com/">the RUM data already available to them.</a> Few are in touch with <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">device and network realities</a> of their current and future (🤞) users. PMs that clearly articulate critical-user-journeys for their teams are like hen's teeth. And I can count on one hand teams that have run bake offs — without resorting to binary. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-buck-passing-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-off-brand-therapy-6" class="footnote-item"><p>It's no exaggeration to say that team leaders encountering evidence that their React (or Angular, etc.) technology choices are letting down users and the business <em>go through some things</em>.</p>
<p>Following the herd is an adaptation to prevent their specific decisions from standing out — tall poppies and all that — and it's uncomfortable when those decisions receive belated scrutiny. But when the evidence is incontrovertible, needs must. This creates cognitive dissonance.</p>
<p>Few are so entitled and callous that they wallow in denial. Most want to improve. They don't come to work every day to make a <em>bad</em> product; they just thought the herd knew more than they did. It's disorienting when that turns out not to be true. That's more than understandable.</p>
<p>Leaders in this situation work through the <a href="https://en.wikipedia.org/wiki/Five_stages_of_grief">stages of grief</a> in ways that speak to their character.</p>
<p>Strong teams own the reality and look for ways to learn more about their users and the constraints that should shape product choices. The goal isn't to justify another rewrite, but to find targets the team should work towards, breaking down the problem into actionable steps. This is hard and often unfamiliar work, but it is rewarding. Setting accurate goalposts helps teams take credit as they make progress remediating the current mess. These are all markers of teams on the way to <a href="https://infrequently.org/2022/05/performance-management-maturity/">improving their performance management maturity.</a></p>
<p>Some get stuck in anger, bargaining, or depression. Sadly, these teams are taxing to help. Supporting engineers and PMs through emotional turmoil is a big part of a performance consultant's job. The stronger the team's attachment to <a href="https://infrequently.org/2023/02/the-market-for-lemons/">React community narratives</a>, the harder it can be to accept responsibility for defining team success in terms of <em>user</em> success. But that's the only way out of the deep hole they've dug.</p>
<p>Consulting experts can only do so much. Tech leads and managers that continue to prioritise &quot;Developer Experience&quot; (without metrics, obviously) and &quot;the ecosystem&quot; (pray tell, which parts?) in lieu of user outcomes can remain beyond reach, no matter how much empathy and technical analysis is provided. Sometimes, you have to cut bait and hope time and the costs of ongoing failure create the necessary conditions for change. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-off-brand-therapy-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-shortcuts-7" class="footnote-item"><p>Most are substituting (perceived) popularity for the work of understanding users and their needs. Starting with user needs creates constraints to work backwards from.</p>
<p>Instead of doing this work-back, many sub in short-term popularity contest winners. This goes hand-in-glove with a predictable failure to deeply understand business goals.</p>
<p>It's common to hear stories of companies shocked to find the PHP/Python/etc. systems they are replacing with React will require multiples of currently allocated server resources <em>for the same userbase</em>. The impacts of inevitably worse client-side lag cost dearly, but only show up later. And all of these costs are on top of the salaries for the bloated teams frameworkists demand.</p>
<p>One team shared that avoidance of React was tantamount to a trade secret. If their React-based competitors understood how expensive React stacks are, they'd lose their (considerable) margin advantage. Wild times. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-shortcuts-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-success-through-quality-8" class="footnote-item"><p>UIs that works well for <em>all</em> users aren't charity, they're hard-nosed business choices about market expansion and development cost.</p>
<p>Don't be confused: every time a developer makes a claim <em>without evidence</em> that a site doesn't need to work well on a low-end device, understand it as a true threat to your product's success, if not your own career.</p>
<p>The point of building a web experience is to maximize reach for the lowest development outlay, otherwise you'd build a bunch of native apps for every platform instead. Organisations that <em>aren't</em> spending bundles to build per-OS proprietary apps...well...<em>aren't doing that</em>. In this context, unbacked claims about why it's OK to exclude <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">large swaths of the web market</a> to introduce legacy desktop-era frameworks designed for browsers that <em>don't exist any more</em> work directly against strategy. Do not suffer them gladly.</p>
<p>In most product categories, quality and reach are the product attributes web developers can impact most directly. It's wasteful, bordering insubbordinate, to suggest that not delivering those properties is an effective use of scarce funding. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-success-through-quality-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-rubrics-9" class="footnote-item"><p>Should a site be built as a Single Page App?</p>
<p>A good way to work this question is to ask <em>&quot;what's the point of an SPA?&quot;</em>. The answer is that they <em>can</em> (in theory) reduce interaction latency, which <em>implies</em> many interactions per session. It's also an (implicit) claim about the costs of loading code up-front versus on-demand. This sets us up to create a rule of thumb.</p>
<picture>
  <img src="https://infrequently.org/2024/11/if-not-react-then-what/spa-decision-tree.avif" alt="Should this site be built as a Single Page App? A decision tree. (hint: at best, maybe)" decoding="async" loading="lazy" style="aspect-ratio: 1592 / 1802;" />
</picture>
<p>Sites should only be built as SPAs, or with SPA-premised technologies if and only if:</p>
<ul>
<li>They are known to have long sessions (more than ten minutes) on average</li>
<li>More than ten updates are applied to the <em>same</em> (primary) data</li>
</ul>
<p>This instantly disqualifies almost every e-commerce experience, for example, as sessions generally involve traversing pages with entirely different primary data rather than updating a subset of an existing UI. Most also feature average sessions that fail the length and depth tests. Other common categories (blogs, marketing sites, etc.) are even easier to disqualify. At most, these categories can stand a dose of progressive enhancement (but not too much!) owing to their shallow sessions.</p>
<p>What's left? Productivity and social apps, mainly.</p>
<p>Of course, there are many sites with bi-modal session types or sub-apps, all of which might involve different tradeoffs. For example, a blogging site is two distinct systems combined by a database/CMS. The first is a long-session, heavy interaction post-writing and editing interface for a small set of users. The other is a short-session interface for a much larger audience who mostly interact by loading a page and then scrolling. As the browser, not developer code, handles scrolling, we omit from interaction counts. For most sessions, this leaves us only a single data update (initial page load) to divide all costs by.</p>
<p>If the denominator of our equation is always close to one, it's nearly impossible to justify extra weight in anticipation of updates that will likely never happen.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-out-with-the-bathwater-12" id="fnref-out-with-the-bathwater-12">12</a></sup></p>
<p>To formalise slightly, we can understand average latency as the sum of latencies in a session, divided by the number of interactions. For multi-page architectures, a session's average latency (<math><msub><mi>L</mi><mi>avg</mi></msub></math>) is simply a session's summed <a href="https://web.dev/articles/lcp" title="Largest Contentful Paint"><math><mi>LCP</mi></math></a>'s divided by the number of navigations in a session (<math><mi>N</mi></math>):</p>
<math display="block">
  <msub>
    <msup>
      <mi>L</mi>
      <mi>m</mi>
    </msup>
    <mi>avg</mi>
  </msub>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>i</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mi>N</mi>
      </munderover>
      <mi>LCP</mi>
      <mo>(</mo>
      <mi>i</mi>
      <mo>)</mo>
    </mrow>
    <mi>N</mi>
  </mfrac>
</math>
<p>SPAs need to add initial navigation latency to the latencies of all other session interactions (<math><mi>I</mi></math>). The total number of interactions in a session <math><mi>N</mi></math> is:</p>
<math display="block">
  <mi>N</mi><mo>=</mo><mn>1</mn><mo>+</mo><mi>I</mi>
</math>
<p>The general form is of SPA average latency is:</p>
<math display="block">
  <msub>
    <mi>L</mi>
    <mi>avg</mi>
  </msub>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <mi>latency</mi>
      <mo>(</mo>
      <mi>navigation</mi>
      <mo>)</mo>
      <mo>+</mo>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>i</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mi>I</mi>
      </munderover>
      <mi>latency</mi>
      <mo>(</mo>
      <mi>i</mi>
      <mo>)</mo>
    </mrow>
    <mi>N</mi>
  </mfrac>
</math>
<p>We can handwave a bit and use <a href="https://web.dev/articles/inp" title="Interaction-to-Next Paint"><math><mi>INP</mi></math></a> <em>for each individual update</em> (via the Performance Timeline) as our measure of in-page update lag. This leaves some room for gamesmanship — the React ecosystem is famous for attempting to duck metrics accountability with scheduling shenanigans — so a real measurement system will need to substitute end-to-end action completion (including server latency) for <math><mi>INP</mi></math>, but this is a reasonable bootstrap.</p>
<p><math><mi>INP</mi></math> also helpfully omits scrolling unless the programmer does something problematic. This is correct for the purposes of metric construction as scrolling gestures are generally handled by the browser, not application code, and our metric should only measure what developers control. SPA average latency simplifies to:</p>
<math display="block">
  <msub>
    <msup>
      <mi>L</mi>
      <mi>s</mi>
    </msup>
    <mi>avg</mi>
  </msub>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <mi>LCP</mi>
      <mo>+</mo>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>i</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mi>I</mi>
      </munderover>
      <mi>INP</mi>
      <mo>(</mo>
      <mi>i</mi>
      <mo>)</mo>
    </mrow>
    <mi>N</mi>
  </mfrac>
</math>
<p>As a metric for architecture, this is simplistic and fails to capture <a href="https://en.wikipedia.org/wiki/Variance">variance</a>, which SPA defenders will argue matters greatly. How might we incorporate it?</p>
<p>Variance (<math><msup><mi>σ</mi><mn>2</mn></msup></math>) across a session is straightforward if we have logs of the latencies of all interactions and an understanding of <a href="https://newrelic.com/blog/best-practices/expected-distributions-website-response-times">latency distributions</a>. Assuming latencies follows the <a href="https://en.wikipedia.org/wiki/Erlang_distribution">Erlang distribution</a>, we would have to work to assess variance, except that complete logs simplify this to the usual population variance formula. Standard deviation (<math><mi>σ</mi></math>) is then just the square root:</p>
<math display="block">
  <msup>
    <mi>σ</mi>
    <mn>2</mn>
  </msup>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <mo>∑</mo>
      <msup>
        <mrow>
          <mo>(</mo>
          <mi>x</mi>
          <mo>-</mo>
          <mi>μ</mi>
          <mo>)</mo>
        </mrow>
        <mn>2</mn>
      </msup>
    </mrow>
    <mi>N</mi>
  </mfrac>
</math>
<p>Where <math><mi>μ</mi></math> is the mean (average) of the population <math><mi>X</mi></math>, the set of measured latencies in a session, with this value summed across all sessions.</p>
<p>We can use these tools to compare architectures and their outcomes, particularly the effects of larger up-front payloads for SPA architecture for sites with shallow sessions. Suffice to say, the smaller the deonominator (i.e., the shorter the session), the worse average latency will be for JavaScript-oriented designs and the more sensitive variance will be to population-level effects of hardware and networks.</p>
<p>A fuller exploration will have to wait for a separate post. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-rubrics-9" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-rubrics-9:1" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-rubrics-9:2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-no-ssr-doesnt-count-10" class="footnote-item"><p>Certain frameworkists will claim that <em>their</em> framework is fine for use in informational scenarios because their systems do &quot;Server-Side Rendering&quot; (a.k.a., &quot;SSR&quot;).</p>
<p>Parking for a moment discussion of the linguistic crime that &quot;SSR&quot; represents, we can reject these claims by substituting a test: does the tool in question send a copy of a library to support SPA navigations down the wire by default?</p>
<p>This test is helpful, as it shows us that React-based tools like Next.js are wholly unsuitable for this class of site, while React-friendly tools like <a href="https://astro.build/">Astro</a> are appropriate.</p>
<p>We lack a name for this test today, and I hope readers will suggest one. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-no-ssr-doesnt-count-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ignorance-or-malice-11" class="footnote-item"><p>React's initial claims of good performance <em>because</em> it used a virtual DOM were never true, and the React team was forced to retract them by 2015. But like many <a href="https://gh.bmj.com/content/5/11/e003719.abstract">zombie ideas</a>, there seems to have been no reduction in the rate of junior engineers regurgitating this long-falsified idea as a reason to continue to choose React.</p>
<p>How <em>did</em> such a <a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead#How-did-the-meme-start">baldly incorrect claim come to be offered in the first place?</a> The options are unappetising; either the React team knew their work-doubling machine was not fast but allowed others to think it was, or they didn't know but should have.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-private-views-15" id="fnref-private-views-15">15</a></sup></p>
<p>Neither suggest the sort of grounded technical leadership that developers or businesses should invest heavily in. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-ignorance-or-malice-11" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-out-with-the-bathwater-12" class="footnote-item"><p>It should go without saying, but sites that aren't SPAs shouldn't use tools that are premised entirely on optimistic updates to client-side data because sites that aren't SPAs shouldn't be paying the cost of creating a (separate, expensive) client-side data store separate from the DOM representation of HTML.</p>
<p>Which is the long way of saying that if there's React or Angular in your blogware, 'ya done fucked up, son. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-out-with-the-bathwater-12" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-or-whatever-13" class="footnote-item"><p>When it's pointed out that React is, in fact, <em>not</em> great in these contexts, the excuses come fast and thick. It's generally less than 10 minutes before they're rehashing some variant of how some <em>other</em> site is fast (without traces to prove it, obvs), and <em>it</em> uses React, so React is fine.</p>
<p>Thus begins an infinite regression of easily falsified premises.</p>
<p>The folks dutifully shovelling this bullshit aren't consciously trying to invoke Brandolini's Law in their defence, but that's the net effect. It's exhausting and principally serves to convince the challenged party <em>not</em> that they should try to understand user needs and build to them, but instead that you're an asshole. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-or-whatever-13" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-reversability-14" class="footnote-item"><p>Most managers pay lip service to the idea of preferring reversible decisions. Frustratingly, failure to put this into action is in complete alignment with social science research into the <a href="https://www.sciencedirect.com/science/article/abs/pii/S0022103113001443">psychology of decision-making biases</a> (<a href="https://pure.uva.nl/ws/files/1746420/130125_06.pdf">open access PDF summary</a>).</p>
<p>The job of managers is to <em>manage</em> these biases. Working against them involves building processes and objective frames of reference to nullify their effects. It isn't particularly challenging, but it is <em>work</em>. Teams that do not build this discipline pay for it dearly, particularly on the front end, where we program the devil's computer.<sup class="footnote-ref"><a href="https://infrequently.org/2024/11/if-not-react-then-what/#fn-the-devils-computer-2" id="fnref-the-devils-computer-2:1">2:1</a></sup></p>
<p>But make no mistake: choosing React is a one-way door; an irreversible decision that is costly to relitigate. Teams that buy into React implicitly opt into leaky abstractions like timing quirks of React's unique (as in, nobody else has one because it's costly and slow) synthentic event system and non-portable concepts like portals. React-based products are stuck, and the paths out are challenging.</p>
<p>This will seem comforting, but the long-run maintenance costs of being trapped in this decision are excruciatingly high. No wonder Over Reactors believe they should command a salary premium.</p>
<p>Whatcha gonna do, switch? <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-reversability-14" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-private-views-15" class="footnote-item"><p>Where do I come down on this?</p>
<p>My interactions with React team members over the years, combined with their confidently incorrect public statements about how browsers work, have convinced me that honest ignorance about their system's performance sat underneath misleading early claims.</p>
<p>This was likely exascerbated by a competitive landscape in which their customers (web developers) were unable to judge the veracity of the assertions, and a deference to authority; surely <em>Facebook</em> wouldn't mislead folks?</p>
<p>The need for an edge against Angular and other competitors also likely played a role. It's underappreciated how tenuous the position of frontend and client-side framework teams are within Big Tech companies. The Closure <a href="https://github.com/google/closure-library">library</a> and compiler that powered Google's most successful web apps (Gmail, Docs, Drive, Sheets, Maps, etc.) <em>was not staffed</em> for most of its history. It was literally a 20% project that the entire company depended on. For the React team to justify headcount within Facebook, public success was likely essential.</p>
<p>Understood in context, I don't entirely excuse the React team for their early errors, but they are understandable. What's not forgivable are the material and willful omissions by Facebook's React team once the evidence of terrible performance began to accumulate. The React team took no responsibility, did not explain the constraints that Facebook applied to their JavaScript-based UIs to make them perform as well as they do — particularly on mobile — and benefited greatly from <a href="https://infrequently.org/2023/02/the-market-for-lemons/">pervasive misconceptions</a> that continue to cast React is a better light than hard evidence can support. <a href="https://infrequently.org/2024/11/if-not-react-then-what/#fnref-private-views-15" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Platform Strategy and Its Discontents</title>
    <link href="https://infrequently.org/2024/10/platforms-are-competitions/"/>
    <updated>2024-10-27T00:00:00Z</updated>
    <id>https://infrequently.org/2024/10/platforms-are-competitions/</id>
    <content type="html"><![CDATA[
      <div style="font-size: 1rem;">
<p><em>This post is an edited and expanded version of a now-mangled <a href="https://toot.cafe/@slightlyoff/113346554300095442">Mastodon thread</a>.</em></p>
</div>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#platforms-are-competitions">Platforms Are Competitions</a></li><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#...and-we're-losing">...and We're Losing</a></li><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#win-condition">Win Condition</a></li><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#you-do-it-to-yourself%2C-and-that's-what-really-hurts">You Do It To Yourself, And That's What Really Hurts</a></li><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#groundhog-day">Groundhog Day</a></li><li><a href="https://infrequently.org/2024/10/platforms-are-competitions/#reboot">Reboot</a></li></ul></nav>
<p>Some in the JavaScript community <a href="https://www.youtube.com/watch?v=K_9JYPLU-8s&amp;t=404s">imagine that I harbour an irrational dislike of their tools</a> when, in fact, I want nothing more than to stop thinking about them. Live-and-let-live is excellent guidance, and if it weren't for React <em>et. al.</em>'s predictably ruinous outcomes, the public side of my work wouldn't involve educating about <a href="https://infrequently.org/series/performance-inequality/">the problems JS-first development has caused.</a></p>
<p>But that's not what strategy demands, and strategy is my job.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-ecosystem-strategy-is-a-weird-job-1" id="fnref-ecosystem-strategy-is-a-weird-job-1">1</a></sup></p>
<p>I've been holding my fire (and the confidences of consulting counterparties) for most of the last decade. Until <a href="https://infrequently.org/series/reckoning/">this year,</a> I only occasionally posted traces documenting the worsening rot. I fear this has only served to make things look <em>better</em> than they are.</p>
<p>Over the past decade, my work helping teams deliver competitive PWAs gave me a front-row seat to a disturbing trend. The rate of failure to deliver usable experiences on phones was <em>increasing</em> over time, despite the eye-watering cost of JS-based stacks teams were reaching for. Worse <em>and</em> costlier is a bad combo, and the opposite of what competing ecosystems did.</p>
<p>Native developers reset <em>hard</em> when moving from desktop to mobile, getting deeply in touch with the new constraints. Sure, developing a codebase multiple times is more expensive than the web's write-once-test-everywhere approach, but at least you got speed for the extra cost.</p>
<p>That's not what web developers did. Contemporary frontend practice pretended that legacy-oriented, desktop-focused tools would perform fine in this new context, without ever checking if they <em>did</em>. When that didn't work, the toxic-positivity crowd blamed the messenger.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-failure-on-repeat-2" id="fnref-failure-on-repeat-2">2</a></sup></p>
<p>Frontend's <a href="https://infrequently.org/2024/08/caprock/">tragically timed turn towards JavaScript</a> means the damage isn't limited to <a href="https://infrequently.org/2024/08/object-lesson/">the public sector</a> or &quot;bad&quot; developers. Some of the strongest engineers I know find themselves mired in the same quicksand. Today's popular JS-based approaches are simply unsafe at any speed. The rot is now ecosystem-wide, and JS-first culture owns a share of the responsibility.</p>
<p>But why do I care?</p>
<h2 id="platforms-are-competitions" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#platforms-are-competitions">Platforms Are Competitions</a></h2>
<p>I want the web to win.</p>
<p>What does that mean? Concretely, folks should be able to accomplish most of their daily tasks on the web. But capability isn't sufficient; for the web to win in practice, users need to turn to the browser for those tasks because it's easier, faster, and more secure.</p>
<p>A reasonable metric of success is <em>time spent as a percentage of time on device</em>.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-thirst-traps-3" id="fnref-thirst-traps-3">3</a></sup></p>
<p>But why should we prefer one platform over another when, in theory, they can deliver equivalently good experiences?</p>
<p>As I see it, the web is the only generational software platform that has a reasonable shot at delivering a potent set of benefits to users:</p>
<ul>
<li>Fresh</li>
<li>Frictionless</li>
<li>Safe by default</li>
<li>Portable and interoperable</li>
<li>Gatekeeper-free (no prior restraint on publication)<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-our-awol-tech-press-4" id="fnref-our-awol-tech-press-4">4</a></sup></li>
<li>Standards-based, and therefore...</li>
<li>User-mediated (extensions, browser settings, etc.)</li>
<li>Open Source compatible</li>
</ul>
<p>No other successful platform provides all of these, and others that could are too small to matter.</p>
<p>Platforms like Android and Flutter deliver subsets of these properties but capitulate to capture by the host OS agenda, allowing their developers to be taxed through app stores and proprietary API lock-in. Most treat user mediation like a bug to be fixed.</p>
<p>The web's inherent properties have created an ecosystem that is unique in the history of software, both in scope and resilience.</p>
<h2 id="...and-we're-losing" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#...and-we're-losing">...and We're Losing</a></h2>
<p>So why does this result in intermittent antagonism towards today's JS community?</p>
<p>Because the web is losing, and instead of recognising that we're all in it together, then pitching in to right the ship, the <a href="https://infrequently.org/2023/02/the-market-for-lemons/">Lemon Vendors</a> have decided that predatory delay and <em>&quot;I've got mine, Jack&quot;</em>-ism is the best response.</p>
<p>What do I mean by &quot;losing&quot;?</p>
<p>Going back to the time spent metric, the web is cleaning up on the desktop. The web's JTBD percentage and fraction of time spent both continue to rise as we add new capabilities to the platform, displacing other ways of writing and delivering software, one fraction of a percent every year.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-no-kos-5" id="fnref-no-kos-5">5</a></sup></p>
<p>The web is desktop's indispensable ecosystem. Who, a decade ago, thought the web would be such a threat to Adobe's native app business that it would need to respond with a <a href="https://news.adobe.com/news/news-details/2022/adobe-to-acquire-figma">$20BN acquisition attempt</a> and a full-fledged version of <a href="https://web.dev/articles/ps-on-the-web">Photoshop (<em>real</em> Photoshop) on the web?</a></p>
<p>Model advantages grind slowly but finely. They create space for new competitors to introduce the intrinsic advantages of their platform in previously stable categories. But only when specific criteria are met.</p>
<h2 id="win-condition" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#win-condition">Win Condition</a></h2>
<p>First and foremost, challengers need <strong>a cost-competitive channel</strong>. That is, users have to be able to acquire software that runs on this new platform without a lot of extra work. The web drops channel costs to nearly zero, assuming...</p>
<p><strong>80/20 capability</strong>. Essential use-cases in the domain have to be (reliably) possible for the vast majority (90+%) of the TAM. Some nice-to-haves might not be there, but the model advantage makes up for it. Lastly...</p>
<p><strong>It has to feel good</strong>. Performance can't suck for core tasks.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-status-tracking-6" id="fnref-status-tracking-6">6</a></sup> It's fine for UI consistency with native apps to wander a bit.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-ui-coherence-7" id="fnref-ui-coherence-7">7</a></sup> It's even fine for there to be a large peak performance delta. But the gap can't be such a gulf that it generally changes the <a href="https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/planning-and-measuring-performance#time">interaction class</a> of common tasks.</p>
<p>So if the web is meeting all these requirements on desktop – even running away with the lead – why am I saying &quot;the web is losing&quot;?</p>
<p>Because <a href="https://www.statista.com/statistics/265878/global-shipments-of-pcs-tablets-ultra-mobiles-mobile-phones/">more than 75% of new devices that can run full browsers are phones</a>. And the web is getting <em>destroyed</em> on mobile.</p>
<p>Utterly routed.</p>
<p></p><figure><picture style="--lqip: 172771" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/10/platforms-are-competitions/time-spent-statista.jpg&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/10/platforms-are-competitions/time-spent-statista.jpg" alt="It's not going well" style="aspect-ratio: 816 / 729" class="preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>It's not going well</figcaption>      </figure><p></p>
<p>This is what I <a href="https://vimeo.com/364402896">started warning about in 2019</a>, and more recently <a href="https://infrequently.org/2024/08/the-way-out/">on this blog.</a> The terrifying data I had access to five years ago is now visible from space.</p>
<p></p><figure><a href="https://www.emarketer.com/content/the-majority-of-americans-mobile-time-spent-takes-place-in-apps" alt="Public data <a href='https://vimeo.com/364402896'>shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web." target="_blank"><picture style="--lqip: 524212" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp" alt="Public data <a href='https://vimeo.com/364402896'>shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web." style="aspect-ratio: 1280 / 1325" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Public data <a href="https://vimeo.com/364402896">shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web.</figcaption>      </figure><p></p>
<p>If that graph looks rough-but-survivable, understand that it's only this high in the US (and other Western markets) because the web was <em>already</em> a success in those geographies when mobile exploded.</p>
<p>That history isn't shared in the most vibrant growth markets, meaning the web has fallen from &quot;minuscule&quot; to &quot;nonexistent&quot; as a part of mobile-first daily life globally.</p>
<p>This is the landscape. The web is extremely likely to get cast in amber and will, in less than a technology generation, become a weird legacy curio.</p>
<p>What happens then? The market for web developers will stop expanding, and the safe, open, interoperable, gatekeeper-free future for computing will be entirely foreclosed — or at least the difficulty will go from &quot;slow build&quot; to &quot;cold-start problem&quot;; several orders of magnitude harder (and therefore unlikely).</p>
<p>This failure has many causes, but they're all tractable. This is why I have worked so hard to close the capability gaps with <a href="https://web.dev/learn/pwa/service-workers">Service Workers</a>, <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">PWAs</a>, <a href="https://web.dev/explore/notifications">Notifications</a>, <a href="https://developer.chrome.com/docs/capabilities/fugu-showcase">Project Fugu</a>, and <a href="https://www.chromium.org/blink/launching-features/">structural solutions</a> to the <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">governance problems</a> that <a href="https://infrequently.org/2015/08/doing-science-on-the-web/">held back progress.</a> All of these projects have been motivated by the logic of platform competition, and the urgency that comes from understanding that that web doesn't have a natural constituency.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-fair-weather-friends-8" id="fnref-fair-weather-friends-8">8</a></sup></p>
<p>If you've read any of my writing over this time, it will be unsurprising that this is why I eventually had to break silence and <a href="https://infrequently.org/series/browser-choice-must-matter/">call out what Apple has done on iOS, and what Facebook and Android have done to more quietly undermine browser choice.</a></p>
<p>These gatekeepers are kneecapping the web in different, but overlapping and reinforcing ways. There's much more to say here, but I've tried to lay out the landscape <a href="https://infrequently.org/series/browser-choice-must-matter/">over the past few years,</a>. But even if we break open the necessary 80/20 capabilities and restart engine competition, today's web is unlikely to succeed on mobile.</p>
<h2 id="you-do-it-to-yourself%2C-and-that's-what-really-hurts" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#you-do-it-to-yourself%2C-and-that's-what-really-hurts">You Do It To Yourself, And That's What Really Hurts</a></h2>
<p>Web developers and browsers have capped the web's mobile potential by ensuring it will feel terrible on <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">the phones most folks have.</a> A web that can win is a web that doesn't feel like sludge. And today it does.</p>
<p>This failure has many fathers. Browsers have not done nearly enough to intercede on users' behalf; hell, we don't even warn users that links they tap on might take them to sites that lock up the main thread for seconds at a time!</p>
<p>Things have gotten so bad that even the extremely weak pushback on developer excess that Google's <a href="https://web.dev/articles/vitals">Core Web Vitals</a> effort provides is a slow-motion earthquake. <a href="https://developers.google.com/search/blog/2023/05/introducing-inp">INP,</a> in particular, is forcing even the worst JS-first lemon vendors to <a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components">retreat to the server</a> — a tacit acknowledgement that their shit stinks.</p>
<p>So this is the strategic logic of why web performance matters in 2024; for the web to survive, it must start to grow on mobile. For that growth to start, we need the web to be a credible way to deliver these sorts of 80/20 capability-enabled mobile experiences with not-trash performance. That depends both on browsers that don't suck (we see you, Apple) and websites that don't consistently lock up phones and drain batteries.</p>
<p>Toolchains and communities that retreat into the numbing comfort of desktop success are a threat to that potential.</p>
<p>There's (much) more for browsers to do here, but developers that want the web to succeed can start without us. Responsible, web-ecology-friendly development is more than possible today, and the great news is that <a href="https://wpostats.com/">it tends to make companies more money, too!</a></p>
<p>The JS-industrial-complex culture that pooh-poohs responsibility is self-limiting and a harm to our collective potential.</p>
<h2 id="groundhog-day" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#groundhog-day">Groundhog Day</a></h2>
<p>Nobody has ever hired me to work on performance.</p>
<p>It's (still) on my plate because terrible performance is a limiting factor on the web's potential to heal and grow. Spending nearly half my time diagnosing and remediating easily preventable failure <em>is not fun</em>. The teams I sit with <em>are not having fun either</em>, and goodness knows there are APIs I'd <em>much</em> rather be working on instead.</p>
<p>My work today, and for the past 8 years, has only included performance because until it's fixed <em>the whole web</em> is at risk.</p>
<p>It's actually that dire, and <a href="https://infrequently.org/series/performance-inequality/">the research I publish</a> indicates that we are not on track to cap our JS emissions or mitigate them with CPUs fast enough to prevent ecosystem collapse.</p>
<p>Contra the framework apologists, pervasive, preventable failure to deliver usable mobile experiences <em>is</em> often because we're dragging around IE 9 compat and long toolchains premised on outdated priors like a ball and chain.<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-sinking-costs-9" id="fnref-sinking-costs-9">9</a></sup></p>
<h2 id="reboot" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/10/platforms-are-competitions/#reboot">Reboot</a></h2>
<p>Things look bad, and I'd be remiss if I didn't acknowledge that it could just be too late. Apple and Google and Facebook, with the help of a pliant and credulous JavaScript community, might have succeeded where 90s-era Microsoft failed — we just don't know it yet.</p>
<p>But it seems equally likely that the web's advantages are just dormant. When browser competition is finally unlocked, and when web pages aren't bloated with <a href="https://httparchive.org/reports/state-of-javascript">half a megabyte of JavaScript (on average)</a>, we <em>can</em> expect a revolution. But we need to prepare for that day and do everything we can to make it possible.</p>
<p>Failure and collapse aren't pre-ordained. We <em>can</em> do better. We <em>can</em> grow the web again. But to do that, the frontend community has to decide that user experience, the web's health, and their own career prospects are more important than whatever JS-based dogma VC-backed SaaS vendors are shilling this month.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-ecosystem-strategy-is-a-weird-job-1" class="footnote-item"><p>My business card says <em>&quot;Product Manager&quot;</em> which is an uncomfortable fudge in the same way <em>&quot;Software Engineer&quot;</em> was an odd fit in my dozen+ years on the Chrome team.</p>
<p>My job on both teams has been somewhat closer to <em>&quot;Platform Strategist for the Web&quot;</em>. But nobody hires platform strategists, and when they do, it's to support proprietary platforms. The tactics, habits of mind, and ways of thinking about platform competition for open vs. closed platforms could not be more different. Indeed, I've seen many successful proprietary-platform folks try their hand at open systems and bounce hard off the different constraints, cultures, and &quot;soft power&quot; thinking they require.</p>
<p>Doing strategy on behalf of a collectively-owned, open system is extremely unusual. Getting paid to do it is almost unheard of. And the job itself is strange; because facts about the ecosystem develop slowly, there isn't a great deal to re-derive from current events.</p>
<p>Companies also don't ask strategists to design and implement solutions in the opportunity spaces they identify. But solving problems is the only way to deliver progress, so along with others who do roughly similar work, I have camped out in roles that allow arguments about the health of the web ecosystem to motivate the concrete engineering projects necessary to light the fuse of web growth.</p>
<p>Indeed, nobody <em>asked</em> me to work on web performance, just as nobody <em>asked</em> me to develop PWAs, in the same way that nobody <em>asked</em> me to work on the capability gap between web and native. Each one falls out of the sort of strategy analysis I'm sharing in this post for the first time. These projects are examples of the sort of work I think anyone would do once they understood the stakes and marinated in the same data.</p>
<p>Luckily, inside of browser teams, I've found that largely to be true. Platform work attracts long-term thinkers, and those folks are willing to give strategy analysis a listen. This, in turn, has allowed the formation of large collaborations (like <a href="https://www.chromium.org/teams/web-capabilities-fugu/">Project Fugu</a> and <a href="https://conffab.com/in_person_session/summit-23-front-end-engineering-afternoon-day-2/">Project Sidecar</a> to tackle the burning issues that pro-web strategy analysis yields.</p>
<p>Strategy without action isn't worth a damn, and action without strategy can easily misdirect scarce resources. It's a strange and surprising thing to have found a series of teams (and bosses) willing to support an oddball like me that works both sides of the problem space without direction.</p>
<p>So what is it that I do for a living? Whatever working to make the web a success for another generation demands. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-ecosystem-strategy-is-a-weird-job-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-failure-on-repeat-2" class="footnote-item"><p>Just how bad is it?</p>
<p>This table shows the mobile Core Web Vitals scores for every production site listed on the <a href="https://nextjs.org/showcase">Next.js showcase web page</a> as of Oct 2024. It includes every site that gets enough traffic to report mobile-specific data, and ignores sites which no longer use Next.js:<sup class="footnote-ref"><a href="https://infrequently.org/2024/10/platforms-are-competitions/#fn-the-softest-target-10" id="fnref-the-softest-target-10">10</a></sup></p>
<style>
  #next-showcase {
    text-align: center;
    line-height: 2;
    & .align-l { text-align: left; }
    td { 
      text-align: right;
      padding-right: 0.5rem;
    }
    & > caption {
      caption-side: top;
      padding-bottom: 0.5em;
    }
    & thead {
      & > th[aria-sort="descending"]::after {
        float: right;
        font-style: normal;
        content: " ↓";
      }
      & > th[aria-sort="ascending"]::after {
        float: right;
        font-style: normal;
        content: " ↑";
      }
      & > th:not(:first-of-type),
      & > th:not(:last-of-type) {
        padding: 0.3rem;
      }
    }
    & tbody tr:last-of-type {
      font-weight: bold;
    }
    & tbody {
      & > tr > td.ni { 
        color: white;
        background-color: #ae6032; 
      }
      & > tr > td.pass { 
        color: white;
        background-color: #018642; 
      }
      & > tr > td.fail { 
        color: white;
        background-color: #eb0c00; 
      }
      & > tr > td:not(:first-of-type) {
        padding-right: 0.5rem;
      }
      & > tr > td:last-of-type {
        color: white;
        & a { color: white; }
      }
    }
  }
  @media (prefers-color-scheme: dark) {
    #next-showcase { color: white; }
  }
</style>
<table class="summary" style="margin: auto; min-width: 100%;" id="next-showcase" skip-last="1">  
<caption><em>Mobile Core Web Vitals statistics for Next.js sites from <a href="https://nextjs.org/showcase" target="_new">Vercel's showcase</a>, as well as the fraction of mobile traffic to each site. The last column indicates CWV stats (<a href="https://web.dev/articles/lcp" target="_new">LCP</a>, <a href="https://web.dev/articles/inp" target="_new">INP</a>, and <a href="https://web.dev/articles/cls" target="_new">CLS</a>) that consistently passed over the past 90 days.<br />Tap column headers to sort.</em></caption>
  <thead>
    <tr>
      <th style="text-align: left;" sort="string">Site</th>
      <th aria-description="Percentage of traffic from mobile devices" sort="percent">mobile</th>
      <th aria-description="Largest Contentful Paint, in milliseconds" sort="int">LCP (ms)</th>
      <th aria-description="Interaction to Next Paint, in milliseconds" sort="int">INP (ms)</th>
      <th aria-description="Cumulative Layout Shift" sort="float">CLS</th>
      <th aria-description="CWV Metrics that have consistently passed over the past 90 days" sort="int">90d pass</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.sonos.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Sonos</a></td>
      <td>70%</td>
      <td class="ni">3874</td>
      <td class="ni">205</td>
      <td class="pass">0.09</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.sonos.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.nike.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Nike</a></td>
      <td>75%</td>
      <td class="ni">3122</td>
      <td class="ni">285</td>
      <td class="ni">0.12</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.nike.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fopenai.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">OpenAI</a></td>
      <td>62%</td>
      <td class="pass">2164</td>
      <td class="ni">387</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fopenai.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fclaude.ai%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Claude</a></td>
      <td>30%</td>
      <td class="fail">7237</td>
      <td class="fail">705</td>
      <td class="pass">0.08</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fclaude.ai%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fopen.spotify.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Spotify</a></td>
      <td>28%</td>
      <td class="ni">3086</td>
      <td class="ni">417</td>
      <td class="pass">0.02</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fopen.spotify.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.nerdwallet.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Nerdwallet</a></td>
      <td>55%</td>
      <td class="pass">2306</td>
      <td class="ni">244</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.nerdwallet.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fjobs.netflix.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Netflix Jobs</a></td>
      <td>42%</td>
      <td class="pass">2145</td>
      <td class="pass">147</td>
      <td class="pass">0.02</td>
      <td class="pass"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fjobs.netflix.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">3</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fzapier.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Zapier</a></td>
      <td>10%</td>
      <td class="pass">2408</td>
      <td class="ni">294</td>
      <td class="pass">0.01</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fzapier.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fsolana.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Solana</a></td>
      <td>48%</td>
      <td class="pass">1915</td>
      <td class="pass">188</td>
      <td class="pass">0.07</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fsolana.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fplex.tv%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Plex</a></td>
      <td>49%</td>
      <td class="pass">1501</td>
      <td class="pass">86</td>
      <td class="pass">0.00</td>
      <td class="pass"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fplex.tv%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">3</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.wegmans.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Wegmans</a></td>
      <td>58%</td>
      <td class="pass">2206</td>
      <td class="pass">122</td>
      <td class="pass">0.10</td>
      <td class="pass"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.wegmans.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">3</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.wayfair.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Wayfair</a></td>
      <td>57%</td>
      <td class="ni">2663</td>
      <td class="ni">272</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.wayfair.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.underarmour.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Under Armour</a></td>
      <td>78%</td>
      <td class="ni">3966</td>
      <td class="ni">226</td>
      <td class="ni">0.17</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.underarmour.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fenterthegungeon.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Devolver</a></td>
      <td>68%</td>
      <td class="pass">2053</td>
      <td class="ni">210</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fenterthegungeon.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.anthropic.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Anthropic</a></td>
      <td>30%</td>
      <td class="fail">4866</td>
      <td class="ni">275</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.anthropic.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Frunwayml.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Runway</a></td>
      <td>66%</td>
      <td class="pass">1907</td>
      <td class="pass">164</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Frunwayml.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.parachutehome.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Parachute</a></td>
      <td>55%</td>
      <td class="pass">2064</td>
      <td class="ni">211</td>
      <td class="pass">0.03</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.parachutehome.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.washingtonpost.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">The Washington Post</a></td>
      <td>50%</td>
      <td class="pass">1428</td>
      <td class="pass">155</td>
      <td class="pass">0.01</td>
      <td class="pass"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.washingtonpost.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">3</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.lg.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">LG</a></td>
      <td>85%</td>
      <td class="fail">4898</td>
      <td class="fail">681</td>
      <td class="fail">0.27</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.lg.com%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.perplexity.ai&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Perplexity</a></td>
      <td>44%</td>
      <td class="ni">3017</td>
      <td class="fail">558</td>
      <td class="pass">0.09</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.perplexity.ai%2F&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.tiktok.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TikTok</a></td>
      <td>64%</td>
      <td class="ni">2873</td>
      <td class="ni">434</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.tiktok.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fapp.leonardo.ai&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Leonardo.ai</a></td>
      <td>60%</td>
      <td class="ni">3548</td>
      <td class="fail">736</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fapp.leonardo.ai&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hulu.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Hulu</a></td>
      <td>26%</td>
      <td class="pass">2490</td>
      <td class="ni">211</td>
      <td class="pass">0.01</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hulu.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.notion.so&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Notion</a></td>
      <td>4%</td>
      <td class="fail">6170</td>
      <td class="ni">484</td>
      <td class="ni">0.12</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.notion.so&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.target.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Target</a></td>
      <td>56%</td>
      <td class="ni">2575</td>
      <td class="ni">233</td>
      <td class="pass">0.07</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.target.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hbomax.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">HBO Max</a></td>
      <td>50%</td>
      <td class="fail">5735</td>
      <td class="ni">263</td>
      <td class="pass">0.05</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hbomax.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.realtor.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">realtor.com</a></td>
      <td>66%</td>
      <td class="pass">2004</td>
      <td class="ni">296</td>
      <td class="pass">0.05</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.realtor.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.att.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">AT&amp;T</a></td>
      <td>49%</td>
      <td class="fail">4235</td>
      <td class="ni">258</td>
      <td class="ni">0.18</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.att.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fxw.qq.com&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Tencent News</a></td>
      <td>98%</td>
      <td class="pass">1380</td>
      <td class="pass">78</td>
      <td class="ni">0.12</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fxw.qq.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ign.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">IGN</a></td>
      <td>76%</td>
      <td class="pass">1986</td>
      <td class="ni">355</td>
      <td class="ni">0.18</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ign.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fcompete.playstation.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Playstation Comp Ctr.</a></td>
      <td>85%</td>
      <td class="fail">5348</td>
      <td class="pass">192</td>
      <td class="pass">0.10</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ign.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ticketmaster.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Ticketmaster</a></td>
      <td>55%</td>
      <td class="ni">3878</td>
      <td class="ni">429</td>
      <td class="pass">0.01</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ticketmaster.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.doordash.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Doordash</a></td>
      <td>38%</td>
      <td class="ni">3559</td>
      <td class="ni">477</td>
      <td class="ni">0.14</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.doordash.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.audible.com%2Fabout&identifier=url&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">
      Audible (Marketing)
      </a></td>
      <td>21%</td>
      <td class="ni">2529</td>
      <td class="pass">137</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.audible.com%2Fabout&identifier=url&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.typeform.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Typeform</a></td>
      <td>49%</td>
      <td class="pass">1719</td>
      <td class="ni">366</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.typeform.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fpackages.united.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">United</a></td>
      <td>46%</td>
      <td class="fail">4566</td>
      <td class="ni">488</td>
      <td class="ni">0.22</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fpackages.united.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hilton.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Hilton</a></td>
      <td>53%</td>
      <td class="fail">4291</td>
      <td class="ni">401</td>
      <td class="fail">0.33</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hilton.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fngc.nvidia.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Nvidia NGC</a></td>
      <td>3%</td>
      <td class="fail">8398</td>
      <td class="fail">635</td>
      <td class="pass">0.00</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fngc.nvidia.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ted.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TED</a></td>
      <td>28%</td>
      <td class="fail">4101</td>
      <td class="fail">628</td>
      <td class="pass">0.07</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ted.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fauth0.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Auth0</a></td>
      <td>41%</td>
      <td class="pass">2215</td>
      <td class="ni">292</td>
      <td class="pass">0.00</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.auth0.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">2</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hostgator.com%2Fhelp&identifier=url&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Hostgator</a></td>
      <td>34%</td>
      <td class="pass">2375</td>
      <td class="ni">208</td>
      <td class="pass">0.01</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.hostgator.com%2Fhelp&identifier=url&device=PHONE&periodStart=16&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fhaveyoursay.tfl.gov.uk%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TFL "Have your say"</a></td>
      <td>65%</td>
      <td class="ni">2867</td>
      <td class="pass">145</td>
      <td class="ni">0.22</td>
      <td class="ni"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fhaveyoursay.tfl.gov.uk&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">1</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.vodafone.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Vodafone</a></td>
      <td>80%</td>
      <td class="fail">5306</td>
      <td class="ni">484</td>
      <td class="fail">0.53</td>
      <td class="fail"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.vodafone.com&identifier=origin&device=PHONE&periodStart=14&periodEnd=-1&display=p75s" target="new">0</a></td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.producthunt.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Product Hunt</a></td>
      <td>48%</td>
      <td class="ni">2783</td>
      <td class="ni">305</td>
      <td class="ni">0.11</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.invisionapp.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Invision</a></td>
      <td>23%</td>
      <td class="ni">2555</td>
      <td class="pass">187</td>
      <td class="pass">0.02</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Flocation.westernunion.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Western Union</a></td>
      <td>90%</td>
      <td class="fail">10060</td>
      <td class="ni">432</td>
      <td class="ni">0.11</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.today.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Today</a></td>
      <td>77%</td>
      <td class="pass">2365</td>
      <td class="ni">211</td>
      <td class="pass">0.04</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fkids.lego.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Lego Kids</a></td>
      <td>64%</td>
      <td class="ni">3567</td>
      <td class="ni">324</td>
      <td class="pass">0.02</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.staples.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Staples</a></td>
      <td>35%</td>
      <td class="ni">3387</td>
      <td class="ni">263</td>
      <td class="fail">0.29</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Ffilm.britishcouncil.org%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">British Council</a></td>
      <td>37%</td>
      <td class="ni">3415</td>
      <td class="pass">199</td>
      <td class="ni">0.11</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fvercel.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Vercel</a></td>
      <td>11%</td>
      <td class="pass">2307</td>
      <td class="ni">247</td>
      <td class="pass">0.01</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.truecar.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TrueCar</a></td>
      <td>69%</td>
      <td class="pass">2483</td>
      <td class="ni">396</td>
      <td class="pass">0.06</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fartlab.hyundai.com%2F&identifier=url&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Hyundai Artlab</a></td>
      <td>63%</td>
      <td class="fail">4151</td>
      <td class="pass">162</td>
      <td class="ni">0.22</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Ffinder.porsche.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Porsche</a></td>
      <td>59%</td>
      <td class="ni">3543</td>
      <td class="ni">329</td>
      <td class="ni">0.22</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.elastic.co%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">elastic</a></td>
      <td>11%</td>
      <td class="ni">2834</td>
      <td class="ni">206</td>
      <td class="pass">0.10</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.leafly.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Leafly</a></td>
      <td>88%</td>
      <td class="pass">1958</td>
      <td class="pass">196</td>
      <td class="pass">0.03</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fgopro.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">GoPro</a></td>
      <td>54%</td>
      <td class="ni">3143</td>
      <td class="pass">162</td>
      <td class="ni">0.17</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fworldpopulationreview.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">World Population Review</a></td>
      <td>65%</td>
      <td class="pass">1492</td>
      <td class="ni">243</td>
      <td class="pass">0.10</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Freplit.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">replit</a></td>
      <td>26%</td>
      <td class="fail">4803</td>
      <td class="fail">532</td>
      <td class="pass">0.02</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fjobs.redbull.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Redbull Jobs</a></td>
      <td>53%</td>
      <td class="pass">1914</td>
      <td class="ni">201</td>
      <td class="pass">0.05</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.marvel.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Marvel</a></td>
      <td>68%</td>
      <td class="pass">2272</td>
      <td class="pass">172</td>
      <td class="pass">0.02</td>
      <td class="pass">3</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fnubank.com.br%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Nubank</a></td>
      <td>78%</td>
      <td class="pass">2386</td>
      <td class="fail">690</td>
      <td class="pass">0.00</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fweedmaps.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Weedmaps</a></td>
      <td>66%</td>
      <td class="ni">2960</td>
      <td class="ni">343</td>
      <td class="ni">0.15</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Finternet.frontier.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Frontier</a></td>
      <td>82%</td>
      <td class="ni">2706</td>
      <td class="pass">160</td>
      <td class="ni">0.22</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fdeliveroo.co.uk%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Deliveroo</a></td>
      <td>60%</td>
      <td class="pass">2427</td>
      <td class="ni">381</td>
      <td class="pass">0.10</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fmui.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">MUI</a></td>
      <td>4%</td>
      <td class="pass">1510</td>
      <td class="ni">358</td>
      <td class="pass">0.00</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Ffriday.kodansha.co.jp%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">FRIDAY DIGITAL</a></td>
      <td>90%</td>
      <td class="pass">1674</td>
      <td class="ni">217</td>
      <td class="fail">0.30</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.realself.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">RealSelf</a></td>
      <td>75%</td>
      <td class="pass">1990</td>
      <td class="ni">271</td>
      <td class="pass">0.04</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fexpo.dev%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Expo</a></td>
      <td>32%</td>
      <td class="ni">3778</td>
      <td class="ni">269</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fplot.ly%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Plotly</a></td>
      <td>8%</td>
      <td class="ni">2504</td>
      <td class="ni">245</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.sumup.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Sumup</a></td>
      <td>70%</td>
      <td class="ni">2668</td>
      <td class="fail">888</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.eurostar.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Eurostar</a></td>
      <td>56%</td>
      <td class="ni">2606</td>
      <td class="fail">885</td>
      <td class="fail">0.44</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.eaze.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Eaze</a></td>
      <td>78%</td>
      <td class="ni">3247</td>
      <td class="ni">331</td>
      <td class="pass">0.09</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ferrari.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Ferrari</a></td>
      <td>65%</td>
      <td class="fail">5055</td>
      <td class="ni">310</td>
      <td class="pass">0.03</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.ftd.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">FTD</a></td>
      <td>61%</td>
      <td class="pass">1873</td>
      <td class="ni">295</td>
      <td class="pass">0.08</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fgartic.io%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Gartic.io</a></td>
      <td>77%</td>
      <td class="ni">2538</td>
      <td class="ni">394</td>
      <td class="pass">0.02</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fframer.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Framer</a></td>
      <td>16%</td>
      <td class="fail">8388</td>
      <td class="ni">222</td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fopencollective.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Open Collective</a></td>
      <td>49%</td>
      <td class="ni">3944</td>
      <td class="ni">331</td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://infrequently.org/2024/10/platforms-are-competitions/" target="_new">Õhtuleht</a></td>
      <td>80%</td>
      <td class="pass">1687</td>
      <td class="pass">136</td>
      <td class="ni">0.20</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.movietickets.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">MovieTickets</a></td>
      <td>76%</td>
      <td class="ni">3777</td>
      <td class="pass">169</td>
      <td class="pass">0.08</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.bang-olufsen.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">BANG &amp; OLUFSEN</a></td>
      <td>56%</td>
      <td class="ni">3641</td>
      <td class="ni">335</td>
      <td class="pass">0.08</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.tvpublica.com.ar%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TV Publica</a></td>
      <td>83%</td>
      <td class="ni">3706</td>
      <td class="ni">296</td>
      <td class="ni">0.23</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fstyled-components.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">styled-components</a></td>
      <td>4%</td>
      <td class="pass">1875</td>
      <td class="ni">378</td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.mprnews.org%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">MPR News</a></td>
      <td>78%</td>
      <td class="pass">1836</td>
      <td class="pass">126</td>
      <td class="fail">0.51</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.mesalva.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Me Salva!</a></td>
      <td>41%</td>
      <td class="ni">2831</td>
      <td class="ni">272</td>
      <td class="ni">0.20</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://infrequently.org/2024/10/platforms-are-competitions/" target="_new">Suburbia</a></td>
      <td>91%</td>
      <td class="fail">5365</td>
      <td class="ni">419</td>
      <td class="fail">0.31</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.lightningdesignsystem.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Salesforce LDS</a></td>
      <td>3%</td>
      <td class="ni">2641</td>
      <td class="ni">230</td>
      <td class="pass">0.04</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.virgin.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Virgin</a></td>
      <td>65%</td>
      <td class="ni">3396</td>
      <td class="ni">244</td>
      <td class="ni">0.12</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.giveindia.org%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">GiveIndia
      </a></td>
      <td>71%</td>
      <td class="pass">1995</td>
      <td class="pass">107</td>
      <td class="pass">0.00</td>
      <td class="pass">3</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fdice.fm%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">DICE</a></td>
      <td>72%</td>
      <td class="pass">2262</td>
      <td class="ni">273</td>
      <td class="pass">0.00</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fscale.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Scale</a></td>
      <td>33%</td>
      <td class="pass">2258</td>
      <td class="ni">294</td>
      <td class="pass">0.00</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fthehhub.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">TheHHub</a></td>
      <td>57%</td>
      <td class="ni">3396</td>
      <td class="ni">264</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.aenetworks.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">A+E</a></td>
      <td>61%</td>
      <td class="pass">2336</td>
      <td class="pass">106</td>
      <td class="pass">0.00</td>
      <td class="pass">3</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fhyper.is%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Hyper</a></td>
      <td>33%</td>
      <td class="ni">2818</td>
      <td class="pass">131</td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fcarbon.now.sh%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Carbon</a></td>
      <td>12%</td>
      <td class="ni">2565</td>
      <td class="fail">560</td>
      <td class="pass">0.02</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.sanity.io%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Sanity</a></td>
      <td>10%</td>
      <td class="ni">2861</td>
      <td class="ni">222</td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://infrequently.org/2024/10/platforms-are-competitions/" target="_new">Elton John</a></td>
      <td>70%</td>
      <td class="ni">2518</td>
      <td class="pass">126</td>
      <td class="pass">0.00</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Finstitchu.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">InStitchu</a></td>
      <td>27%</td>
      <td class="ni">3186</td>
      <td class="pass">122</td>
      <td class="pass">0.09</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.starbucksreserve.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Starbucks Reserve</a></td>
      <td>76%</td>
      <td class="pass">1347</td>
      <td class="pass">87</td>
      <td class="pass">0.00</td>
      <td class="pass">3</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fvergecurrency.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Verge Currency</a></td>
      <td>67%</td>
      <td class="ni">2549</td>
      <td class="ni">223</td>
      <td class="pass">0.04</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Ffontba.se%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">FontBase</a></td>
      <td>11%</td>
      <td class="ni">3120</td>
      <td class="pass">170</td>
      <td class="pass">0.02</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fcolorbox.io%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Colorbox</a></td>
      <td>36%</td>
      <td class="pass">1421</td>
      <td class="pass">49</td>
      <td class="pass">0.00</td>
      <td class="pass">3</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fnilefm.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">NileFM</a></td>
      <td>63%</td>
      <td class="ni">2869</td>
      <td class="pass">186</td>
      <td class="fail">0.36</td>
      <td class="fail">0</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fsyntax.fm%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Syntax</a></td>
      <td>40%</td>
      <td class="ni">2531</td>
      <td class="pass">129</td>
      <td class="pass">0.06</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.frog.co%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Frog</a></td>
      <td>24%</td>
      <td class="fail">4551</td>
      <td class="pass">138</td>
      <td class="pass">0.05</td>
      <td class="ni">2</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Finflect.com%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Inflect</a></td>
      <td>55%</td>
      <td class="ni">3435</td>
      <td class="ni">289</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td class="align-l"><a href="https://cruxvis.withgoogle.com/#/?view=cwvsummary&url=https%3A%2F%2Fwww.swoosh.nike%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s" target="_new">Swoosh by Nike</a></td>
      <td>78%</td>
      <td class="pass">2081</td>
      <td class="pass">99</td>
      <td class="pass">0.01</td>
      <td class="ni">1</td>
    </tr>
    <tr>
      <td><em>Passing %</em></td>
      <td></td>
      <td class="fail">38%</td>
      <td class="fail">28%</td>
      <td class="ni">72%</td>
      <td class="fail">8%</td>
    </tr>
    <!-- 
    <tr>
      <td class="align-l"><a href="
      " target="_new">
      </a></td>
      <td>%</td>
      <td class="ni"></td>
      <td class="ni"></td>
      <td class="pass">0.00</td>
      <td class="ni">1</td>
    </tr>
    -->
  </tbody>
</table>
<script type="module">
  // Make the table sortable
  let tbl = document.getElementById("next-showcase");
  let thead = tbl.querySelector("thead");
  let headers = Array.from(thead.querySelectorAll("th"));
  headers.forEach((h) => { 
    h.role = "button";
    h.tabIndex = 0; 
  });
  let tbody = tbl.querySelector("tbody");
  let skipLast = parseInt(tbl.getAttribute("skip-last") || 0);
  let rows = Array.from(tbody.querySelectorAll("tr"));
  let dirAttr = "aria-sort";
  if(skipLast) {
    rows = rows.slice(0, -(skipLast));
  }
  let prevSortedHeader = null;
  let sortFromEvent = (e) => {
    e.stopPropagation();
    e.preventDefault();
    let column = headers.indexOf(e.target);
    let header = headers[column];
    header.focus();
    let sort = header.getAttribute("sort") || "string";
    let sortRows = Array.from(rows);
    let toData;
    if(prevSortedHeader != header) {
      prevSortedHeader?.removeAttribute(dirAttr);
      prevSortedHeader = header;
    }
    let dir = (header.getAttribute(dirAttr) == "ascending") ? 
                  "descending" : "ascending";
    header.setAttribute(dirAttr, dir);
    switch(sort) {
      case "int":
      case "percent":
      case "float":
        toData = (el) => {
          if("data" in el) { return el.data; }
          el.data = 
            ((sort == "float") ? parseFloat : parseInt)(el.textContent);
          return el.data;
        };
        break;
      case "string":
      default:
        toData = (el) => { return el.textContent; };
        break;
    }
    sortRows.sort(function(a, b) {
      let aData = toData(a.children[column]);
      let bData = toData(b.children[column]);
      let r = 0;
      if (sort == "string") {
        r = ((aData > bData) ? -1 : ((bData > aData) ? 1 : 0));
      } else {
        r = bData - aData;
      }
      return (dir == "descending") ? r : -r;
    });
    tbody.append(...sortRows);
    for(let x=0; x < skipLast; x++) {
      tbody.append(tbody.firstElementChild);
    }
  };
  thead.onclick = sortFromEvent;
  thead.onkeydown = (e) => {
    if(["Space", " ", "Enter"].includes(e.key)) {
      sortFromEvent(e);
    }
  }
</script>
<p>Needless to say, these results are significantly worse than those of responsible JS-centric metaframeworks like <a href="https://astro.build/">Astro</a> or HTML-first systems like <a href="https://www.11ty.dev/">Eleventy</a>. Spot-checking their results gives me hope.</p>
<p>Failure doesn't have to be our destiny, we only need to change the way we build and support <a href="https://open-web-advocacy.org/">efforts that can close the capability gap.</a> <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-failure-on-repeat-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-thirst-traps-3" class="footnote-item"><p>This phrasing — fraction of time spent, rather than absolute time — has the benefit of not being thirsty. It's also tracked by various parties.</p>
<p>The fraction of <a href="https://hbr.org/2016/09/know-your-customers-jobs-to-be-done">&quot;Jobs To Be Done&quot;</a> happening on the web would be the natural leading metric, but it's challenging to track. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-thirst-traps-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-our-awol-tech-press-4" class="footnote-item"><p>Web developers aren't the only ones shooting their future prospects in the foot.</p>
<p>It's bewildering to see today's tech press capitulate to the gatekeepers. <a href="https://www.theregister.com/">The Register</a> and <a href="https://thenewstack.io/">The New Stack</a> stand apart in using above-the-fold column inches to <a href="https://www.theregister.com/2022/02/28/apple_apps_challenge/">cover</a> just how <a href="https://www.theregister.com/2024/06/21/eu_apple_owa/">rancid</a> and self-dealing <a href="https://www.theregister.com/2024/03/27/inapp_browsers/">Apple, Google, and Facebook's suppression</a> of the mobile web has been.</p>
<p>Most can't even summon <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">their opinion bytes to highlight how broken the situation has become</a>, or how the alternative would benefit everyone, even though it would <em>directly</em> benefit those outlets.</p>
<p>If the web has a posse, it doesn't include The Verge or TechCrunch. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-our-awol-tech-press-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-no-kos-5" class="footnote-item"><p>There are rarely KOs in platform competitions, only slow, grinding changes that look &quot;boring&quot; to a tech press that would rather report on social media contratemps.</p>
<p>Even the smartphone revolution, which featured never before seen device sales rates, took most of a decade to overtake desktop as the dominant computing form-factor. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-no-kos-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-status-tracking-6" class="footnote-item"><p>The web wasn't always competitive with native on desktop, either. It took Ajax (new capabilities), Moore's Law (RIP), and broadband to make it so. There had to be enough overhang in CPUs and network availability to make the performance hit of the web's languages and architecture largely immaterial.</p>
<p>This is why I continue to track the <a href="https://infrequently.org/series/performance-inequality/">mobile device and network situation.</a> For the mobile web to take off, it'll need to overcome similar hurdles to usability on most devices.</p>
<p>The only way that's likely to happen in the short-to-medium term is for developers to emit less JS per page. And <a href="https://httparchive.org/reports/state-of-javascript">that is not what's happening.</a> <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-status-tracking-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ui-coherence-7" class="footnote-item"><p>One common objection to metaplatforms like the web is that the look and feel versus &quot;native&quot; UI is not consistent. The theory goes that consistent affordances create less friction for users as they navigate their digital world. This is a nice theory, but in practice the more important question in the fight between web and native look-and-feel is which one users encounter more often.</p>
<p>The dominant experience is what others are judged against. On today's desktops, browsers that set the pace, leaving OSes with reduced influence. OS purists decry this as an abomination, but it just is what it is. &quot;Fixing&quot; it gains users very little.</p>
<p>This is particularly true in a world where OSes change up large aspects of their design languages every half decade. Even without the web's influence, this leaves a trail of unreconciled experiences sitting side-by-side uncomfortably. Web apps aren't an unholy disaster, just more of the same. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-ui-coherence-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-fair-weather-friends-8" class="footnote-item"><p>No matter how much they protest that they love it (sus) and couldn't have succeeded without it (true), the web is, at best, an also-ran in the internal logic of today's tech megacorps. They can do platform strategy, too, and know that that exerting direct control over access to APIs is worth its weight in Californium. As a result, the preferred alternative is always the proprietary (read: directly controlled and therefore taxable) platform of their OS frameworks. API access gatekeeping enables distribution gatekeeping, which becomes a business model chokepoint over time.</p>
<p>Even Google, the sponsor of the projects I pursued to close platform gaps, couldn't summon the organisational fortitude to inconvenience the Play team for the web's benefit. For its part, Apple froze Safari funding and API expansion almost as soon as the App Store took off. Both benefit from a cozy duopoly that forces businesses into the logic of heavily mediated app platforms.</p>
<p>The web isn't suffering on mobile because it isn't good enough in some theoretical sense, it's failing on mobile because the duopolists directly benefit from keeping it in a weakened state. And because the web is a collectively-owned, reach-based platform, neither party has to have their fingerprints on the murder weapon. At current course and speed, the web will die from a lack of competitive vigour, and nobody will be able to point to the single moment when it happened.</p>
<p>That's by design. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-fair-weather-friends-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-sinking-costs-9" class="footnote-item"><p>Real teams, doing actual work, aren't nearly as wedded to React vs., e.g., Preact or Lit or FAST or Stencil or Qwik or Svelte as the JS-industrial-complex wants us all to believe. And moving back to the server entirely is even easier.</p>
<p>React is the last of the totalising frameworks. Everyone else is living in the interoperable, plug-and-play future (via Web Components). Escape doesn't hurt, but it can be scary. But teams that want to do better aren't wanting for off-ramps. <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-sinking-costs-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-softest-target-10" class="footnote-item"><p>It's hard to overstate just how fair this is to the over-Reactors. The (still) more common <a href="https://create-react-app.dev/">Create React App</a> <s>metaframework</s> starter kit would suffer terribly by comparison, and Vercel has had years of browser, network, and CPU progress to water down the negative consequences of Next.js's blighted architecture.</p>
<p>Next has also been pitched since 2018 as <a href="https://web.archive.org/web/20191227200506/https://nextjs.org/"><em>&quot;The React Framework for the Mobile Web&quot;</em> and <em>&quot;The React Framework for SEO-Friendly Sites&quot;</em></a>. Nobody else's petard is doing the hoisting; these are the sites that <em>Vercel</em> is chosing to highlight, built using <em>their</em> technology, which has <a href="https://web.archive.org/web/20201021152422/https://nextjs.org/">consistently advertised performance-oriented features like code-splitting and SSG support.</a> <a href="https://infrequently.org/2024/10/platforms-are-competitions/#fnref-the-softest-target-10" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Reckoning: Part 4 — The Way Out</title>
    <link href="https://infrequently.org/2024/08/the-way-out/"/>
    <updated>2024-08-16T00:00:00Z</updated>
    <id>https://infrequently.org/2024/08/the-way-out/</id>
    <content type="html"><![CDATA[
      <div style="font-size: 1rem;">
<p><em>Other posts in the series:</em></p>
<ul>
<li><em><a href="https://infrequently.org/2024/08/the-landscape/">Reckoning: Part 1 — The Landscape</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/object-lesson/">Reckoning: Part 2 — Object Lesson</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/caprock/">Reckoning: Part 3 — Caprock</a></em></li>
</ul>
</div>
<p>Frontend took ill with a <a href="https://infrequently.org/2017/10/can-you-afford-it-real-world-web-performance-budgets/">bad case</a> of JavaScript fever <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-great-branch-mispredict">at the worst possible moment.</a> The predictable consequence is a web that feels terrible most of the time, resulting in low and falling use of the web on smartphones.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-way-out/#fn-obselesence-1" id="fnref-obselesence-1">1</a></sup></p>
<p></p><figure><a href="https://www.emarketer.com/content/the-majority-of-americans-mobile-time-spent-takes-place-in-apps" alt="Public data <a href='https://vimeo.com/364402896'>shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web." target="_blank"><picture style="--lqip: 524212" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/mobile-app-vs-browser-time-spent-us-emarketer.webp" alt="Public data <a href='https://vimeo.com/364402896'>shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web." style="aspect-ratio: 1280 / 1325" class="preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>Public data <a href="https://vimeo.com/364402896">shows what I warned about, citing Google-private data, in 2019.</a> In the US, time spent in browsers continues to stagnate while smartphone use grows, and the situation is even more dire outside the states. The result is a falling fraction of time spent. This is not a recipe for a healthy web.</figcaption>      </figure><p></p>
<p>If nothing changes, eventually, the web will become a footnote in the history of computing; a curio along side mainframes and minicomputers — <a href="https://www.networkworld.com/article/971580/ibm-sales-jump-shows-the-mainframe-is-not-dead-with-hybrid-cloud-alive-and-well.html">never truly gone</a> but lingering with an ashen palour and a necrotic odour.</p>
<p>We don't have to wait to see how this drama plays out to understand the <a href="https://infrequently.org/2024/08/object-lesson/">very real consequences of JavaScript excess</a> on users.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-way-out/#fn-close-to-home-2" id="fnref-close-to-home-2">2</a></sup></p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/08/the-way-out/#managers">Managers</a></li><li><a href="https://infrequently.org/2024/08/the-way-out/#engineers-and-designers">Engineers and Designers</a></li><li><a href="https://infrequently.org/2024/08/the-way-out/#public-sector-agencies">Public Sector Agencies</a></li><li><a href="https://infrequently.org/2024/08/the-way-out/#values-matter">Values Matter</a></li></ul></nav>
<p>Everyone in a site's production chain has agency to prevent <a href="https://infrequently.org/2024/08/object-lesson/">disaster.</a> Procurement leads, in-house IT staff, and the managers, PMs, and engineers working for contractors and subcontractors building the SNAP sites we examined all had voices that were more powerful than the users they under-served. Any of them could have acted to steer the ship away from the rocks.</p>
<p>Unacceptable performance is the consequence of a chain of failures to put the user first. Breaking the chain usually requires just one insistent advocate. Disasters like BenefitsCal are not inevitable.</p>
<br style="display: none;" />
<wpt-filmstrip style="display: block; width: 100%; margin: auto; contain: inline-size layout paint;" size="medium" interval="500ms">
  <wpt-test label="BenefitsCal, first load" timeline="/2024/08/the-landscape/wpt-traces/240729_AiDcPE_4F2/runs/1/firstView/timeline.json">
  </wpt-test>
  <wpt-test label="u​n​i​v​e​r​s​a​l​-​c​r​e​d​i​t​.​s​e​r​v​i​c​e​.​g​o​v​.​u​k​, first load" timeline="/2024/08/the-landscape/wpt-traces/240805_AiDcXC_CMR/runs/1/firstView/timeline.json">
  </wpt-test>
</wpt-filmstrip>
<p>The same failures play out in the commercial teams I sit with day-to-day. Failure is not a foregone conclusion, yet there's an endless queue of sites stuck in the same ditch, looking for help to pull themselves out. JavaScript overindulgence is always an affirmative decision, no matter how hard industry &quot;thought leaders&quot; gaslight us.</p>
<p>Marketing that casts highly volatile, serially failed frontend frameworks as &quot;standard&quot; or required is horse hockey. Nobody can force an entire industry to flop so often it limits its future prospects.</p>
<p><em>These are choices.</em></p>
<p>Teams that succeed resolve to stand for the users first, then explore techniques that build confidence.</p>
<p>So, assuming we want to put users first, what approaches can even the odds? There's no silver bullet,<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-way-out/#fn-secret-sauce-3" id="fnref-secret-sauce-3">3</a></sup> but some techniques are unreasonably effective.</p>
<h2 id="managers" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/the-way-out/#managers">Managers</a></h2>
<p>Engineering managers, product managers, and tech leads can make small changes to turn the the larger ship dramatically.</p>
<p>First, <strong>institute critical-user-journey analysis.</strong></p>
<p>Force peers and customers to agree about what actions users will take, <em>in order</em>, on the site most often. Document those flows end-to-end, then automate testing for them end-to-end in something like <a href="https://docs.webpagetest.org/scripting/">WebPageTest.org's scripting system.</a> Then define key metrics around these journeys. Build dashboards to track performance <em>end-to-end</em>.</p>
<p>Next, <strong>reform your frontend hiring processes.</strong></p>
<p>Never, ever hire for JavaScript framework skills. Instead, interview and hire only for fundamentals like web standards, accessibility, modern CSS, semantic HTML, and Web Components. This is <em>doubly</em> important if your system uses a framework.</p>
<p>The push-back to this sort of change comes from many quarters, but I can assure you from deep experience that the folks you <em>want</em> to hire can learn anything, so the framework on top of the platform is the least valuable part of any skills conversation. There's also a glut of folks with those talents on the market, and they're vastly underpriced vs. their effectiveness, so &quot;ability to hire&quot; isn't a legitimate concern. Teams that can't find those candidates aren't trying.</p>
<p>Some teams are in such a sorry state regarding fundamentals that they can't even vet candidates on those grounds. If that's your group, don't hestitate to <a href="https://infrequently.org/about-me/">reach out.</a></p>
<p>In addition to attracting the most capable folks at bargain-basement prices, delivering better work more reliably, and spending less on <a href="https://polotek.net/posts/the-frontend-treadmill/">JavaScript treadmill taxes</a>, publicising these criteria sends signals that will attract more of the right talent over time. Being the place that <em>&quot;does it right&quot;</em> generates compound value. The best developers want to work in teams that prize their deeper knowledge. Demonstrate that respect in your hiring process.</p>
<p>Next, <strong>issue every product and engineering leader cheap phones and laptops.</strong></p>
<p>Senior leaders should set the expectation those devices will be used regularly and for real work, including visibly during team meetings. If we do not live as our customers, blind spots metastasise.</p>
<p>Lastly, climb the <a href="https://infrequently.org/2022/05/performance-management-maturity/">Performance Management Maturity ladder</a>, starting with <strong>latency budgets for every project</strong>, based on the previously agreed critical user journeys. They are foundational in building a culture that does not backslide.</p>
<h2 id="engineers-and-designers" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/the-way-out/#engineers-and-designers">Engineers and Designers</a></h2>
<p>Success or failure is in your hands, literally. Others in the equation may have authority, but you have <em>power</em>.</p>
<p>Begin to use that power to make noise. <strong>Refuse to go along with plans to build YAJSD (Yet Another JavaScript Disaster).</strong> Engineering leaders look to their senior engineers for trusted guidance about what technologies to adopt. When someone inevitably proposes the React rewrite, do not be silent. Do not let the bullshit arguments and nonsense justifications pass unchallenged. Make it clear to engineering leadership that this stuff is <em>expensive</em> and is <a href="https://toot.cafe/@slightlyoff/112933241646309021"><em>absolutely not</em> &quot;standard&quot;.</a></p>
<p><strong>Demand bakeoffs and testing on low-end devices.</strong></p>
<p>The best thing about cheap devices is they're cheap! So inexpensive that you can likely afford a low-end phone out-of-pocket, even if the org doesn't issue one. Alternatively, <a href="https://webpagetest.org/">WebPageTest.org</a> can generate high-quality, low-noise simulations and side-by-side comparisons of the low-end situation.</p>
<p>Write these comparisons into testing plans early.</p>
<p>Advocate for <strong>metrics and measurements that represent users at the margins.</strong></p>
<p>Teams that have climbed the <a href="https://infrequently.org/2022/05/performance-management-maturity/">Performance Management Maturity ladder</a> intuitively look at the highest percentiles to understand system performance. Get comfortable doing the same, and build that muscle in your engineering practice.</p>
<p>Build the infrastructure you'll need to <strong>show, rather than tell.</strong> This can be dashboards or app-specific instrumentation. Whatever it is, just build it. Nobody in a high-performing engineering organisation will be ungrateful for additional visibility.</p>
<p>Lastly, <strong><a href="https://www.oreilly.com/library/view/using-webpagetest/9781491902783/ch04.html">take side-by-side traces</a></strong> and wave them like a red shirt.</p>
<p>Remember, none of the other people in this equation are working to undercut users, but they rely on you to guide their decisions. Be a class traitor; do the right thing and speak up for users on the margins who can't be in the room where decisions are made.</p>
<h2 id="public-sector-agencies" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/the-way-out/#public-sector-agencies">Public Sector Agencies</a></h2>
<p>If your organisation is unfamiliar with the UK Government Digital Service's excellent <a href="https://www.gov.uk/service-manual/">Service Manual</a>, get reading.</p>
<p>Once everyone has put their copy down, <strong><a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">institute the UK's progressive enhancement standard</a> and make it an enforceable requirement</strong> in procurement.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-way-out/#fn-pe-exceptions-4" id="fnref-pe-exceptions-4">4</a></sup> The cheapest architecture errors to fix are the ones that weren't committed.</p>
<p>Next, <strong>build out critical-user-journey maps</strong> to help bidders and in-house developers understand system health. Insist on dashboards to monitor those flows.</p>
<p>Use <strong>tender processes to send clear signals</strong> that proposals which include SPA architectures or heavy JS frameworks (React, Angular, etc.) will face acceptance challenges.</p>
<p>Next, <strong>make space in your budget to hire senior technologists</strong> and give them oversight power with teeth.</p>
<p>The root cause of many failures is the continuation of too-big-to-fail contracting. The antidote is scrutiny from folks versed in systems, not only requirements. An effective way to build and maintain that skill is to stop writing omnibus contracts in the first place.</p>
<p>Instead, farm out smaller bits of work to smaller shops across shorter timelines. Do the integration work in-house. <a href="https://infrequently.org/2013/04/two-governments-both-alike-in-dignity/">That will necessitate maintaining enough tech talent to own and operate these systems, building confidence over time.</a></p>
<p>Reforming procurement is always challenging; old habits run deep. But it's possible to start with the very next RFP.</p>
<h2 id="values-matter" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/the-way-out/#values-matter">Values Matter</a></h2>
<p>Today's frontend community is in crisis.</p>
<p>If it doesn't look that way, it's only because the instinct to deny the truth is now fully ingrained. But the crisis is incontrovertable in the data. If the web had grown at the same pace as mobile computing, mobile web browsing would be more than a 1/3 larger than it is today. Many things are holding the web back — Apple springs to mind — but pervasive JavaScript-based performance disasters are doing their fair share.</p>
<p>All of the failures I documented in public sector sites are things I've seen dozens of times in industry. When an e-commerce company loses tens or hundreds of millions of dollars because the new CTO fired the old guard out to make way for a bussload of Reactors, it's just (extremely stupid) business. But the consequences of frontend's accursed turn towards all-JavaScript-all-the-time are not so readily contained. Public sector services that should have known better are falling for the same malarkey.</p>
<p>Frontend's culture has more to answer for than lost profits; we consistently fail users and the companies that pay us to serve them because we've let <a href="https://infrequently.org/2023/02/the-market-for-lemons/">unscrupulous bastards sell snake oil</a> without consequence.</p>
<p>Consider the alternative.</p>
<p>Canadian engineers graduating college are all given an <a href="https://en.wikipedia.org/wiki/Iron_Ring">iron ring</a>. It's a symbol of professional responsibility to society. It also recognises that every discipline must earn its <a href="https://www.investopedia.com/terms/s/social-license-slo.asp">social license to operate.</a> Lastly, it serves as a reminder of the consequences of shoddy work and corner-cutting.</p>
<p></p><figure><picture style="--lqip: -42717" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-way-out/iron-ring.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-way-out/iron-ring.webp" alt="https://en.wikipedia.org/wiki/Iron_Ring" style="aspect-ratio: 587 / 528" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption><a href="https://www.flickr.com/photos/ryan_tir/3392602105" class="credit">photo by ryan_tir</a><br /></figcaption>      </figure><p></p>
<p>I want to be a part of a frontend culture that accepts and promotes our responsibilities to others, rather than wallowing in self-centred &quot;DX&quot; puffery. In the hierarchy of priorities, users must come first.</p>
<p>What we do in the world matters, particularly our vocations, not because of how it affects us, but because our actions improve or degrade life for others. It's hard to imagine that culture while the JavaScript-industrial-complex has seized the commanding heights, but we should try.</p>
<p>And then we should act, one project at a time, to make that culture a reality.</p>
<div style="font-size: 1rem;">
<p><em>Thanks to <a href="https://polotek.net/">Marco Rogers</a>, and <a href="https://fberriman.com/">Frances Berriman</a> for their encouragement in making this piece a series and for their thoughtful feedback on drafts.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-obselesence-1" class="footnote-item"><p>Users and businesses aren't choosing apps because they love downloading apps. They're choosing them because experiences built with these technologies work as advertised as least as often as they fail.</p>
<p>The same cannot be said for contemporary web development. <a href="https://infrequently.org/2024/08/the-way-out/#fnref-obselesence-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-close-to-home-2" class="footnote-item"><p>This series is a brief, narrow tour of the consequences of these excesses. Situating these case studies in the US, I hope, can dispel the notion that &quot;the problem&quot; is  &quot;over there&quot;.</p>
<p>It never was and still isn't. Friends, neighbours, and family all suffer when we do as terrible a job as has now become normalized in the JavaScript-first frontend conversation. <a href="https://infrequently.org/2024/08/the-way-out/#fnref-close-to-home-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-secret-sauce-3" class="footnote-item"><p>Silver bullets aren't possible at the technical level, but culturally, giving a toss is always the secret ingreedient. <a href="https://infrequently.org/2024/08/the-way-out/#fnref-secret-sauce-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-pe-exceptions-4" class="footnote-item"><p>Exceptions to a blanket policy requiring a Progressive Enhancement approach to frontend development should be carved out narrowly and only for sub-sections of progressively enhanced primary interfaces.</p>
<p>Specific examples of UIs that might need islands of non-progressively enhanced, JavaScript-based UI include:</p>
<ul>
<li>Visualisations, including GIS systems, complex charting, and dashboards.</li>
<li>Editors (rich text, diagramming tools, image editors, IDEs, etc.).</li>
<li>Real-time collaboration systems.</li>
<li>Hardware interfaces to legacy systems.</li>
<li>Videoconferencing.</li>
</ul>
<p>In cases where an exception is granted, a process must be defined to characterise and manage latency. <a href="https://infrequently.org/2024/08/the-way-out/#fnref-pe-exceptions-4" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Reckoning: Part 3 — Caprock</title>
    <link href="https://infrequently.org/2024/08/caprock/"/>
    <updated>2024-08-14T00:00:00Z</updated>
    <id>https://infrequently.org/2024/08/caprock/</id>
    <content type="html"><![CDATA[
      <div style="font-size: 1rem;">
<p><em>Other posts in the series:</em></p>
<ul>
<li><em><a href="https://infrequently.org/2024/08/the-landscape/">Reckoning: Part 1 — The Landscape</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/object-lesson/">Reckoning: Part 2 — Object Lesson</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/the-way-out/">Reckoning: Part 4 — The Way Out</a></em></li>
</ul>
</div>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/08/caprock/#complexity-perplexity">Complexity Perplexity</a></li><li><a href="https://infrequently.org/2024/08/caprock/#carrying-capacity">Carrying Capacity</a><ul><li><a href="https://infrequently.org/2024/08/caprock/#should-this-be-an-spa%3F">Should This Be An SPA?</a></li><li><a href="https://infrequently.org/2024/08/caprock/#the-pits">The Pits</a></li></ul></li><li><a href="https://infrequently.org/2024/08/caprock/#aftermath">Aftermath</a></li></ul></nav>
<p>Last time, <a href="https://infrequently.org/2024/08/object-lesson/">we looked at</a> how JavaScript-based web development compounded serving errors on US public sector service sites, slowing down access to critical services. These defects are not without injury. The pain of accessing SNAP assistance services in California, Massachusetts, Maryland, Tennessee, New Jersey, and Indiana likely isn't dominated by the shocking performance of their frontends, but their glacial delivery isn't helping.</p>
<p><a href="https://www.nytimes.com/2012/08/19/opinion/sunday/why-waiting-in-line-is-torture.html?unlocked_article_code=1.Bk4.c_y7.EhyNmle0_aTb&amp;smid=url-share">Waits are a price that developers ask users to pay</a> and loading spinners <a href="https://www.speedcurve.com/blog/psychology-site-speed/">only buy so much time.</a></p>
<h2 id="complexity-perplexity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/caprock/#complexity-perplexity">Complexity Perplexity</a></h2>
<p>These SNAP application sites create hurdles to access because the departments procuring them made or green-lit inappropriate architecture choices. In fairness, those choices may have seemed reasonable given JavaScript-based development's capture of the industry.</p>
<p>Betting on JavaScript-based, <a href="https://web.dev/articles/rendering-on-the-web">client-side rendered</a> architectures leads to complex and expensive tools. <a href="https://infrequently.org/2024/08/object-lesson/#fn-receipts-1">Judging by the code delivered over the wire,</a> neither CalSAWS nor Deloitte understand those technologies well enough to operate them proficiently.</p>
<p>From long experience and a review of the <a href="https://www.calsaws.org/wp-content/uploads/2024/07/BenefitsCal-Cumulative-Metrics-Report-June-2024.pdf">metrics (pdf)</a> the <a href="https://www.calsaws.org/">CalSAWS Joint Management Authority</a> reports, it is plain as day that the level of <a href="https://infrequently.org/2022/05/performance-management-maturity/">organisational and cultural sophistication</a> required to deploy a complex JavaScript frontend is missing in Sacramento:</p>
<p><lite-youtube videoid="t3smBkiGUWw" videotitle="Dora Militaru | Performance culture through the looking-glass" videoStartAt="1:01" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=t3smBkiGUWw">Dora Militaru | Performance culture through the looking-glass</a>              </lite-youtube></p>
<p>It's safe to assume a version of the same story played out in Annapolis, Nashville, Boston, Trenton, and Indianapolis.</p>
<p>JavaScript-based UIs are fundamentally more challenging to own and operate because the limiting factors on their success are outside the data center and not under the control of procuring teams. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#situation-report">The slow, flaky networks and low-end devices</a> that users bring to the party define the envelope of success for client-side rendered UI.</p>
<p>This means that any system that puts JavaScript in the critical path starts at a disadvantage. Not only does JavaScript cost 3x more in processing power, byte-for-byte, than HTML and CSS, but it also removes the browser's <a href="https://developer.chrome.com/blog/inside-browser-part3">ability to parallelise page loading.</a> SPA-oriented stacks also <em>preload</em> much of the functionality needed for future interactions by default. Preventing over-inclusion of ancilliary code generally requires extra effort; work that is not signposted up-front or well-understood in industry.</p>
<p>This, in turn, places hard limits on scalability that arrive <em>much</em> sooner than with HTML-first progressive enhancement.</p>
<p>Consider today's 75-percentile mobile phone<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/caprock/#fn-P75-1" id="fnref-P75-1">1</a></sup>, a device like the <a href="https://www.gsmarena.com/samsung_galaxy_a50-9554.php">Galaxy A50</a> or the <a href="https://www.gsmarena.com/nokia_g100-12373.php">Nokia G100:</a></p>
<p></p><figure class="seventy_wide"><a href="https://www.gsmarena.com/nokia_g100-12373.php" alt="The Nokia G100. It isn't fast, but it also doesn't run up-to-date Android. But for ~$170 (new, unlocked, at launch), you get a better browser than iPhones costing 10x more." target="_blank"><picture style="--lqip: -505510" class="preview">      <img src="https://infrequently.org/2024/08/the-landscape/nokia-g100.avif" alt="The Nokia G100. It isn't fast, but it also doesn't run up-to-date Android. But for ~$170 (new, unlocked, at launch), you get a better browser than iPhones costing 10x more." style="aspect-ratio: 800 / 989" class="seventy_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>The Nokia G100. It isn't fast, but it also doesn't run up-to-date Android. But for ~$170 (new, unlocked, at launch), you get a better browser than iPhones costing 10x more.</figcaption>      </figure><p></p>
<p>This isn't much of a an improvement on the <a href="https://www.gsmarena.com/motorola_moto_g4-8103.php">Moto G4</a> I recommended for testing in <em>2016</em>, and it's light years from the top-end of the market today.</p>
<p></p><figure class="full_wide"><a href="https://browser.geekbench.com/v6/cpu/compare/3826666?baseline=7190083" alt="1/10th the price, 1/9th the performance." target="_blank"><picture style="--lqip: 174819" class="preview">      <img src="https://infrequently.org/2024/08/the-landscape/nokia-g100-vs-iphone-15-pro-max.avif" alt="1/10th the price, 1/9th the performance." style="aspect-ratio: 1209 / 635" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>1/10th the price, 1/9th the performance.</figcaption>      </figure><p></p>
<p>A device like this presents hard limits on network, RAM, and CPU resources. Because JavaScript is more expensive than HTML and CSS to process, and because SPA architectures frontload script, these devices create a cap on the scalability of SPAs.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/caprock/#fn-hydration-hayfever-2" id="fnref-hydration-hayfever-2">2</a></sup> Any feature that needs to be added once the site's bundle reaches the cap is in tension with every other feature in the site until exotic route-based code-splitting tech is deployed.</p>
<p>JavaScript bundles tend to grow without constraint in the development phase and can easily tip into territory that creates an unacceptable experience for users on slow devices.</p>
<p>Only bad choices remain once a project has reached this state. I have worked with dozens of teams surprised to have found themselves in this ditch. They all feel slightly ashamed because they've been led to believe they're the first; that the technology is working fine for <em>other</em> folks.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/caprock/#fn-omerta-as-market-failure-3" id="fnref-omerta-as-market-failure-3">3</a></sup> Except it isn't.</p>
<p>I can almost recite the initial remediation steps in my sleep.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/caprock/#fn-recommendations-4" id="fnref-recommendations-4">4</a></sup></p>
<p>The remaining options are bad for compounding reasons:</p>
<ul>
<li>Digging into an experience that has been broken with JS inevitably raises a litany of issues that all need unplanned remediation.</li>
<li>Every new feature on the backlog would add to, rather than subtract from, bundle size. This creates pressure on management as feature work grinds to a halt.</li>
<li>Removing code from the bundle involves investigating and investing in new tools and deeply learning parts of the tower of JS complexity everyone assumed was &quot;fine&quot;.</li>
</ul>
<p>These problems don't generally arise in HTML-first, progressively-enhanced experiences because costs are lower at every step in the process:</p>
<ul>
<li>HTML and CSS are byte-for-byte cheaper for building an equivalent interface.</li>
<li>&quot;Routing&quot; is handled directly by the browser and the web platform through forms, links, and REST. This removes the need to load code to rebuild it.</li>
<li>Component definitions can live primarily on the server side, reducing code sent to the client.</li>
<li>Many approaches to progressive enhancement (rather than &quot;rehydration&quot;) use browser-native Web Components, eliminating both initial and incremental costs of larger, legacy-oriented frameworks.</li>
<li>Because there isn't an assumption that script is critical to the UX, users succeed more often <a href="https://medium.com/@jason.godesky/when-javascript-fails-52eef47e90db">when it isn't there.</a></li>
</ul>
<p>This model reduces the initial pressure level and keeps the temperature down by limiting the complexity of each page to what's needed.</p>
<p>Teams remediating underperforming JavaScript-based sites often make big initial gains, but the difficulty ramps up once egregious issues are fixed. The residual challenges highlight the higher structural costs of SPA architectures, and must be wrestled down the hard (read: &quot;expensive&quot;) way.</p>
<p>Initial successes also create cognitive dissonance within the team. Engineers and managers armed with experience and evidence will begin to compare themselves to competitors and, eventually, question the architecture they adopted. Teams that embark on this journey <a href="https://infrequently.org/2022/05/performance-management-maturity/">can (slowly) become masters of their own destinies.</a></p>
<p>From the plateau of enlightenment, it's simple to look back and acknowledge that for most sites, the pain, chaos, churn, and cost associated with SPA technology stacks are entirely unnecessary. From that vantage point, a team can finally, firmly <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">set policy.</a></p>
<h2 id="carrying-capacity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/caprock/#carrying-capacity">Carrying Capacity</a></h2>
<p>Organisations that purchase and operate technology all have a base carrying capacity. The cumulative experience, training, and OpEx budgets of teams set the level.</p>
<p>Traditional web development presents a model that many organisations have learned to manage. The incremental costs of additional HTML-based frontends are well understood, from authorisation to database capacity to the intricacies of web servers</p>
<p>SPA-oriented frameworks? Not so much.</p>
<p>In practice, the complex interplay of bundlers, client-side routing mechanisms, GraphQL API endpoints, and the need to rebuild monitoring and logging infrastructure creates wholly unowned areas of endemic complexity. This complexity is experienced as a shock to the operational side of the house.</p>
<p>Before, developers deploying new UIs would cabin the complexity and cost within the data center, enabling mature tools to provide visibility. SPAs and client-side rendered UIs invalidate all of these assumptions. A common result is that the operational complexity of SPA-based technologies creates new, additive points of poorly monitored system failure — failures like the ones we have explored in this series.</p>
<p>This is an industry-wide scandal. Promoters of these technologies have not levelled with their customers. Instead, they continue to flog each new iteration as &quot;the future&quot; despite the widespread failure of these models outside sophisticated organisations.</p>
<p>The pitch for SPA-oriented frameworks like React and Angular has always been contingent — we <em>might</em> deliver better experiences <em>if</em> long chains of interactions can be handled faster on the client.</p>
<p>It's time to acknowledge this isn't what is happening. For most organisations building JavaScript-first, the next dollar spent after launch day is likely go towards recovering basic functionality rather than adding new features.</p>
<p>That's no way to run a railroad.</p>
<h3 id="should-this-be-an-spa%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/caprock/#should-this-be-an-spa%3F">Should This Be An SPA?</a></h3>
<p>Public and private sector teams I consult with regularly experience ambush-by-JavaScript.</p>
<p>This is the predictable result of buying into frontend framework orthodoxy. That creed hinges on the idea that toweringly complex and expensive stacks of client-side JavaScript are necessary to deliver <em>better user experiences</em>.</p>
<p>But this has always been a contingent claim, at least among folks introspective enough to avoid suggesting JS frameworks for every site. Indeed, most web experiences should explicitly avoid both client-side rendered SPA UI and the component systems built to support them. Nearly all sites would be better off opting for <a href="https://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a> instead.</p>
<p>Doing otherwise is to invite the complexity fox into the OpEx henhouse. Before you know it, you're fighting with &quot;SSR&quot; and &quot;islands&quot; and &quot;hybrid rendering&quot; and &quot;ISR&quot; to get back to the sorts of results a bit of PHP or Ruby and some CSS deliver for a tenth the price.</p>
<p>So how can teams evaluate the appropriateness of SPAs and SPA-inspired frameworks? By revisiting the arguments offered by the early proponents of these approaches.</p>
<p>The <em>entirety</em> of SPA orthodoxy springs from the logic of the <a href="https://en.wikipedia.org/wiki/Ajax_(programming)">Ajax revolution</a>. As a witness to, <a href="https://en.wikipedia.org/wiki/Dojo_Toolkit">and early participant in,</a> that movement, I can conclusively assert that the buzz around GMail and Google Maps and many other &quot;Ajax web apps&quot; was their ability to <em>reduce latency for subsequent interactions</em> once an up-front cost had been paid.</p>
<p>The logic of this trade depends, then, on the length of sessions. As we have discussed before, <a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/">it's not clear that even GMail clears the bar</a> in all cases.</p>
<p>The utility of the next quanta of script is <em>intensely</em> dependent on session depth.</p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.png" alt="Sites with short average sessions cannot afford much JS up-front." target="_blank"><picture style="--lqip: -521501" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.png" alt="Sites with short average sessions cannot afford much JS up-front." style="aspect-ratio: 1000 / 455" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Sites with short average sessions cannot afford much JS up-front.</figcaption>      </figure><p></p>
<p>Very few sites match the criteria for SPA architectures.</p>
<p>Questions managers can use to sort wheat from chaff:</p>
<ul>
<li>Does the average session feature more than 20 updates to, or queries against, the <em>same</em> subset of global data?</li>
<li>Does this UI require features that naturally create long-lived sessions (e.g., chat, videoconferencing, etc.), and are those the site's primary purpose?</li>
<li>Is there a reason the experience can't be progressively enhanced (e.g., audio mixing, document editing, photo manipulation, video editing, mapping, hardware interaction, or gaming)?</li>
</ul>
<p>Answering these questions requires understanding critical user journeys. Flows that are most important to a site or project should be written down, and then re-examined through the lens of the marginal networks and devices of the user base.</p>
<p>The rare use-cases that are natural fits for today's JS-first dogma include:</p>
<ul>
<li>Document editors of all sorts</li>
<li>Chat and videoconferencing apps</li>
<li>Maps, geospatial, and BI visualisations</li>
</ul>
<p>Very few sites should lead with JS-based, framework-centric development.</p>
<p>Teams can be led astray when sites include mutliple apps under a single umberella. The canonical example is WordPress; a blog reading experience for millions and a blog editing UI for dozens. Treating these as independent experiences with their own constraints and tech stacks is more helpful than pretending that they're actually a &quot;single app&quot;. This is also the insight behind the &quot;islands architecture&quot;, and transfers well to other contexts, assuming the base costs of an experience remain low.</p>
<h3 id="the-pits" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/caprock/#the-pits">The Pits</a></h3>
<p>DevTools product managers use the phrase <em>&quot;pit of success&quot;</em> to describe how they hope teams experience their tools. The alternative is the (more common) <em>&quot;pit of ignorance&quot;.</em></p>
<p>The primary benefit of progressive enhancement over SPAs and SPA-begotten frameworks is that they leave teams with simpler problems, closer to the metal. Those challenges require attention and focus on the lived experience, which can be remediated cheaply once identified.</p>
<p>The alternative is considerably worse. In a previous post <a href="https://infrequently.org/2024/08/object-lesson/#fn-bull-in-a-china-shop-5">I claimed that:</a></p>
<blockquote>
<p><em>SPAs are &quot;YOLO&quot; for web development.</em></p>
</blockquote>
<p>This is because an over-reliance on JavaScript moves responsibility for <em>everything</em> into the main thread in the most expensive way.</p>
<p>Predictably, teams whose next PR adds to JS weight rather than HTML and CSS payloads will find themselves in the drink faster, and with tougher path out.</p>
<p>What's gobsmacking is that so many folks have seen these bets go sideways, yet continue to participate in the pantomime of JavaScript framework conformism. These tools aren't delivering except in the breach, but nobody will say so.</p>
<p>And if we were only lighting the bonuses of overpaid bosses on fire through under-delivery, that might be fine. But the JavaScript-industrial-complex is now hurting families in my community trying to access the help they're entitled to.</p>
<p>It's not OK.</p>
<h2 id="aftermath" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/caprock/#aftermath">Aftermath</a></h2>
<p>Frontend is mired in a practical and ethical tar pit.</p>
<p>Not only are teams paying unexpectedly large premiums to keep the lights on, a decade of increasing JavaScript complexity hasn't even delivered the better user experiences we were promised.</p>
<p>We are not getting better UX for the escalating capital and operational costs. Instead, the results are getting <em>worse</em> for folks on the margins. JavaScript-driven frontend complexity hasn't just driven out the CSS and semantic-markup experts that used to deliver usable experiences for everyone, it is now <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">a magnifier of inequality.</a></p>
<p>As <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-self-preservation-3">previously noted</a>, engineering is designing under constraint to develop products that serve users and society. The opposite of engineering is bullshitting, substituting fairy tales for inquiry and evidence.</p>
<p>For the frontend to earn and keep its stripes as an engineering discipline, frontenders need to internalise the envelope of what's possible on most devices.</p>
<p>Then we must take responsibility.</p>
<p><em><strong>Next:</strong> <a href="https://infrequently.org/2024/08/the-way-out/">The Way Out.</a></em></p>
<div style="font-size: 1rem;">
<p><em>Thanks to <a href="https://polotek.net/">Marco Rogers</a>, and <a href="https://fberriman.com/">Frances Berriman</a> for their encouragement in making this piece a series and for their thoughtful feedback on drafts.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-P75-1" class="footnote-item"><p>3/4 of all devices are faster than this phone, which means 1/4 of phones are <em>slower</em>. Teams doing serious performance work <em>tend</em> to focus on even higher percentiles (P90, P95, etc.).</p>
<p>The Nokia G100 is by no means a hard target. Teams aspiring to excellence should look further down the price and age curves for representative compute power. Phones with 28nm-fabbed A53 cores are still out there in volume. <a href="https://infrequently.org/2024/08/caprock/#fnref-P75-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-hydration-hayfever-2" class="footnote-item"><p>One response to the regressive performance of the sites enumerated here is a version of <em>&quot;they're just holding it wrong; everybody knows you should use Server-Side Rendering (SSR) to paint content quickly&quot;</em>.</p>
<p>Ignoring the factual inaccuracies undergirding SPA apologetics<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/caprock/#fn-spelling-it-out-5" id="fnref-spelling-it-out-5">5</a></sup>, the promised approaches (<a href="https://www.builder.io/blog/hydration-is-pure-overhead">&quot;SSR + hydration&quot;</a>, <a href="https://legacy.reactjs.org/blog/2022/03/29/react-v18.html">&quot;concurrent mode&quot;</a>, etc.) <em>have not worked</em>.</p>
<p>We can definitively see they haven't worked because <a href="https://web.dev/blog/inp-cwv-launch">the arrival of INP</a> has shocked the body politic. INP has created a disturbance in the JS ecosystem because, for the first time, it sets a price on main-thread excesses backed by real-world data.</p>
<p>Teams that adopt all these techniques are <a href="https://medium.com/timesopen/enhancing-the-new-york-times-web-performance-with-react-18-d6f91a7c5af8#:~:text=Immediate%20Performance%20Benefits"><em>still</em> are not achieving minimally good results.</a> This is likely why &quot;React Server Components&quot; exists; it represents a last-ditch effort to smuggle some of the most costly aspects of the SPA-based tech stack back to the server where it always belonged.</p>
<p>At the risk of tedious repetition, what these INP numbers mean is that these are <em>bad experiences</em> for <em>real users</em>. And these bad experiences can be laid directly at the feet of tools and architectures that promised <em>better</em> experiences.</p>
<p>Putting the lie to SPA theatrics doesn't require inventing a new, more objective value system. The only petard needed to hoist the React ecosystem into the stratosphere is its own sales pitch, which it has miserably and consistently failed to achieve in practice. <a href="https://infrequently.org/2024/08/caprock/#fnref-hydration-hayfever-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-omerta-as-market-failure-3" class="footnote-item"><p>The JavaScript community's omertà regarding the consistent failure of frontend frameworks to deliver reasonable results at acceptable cost is likely to be remembered as one of the most shameful aspects of frontend's lost decade.</p>
<p>Had the risks been prominently signposted, dozens of teams I've worked with personally could have avoided months of painful remediation, and hundreds more sites I've traced could have avoided material revenue losses.</p>
<p>Too many engineering leaders have found their teams beached and unproductive for no reason other than the JavaScript community's dedication to a marketing-over-results ethos of toxic positivity.</p>
<p>Shockingly, cheerleaders for this pattern of failure have not recanted, even when confronted with the consequences. They are not trustworthy. An ethical frontend practice will never arise from this pit of lies and half-truths. New leaders who reject these excesses are needed, and I look forward to supporting their efforts. <a href="https://infrequently.org/2024/08/caprock/#fnref-omerta-as-market-failure-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-recommendations-4" class="footnote-item"><p>The first steps in remediating JS-based performance disasters are always the same:</p>
<ul>
<li>Audit server configurations, including:
<ul>
<li>Check caching headers and server compression configurations.</li>
<li>Enable HTTP/2 (if not already enabled).</li>
<li>Removing extraneous critical-path connections, e.g. by serving assets from the primary rather than a CDN host.</li>
</ul>
</li>
<li>Audit the contents of the main bundle and remove unneeded or under-used dependencies.</li>
<li>Implement code-splitting and dynamic imports.</li>
<li>Set bundle size budgets and implement CI/CD enforcement.</li>
<li>Form a group of senior engineers to act as a &quot;latency council&quot;.
<ul>
<li>Require the group meet regularly to review key performance metrics.</li>
<li>Charter them to approve all changes that will impact latency.</li>
<li>Have them institute an actionable &quot;IOU&quot; system for short-term latency regression.</li>
<li>Require their collective input when drafting or grading OKRs.</li>
</ul>
</li>
<li>Beg, borrow, or <s>steal</s> buy low-end devices for all product managers and follow up to ensure they're using them regularly.</li>
</ul>
<p>There's always more to explore. <a href="https://www.speedcurve.com/web-performance-guide/">SpeedCurve's Performance Guide</a> and <a href="https://www.webpagetest.org/learn/lightning-fast-web-performance/">WebPageTest.org's free course</a> make good next steps. <a href="https://infrequently.org/2024/08/caprock/#fnref-recommendations-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-spelling-it-out-5" class="footnote-item"><p>Apologists for SPA architectures tend to trot out arguments with the form <em>&quot;nobody does X any more&quot;</em> or <em>&quot;everybody knows not to do Y&quot;</em> when facing concrete evidence that sites with <em>active maintenance</em> are doing exactly the things they have recently dissavowed, proving instead that not only are wells uncapped, but the oil slicks aren't even boomed.</p>
<p>It has <em>never</em> been true that in-group disfavour fully contains the spread of once-popular techniques. For chrissake, just look at the CSS-in-JS delusion! This anti-pattern appears in a huge fraction of the traces I look at from <em>new</em> projects today, and that fraction has only gone <em>up</em> since FB hipsters (who were warned directly by browser engineers that it was a terrible idea) finally declared it a terrible idea.</p>
<p>Almost none of today's regretted projects carry disclaimers. None of the frameworks that have led to consistent disasters have posted warnings about their appropriate use. Few boosters for these technologies even outline what <em>they</em> had to do to stop the bleeding (and there is <em>always</em> bleeding) after adopting these complex, expensive, and slow architectures.</p>
<p>Instead, teams are supposed to have followed every twist and turn of inscrutable faddism, spending effort to upgrade huge codebases whenever the new hotness changes.</p>
<p>Of course, when you point out that this is what the apologists are saying, <a href="https://en.wikipedia.org/wiki/No_true_Scotsman">no-true-Scotsmanship</a> unfurls like clockwork.</p>
<p>It's irresponsibility theatre.</p>
<p>Consulting with more than a hundred teams over the past eight years has given me ring-side season tickets to the touring production of this play. The first few performances contained frission, some mystery...but now it's all played out. There's no paradox — the lies by omission are fully revealed, and the workmanlike retelling by each new understudy is as charmless as the last.</p>
<p>All that's left is to pen scathing reviews in the hopes that the tour closes for good. <a href="https://infrequently.org/2024/08/caprock/#fnref-spelling-it-out-5" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Reckoning: Part 2 — Object Lesson</title>
    <link href="https://infrequently.org/2024/08/object-lesson/"/>
    <updated>2024-08-13T00:00:00Z</updated>
    <id>https://infrequently.org/2024/08/object-lesson/</id>
    <content type="html"><![CDATA[
      <div style="font-size: 1rem;">
<p><em>Other posts in the series:</em></p>
<ul>
<li><em><a href="https://infrequently.org/2024/08/the-landscape/">Reckoning: Part 1 — The Landscape</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/caprock/">Reckoning: Part 3 — Caprock</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/the-way-out/">Reckoning: Part 4 — The Way Out</a></em></li>
</ul>
</div>
<!-- <hr> -->
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/08/object-lesson/#the-golden-wait">The Golden Wait</a><ul><li><a href="https://infrequently.org/2024/08/object-lesson/#the-truth-is-in-the-trace">The Truth Is In The Trace</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#zip-it">Zip It</a></li></ul></li><li><a href="https://infrequently.org/2024/08/object-lesson/#near-peers">Near Peers</a><ul><li><a href="https://infrequently.org/2024/08/object-lesson/#blimey">Blimey</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#javascript-masshattery">JavaScript Masshattery</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#maryland-enters-the-chat">Maryland Enters The Chat</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#chattanooga-chug-chug">Chattanooga Chug Chug</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#snap%3F-in-jersey%3F-fuhgeddaboudit">SNAP? In Jersey? Fuhgeddaboudit</a></li><li><a href="https://infrequently.org/2024/08/object-lesson/#hoosier-hospitality">Hoosier Hospitality</a></li></ul></li><li><a href="https://infrequently.org/2024/08/object-lesson/#deep-breaths">Deep Breaths</a></li></ul></nav>
<h2 id="the-golden-wait" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#the-golden-wait">The Golden Wait</a></h2>
<p><a href="https://benefitscal.com/">BenefitsCal</a> is the state of California's recently developed portal for families that need to access SNAP benefits (née &quot;food stamps&quot;):<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-receipts-1" id="fnref-receipts-1">1</a></sup></p>
<br style="display: none;" />
<figure style="max-width: 422px; width: 80%;" class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240729_AiDcPE_4F2/runs/1/firstView/timeline.mp4" poster="https://infrequently.org/2024/08/the-landscape/wpt-traces/240729_AiDcPE_4F2/runs/1/firstView/screenShot.png" playsinline="" controls="" preload="metadata" style="aspect-ratio: 422 / 600;" loading="lazy">
</video>
<figcaption>
  BenefitsCal loading on a low-end device over a 9Mbps link with 170ms RTT latency via WebPageTest.org
</figcaption>
</figure>
<!-- TODO: discuss JS costs here? -->
<p><a href="https://codeforamerica.org/">Code for America's</a> <a href="https://www.getcalfresh.org/"><code>getcalfresh.org</code></a> performs substantially the same function, providing a cleaner, faster, and easier-to-use alternative to California county and state benefits applications systems:</p>
<br style="display: none;" />
<figure style="max-width: 422px; width: 80%;" class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240801_AiDc98_EG7/runs/1/firstView/timeline.mp4" poster="https://infrequently.org/2024/08/the-landscape/wpt-traces/240801_AiDc98_EG7/runs/1/firstView/screenShot.png" playsinline="" controls="" preload="metadata" style="aspect-ratio: 422 / 600;" loading="lazy">
</video>
<figcaption>
  getcalfresh.org loading under the same conditions
</figcaption>
</figure>
<p>The like-for-like, same-state comparison getcalfresh.org provides is unique. Few public sector services in the US have competing interfaces, and only Code for America was motivated to build one for SNAP applications.</p>
<figure class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-getcalfresh.mp4" poster="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-getcalfresh.webp" playsinline="" controls="" preload="metadata" style="aspect-ratio: 904 / 680;" loading="lazy">
</video>
<figcaption>
  getcalfresh.org finishes in 1/3 the time, becoming interactive not long after the BenefitsCal loading screen appears.
</figcaption>
</figure>  
<p>WebPageTest.org timelines document a painful progression. Users can begin to interact with getcalfresh.org before the first (of three) BenefitsCal loading screens finish (scroll right to advance):</p>
<!-- TODO: label styling -->
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" interval="500ms">
      <wpt-test label="BenefitsCal, first load">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240729_AiDcPE_4F2","url":"https://benefitscal.com/","summary":"https://www.webpagetest.org/results.php?test=240729_AiDcPE_4F2","testUrl":"https://benefitscal.com/","location":"ec2-us-east-1:Chrome","from":"Dulles, Virginia, USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722233792,"testRuns":3,"testName":"240729_AiDcPE_4F2","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://benefitscal.com/"},"metrics":{"navigation_types":{"fractions":{"restore":0,"back_forward":0.0017,"back_forward_cache":0.0028,"prerender":0.0181,"navigate":0.4393,"navigate_cache":0.4775,"reload":0.0605}},"round_trip_time":{"percentiles":{"p75":135}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.0826},{"start":"0.10","end":"0.25","density":0.0068},{"start":"0.25","density":0.9106}],"percentiles":{"p75":"1.28"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8555},{"start":800,"end":1800,"density":0.0942},{"start":1800,"density":0.0503}],"percentiles":{"p75":522}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.3788},{"start":1800,"end":3000,"density":0.2685},{"start":3000,"density":0.3526}],"percentiles":{"p75":3868}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9333},{"start":100,"end":300,"density":0.041},{"start":300,"density":0.0257}],"percentiles":{"p75":20}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.6106},{"start":200,"end":500,"density":0.2647},{"start":500,"density":0.1247}],"percentiles":{"p75":305}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.3767},{"start":2500,"end":4000,"density":0.2321},{"start":4000,"density":0.3912}],"percentiles":{"p75":5975}}},"collectionPeriod":{"firstDate":{"year":2024,"month":6,"day":30},"lastDate":{"year":2024,"month":7,"day":27}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/details/","checklist":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/breakdown/","domains":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/domains/","screenShot":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240729_AiDcPE_4F2/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/07/29/AiDcPE/4F2/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/07/29/AiDcPE/4F2/1_connection.png","checklist":"https://www.webpagetest.org/result/24/07/29/AiDcPE/4F2/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240729_AiDcPE_4F2&file=1_screen.jpg"},"breakdown":{"html":{"bytes":4448,"bytesUncompressed":4448,"requests":1},"js":{"bytes":16554750,"bytesUncompressed":20415021,"requests":208},"css":{"bytes":844999,"bytesUncompressed":846451,"requests":4},"image":{"bytes":176009,"bytesUncompressed":176009,"requests":12},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":832148,"bytesUncompressed":832148,"requests":9},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":1334489,"bytesUncompressed":1336419,"requests":14}},"loadTime":12827,"docTime":12827,"fullyLoaded":30032,"firstPaint":3335,"firstContentfulPaint":6036,"lastVisualChange":29400,"visualComplete":29400,"visualComplete85":29400,"visualComplete90":29400,"visualComplete95":29400,"visualComplete99":29400,"SpeedIndex":21501,"TotalBlockingTime":15552,"layoutShifts":[18353,19344,21222,23617,27464,28817],"lcps":[28959],"navigationStart":105,"fetchStart":54,"domLoading":810,"responseEnd":803,"domInteractive":12824,"domContentLoadedEventStart":12824,"domContentLoadedEventEnd":12825,"domComplete":12827,"unloadEventStart":808,"unloadEventEnd":808,"markAsMainFrame":809,"commitNavigationEnd":810,"firstMeaningfulPaintCandidate":16636,"loadEventStart":12827,"loadEventEnd":12827,"firstImagePaint":19453,"LargestTextPaint":28959,"LargestImagePaint":19453,"LargestContentfulPaint":28959,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":3600,"image":"filmstrip/ms_003600.jpg","VisuallyComplete":39},{"time":3700,"image":"filmstrip/ms_003700.jpg","VisuallyComplete":39},{"time":3800,"image":"filmstrip/ms_003800.jpg","VisuallyComplete":40},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":40},{"time":4000,"image":"filmstrip/ms_004000.jpg","VisuallyComplete":40},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":41},{"time":4200,"image":"filmstrip/ms_004200.jpg","VisuallyComplete":41},{"time":4300,"image":"filmstrip/ms_004300.jpg","VisuallyComplete":41},{"time":4500,"image":"filmstrip/ms_004500.jpg","VisuallyComplete":48},{"time":4600,"image":"filmstrip/ms_004600.jpg","VisuallyComplete":48},{"time":4700,"image":"filmstrip/ms_004700.jpg","VisuallyComplete":52},{"time":4800,"image":"filmstrip/ms_004800.jpg","VisuallyComplete":54},{"time":4900,"image":"filmstrip/ms_004900.jpg","VisuallyComplete":50},{"time":5000,"image":"filmstrip/ms_005000.jpg","VisuallyComplete":49},{"time":5100,"image":"filmstrip/ms_005100.jpg","VisuallyComplete":53},{"time":5200,"image":"filmstrip/ms_005200.jpg","VisuallyComplete":54},{"time":5300,"image":"filmstrip/ms_005300.jpg","VisuallyComplete":52},{"time":5400,"image":"filmstrip/ms_005400.jpg","VisuallyComplete":49},{"time":5500,"image":"filmstrip/ms_005500.jpg","VisuallyComplete":48},{"time":5600,"image":"filmstrip/ms_005600.jpg","VisuallyComplete":48},{"time":5700,"image":"filmstrip/ms_005700.jpg","VisuallyComplete":48},{"time":5800,"image":"filmstrip/ms_005800.jpg","VisuallyComplete":48},{"time":5900,"image":"filmstrip/ms_005900.jpg","VisuallyComplete":48},{"time":6000,"image":"filmstrip/ms_006000.jpg","VisuallyComplete":52},{"time":6100,"image":"filmstrip/ms_006100.jpg","VisuallyComplete":54},{"time":6200,"image":"filmstrip/ms_006200.jpg","VisuallyComplete":50},{"time":6300,"image":"filmstrip/ms_006300.jpg","VisuallyComplete":49},{"time":6400,"image":"filmstrip/ms_006400.jpg","VisuallyComplete":54},{"time":6500,"image":"filmstrip/ms_006500.jpg","VisuallyComplete":54},{"time":6600,"image":"filmstrip/ms_006600.jpg","VisuallyComplete":52},{"time":6700,"image":"filmstrip/ms_006700.jpg","VisuallyComplete":49},{"time":6800,"image":"filmstrip/ms_006800.jpg","VisuallyComplete":48},{"time":6900,"image":"filmstrip/ms_006900.jpg","VisuallyComplete":48},{"time":7000,"image":"filmstrip/ms_007000.jpg","VisuallyComplete":48},{"time":7100,"image":"filmstrip/ms_007100.jpg","VisuallyComplete":48},{"time":7200,"image":"filmstrip/ms_007200.jpg","VisuallyComplete":48},{"time":7300,"image":"filmstrip/ms_007300.jpg","VisuallyComplete":52},{"time":7400,"image":"filmstrip/ms_007400.jpg","VisuallyComplete":54},{"time":7500,"image":"filmstrip/ms_007500.jpg","VisuallyComplete":50},{"time":7600,"image":"filmstrip/ms_007600.jpg","VisuallyComplete":49},{"time":7700,"image":"filmstrip/ms_007700.jpg","VisuallyComplete":54},{"time":7800,"image":"filmstrip/ms_007800.jpg","VisuallyComplete":54},{"time":7900,"image":"filmstrip/ms_007900.jpg","VisuallyComplete":52},{"time":8000,"image":"filmstrip/ms_008000.jpg","VisuallyComplete":49},{"time":8100,"image":"filmstrip/ms_008100.jpg","VisuallyComplete":48},{"time":8200,"image":"filmstrip/ms_008200.jpg","VisuallyComplete":48},{"time":8300,"image":"filmstrip/ms_008300.jpg","VisuallyComplete":48},{"time":8400,"image":"filmstrip/ms_008400.jpg","VisuallyComplete":48},{"time":8500,"image":"filmstrip/ms_008500.jpg","VisuallyComplete":48},{"time":8600,"image":"filmstrip/ms_008600.jpg","VisuallyComplete":52},{"time":9000,"image":"filmstrip/ms_009000.jpg","VisuallyComplete":54},{"time":9500,"image":"filmstrip/ms_009500.jpg","VisuallyComplete":48},{"time":10000,"image":"filmstrip/ms_010000.jpg","VisuallyComplete":54},{"time":10500,"image":"filmstrip/ms_010500.jpg","VisuallyComplete":52},{"time":11000,"image":"filmstrip/ms_011000.jpg","VisuallyComplete":48},{"time":11500,"image":"filmstrip/ms_011500.jpg","VisuallyComplete":50},{"time":12000,"image":"filmstrip/ms_012000.jpg","VisuallyComplete":48},{"time":12500,"image":"filmstrip/ms_012500.jpg","VisuallyComplete":52},{"time":13000,"image":"filmstrip/ms_013000.jpg","VisuallyComplete":54},{"time":13500,"image":"filmstrip/ms_013500.jpg","VisuallyComplete":48},{"time":14000,"image":"filmstrip/ms_014000.jpg","VisuallyComplete":50},{"time":15000,"image":"filmstrip/ms_015000.jpg","VisuallyComplete":48},{"time":16000,"image":"filmstrip/ms_016000.jpg","VisuallyComplete":48},{"time":17000,"image":"filmstrip/ms_017000.jpg","VisuallyComplete":4},{"time":18000,"image":"filmstrip/ms_018000.jpg","VisuallyComplete":4},{"time":19000,"image":"filmstrip/ms_019000.jpg","VisuallyComplete":4},{"time":20000,"image":"filmstrip/ms_020000.jpg","VisuallyComplete":4},{"time":21000,"image":"filmstrip/ms_021000.jpg","VisuallyComplete":4},{"time":22000,"image":"filmstrip/ms_022000.jpg","VisuallyComplete":57},{"time":23000,"image":"filmstrip/ms_023000.jpg","VisuallyComplete":8},{"time":24000,"image":"filmstrip/ms_024000.jpg","VisuallyComplete":8},{"time":25000,"image":"filmstrip/ms_025000.jpg","VisuallyComplete":8},{"time":26000,"image":"filmstrip/ms_026000.jpg","VisuallyComplete":8},{"time":27000,"image":"filmstrip/ms_027000.jpg","VisuallyComplete":8},{"time":28000,"image":"filmstrip/ms_028000.jpg","VisuallyComplete":7},{"time":29000,"image":"filmstrip/ms_029000.jpg","VisuallyComplete":8},{"time":29400,"image":"filmstrip/ms_029400.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":324,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
      <wpt-test label="getcalfresh.org, first load">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240801_AiDc98_EG7","url":"https://www.getcalfresh.org/","summary":"https://www.webpagetest.org/results.php?test=240801_AiDc98_EG7","testUrl":"https://www.getcalfresh.org/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722552429,"testRuns":3,"testName":"240801_AiDc98_EG7","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://www.getcalfresh.org/"},"metrics":{"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.9038},{"start":200,"end":500,"density":0.0767},{"start":500,"density":0.0195}],"percentiles":{"p75":110}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.8948},{"start":2500,"end":4000,"density":0.056},{"start":4000,"density":0.0492}],"percentiles":{"p75":1514}},"navigation_types":{"fractions":{"reload":0.0337,"restore":0,"back_forward":0.1502,"back_forward_cache":0.0075,"prerender":0,"navigate":0.8035,"navigate_cache":0.005}},"round_trip_time":{"percentiles":{"p75":124}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.9929},{"start":"0.10","end":"0.25","density":0.0027},{"start":"0.25","density":0.0044}],"percentiles":{"p75":"0.00"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8479},{"start":800,"end":1800,"density":0.1059},{"start":1800,"density":0.0462}],"percentiles":{"p75":598}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.8531},{"start":1800,"end":3000,"density":0.0803},{"start":3000,"density":0.0666}],"percentiles":{"p75":1328}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9431},{"start":100,"end":300,"density":0.0436},{"start":300,"density":0.0133}],"percentiles":{"p75":15}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":3},"lastDate":{"year":2024,"month":7,"day":30}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/details/","checklist":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/breakdown/","domains":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/domains/","screenShot":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240801_AiDc98_EG7/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/01/AiDc98/EG7/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/01/AiDc98/EG7/1_connection.png","checklist":"https://www.webpagetest.org/result/24/08/01/AiDc98/EG7/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240801_AiDc98_EG7&file=1_screen.jpg"},"breakdown":{"html":{"bytes":27658,"bytesUncompressed":23305,"requests":3},"js":{"bytes":682265,"bytesUncompressed":2202922,"requests":14},"css":{"bytes":41288,"bytesUncompressed":198410,"requests":1},"image":{"bytes":221043,"bytesUncompressed":221043,"requests":13},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":128180,"bytesUncompressed":128180,"requests":1},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":2386,"bytesUncompressed":5504,"requests":8}},"loadTime":7110,"docTime":7110,"fullyLoaded":10121,"firstPaint":3100,"firstContentfulPaint":3100,"firstMeaningfulPaint":3834,"lastVisualChange":10300,"visualComplete":10300,"visualComplete85":3900,"visualComplete90":3900,"visualComplete95":10300,"visualComplete99":10300,"SpeedIndex":4332,"TotalBlockingTime":2647,"layoutShifts":[9899,10000,10125],"lcps":[3834],"navigationStart":51,"fetchStart":14,"domLoading":1210,"responseEnd":1197,"domInteractive":4187,"domContentLoadedEventStart":4187,"domContentLoadedEventEnd":4194,"domComplete":7109,"unloadEventStart":1203,"unloadEventEnd":1203,"markAsMainFrame":1203,"commitNavigationEnd":1204,"firstMeaningfulPaintCandidate":3834,"firstImagePaint":4099,"loadEventStart":7109,"loadEventEnd":7119,"LargestTextPaint":3834,"LargestImagePaint":4099,"LargestContentfulPaint":3834,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":3100,"image":"filmstrip/ms_003100.jpg","VisuallyComplete":2},{"time":3900,"image":"filmstrip/ms_003900.jpg","VisuallyComplete":93},{"time":4100,"image":"filmstrip/ms_004100.jpg","VisuallyComplete":93},{"time":10000,"image":"filmstrip/ms_010000.jpg","VisuallyComplete":93},{"time":10100,"image":"filmstrip/ms_010100.jpg","VisuallyComplete":93},{"time":10300,"image":"filmstrip/ms_010300.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":133,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>Google's <a href="https://web.dev/articles/vitals">Core Web Vitals</a> data backs up test bench assessments. Real-world users are having a challenging time accessing the site:</p>
<p></p><figure class="full_wide"><a href="https://treo.sh/sitespeed/benefitscal.com?metrics=cls%2Clcp%2Cr&formFactor=phone" alt="BenefitsCal is a poor experience on real phones." target="_blank"><picture style="--lqip: 173795" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-cwv.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/benefitscal.com-cwv.webp" alt="BenefitsCal is a poor experience on real phones." style="aspect-ratio: 1311 / 391" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>BenefitsCal is a poor experience on real phones.</figcaption>      </figure><p></p>
<p>But wait! There's more. It's even worse than it looks.</p>
<p>The multi-loading-screen structure of BenefitsCal fakes out Chrome's heuristic for when to record Largest Contentful Paint.</p>
<p></p><figure><a href="https://www.webpagetest.org/video/compare.php?tests=240729_AiDcPE_4F2-r:1-c:0#compare_visual_progress" alt="On low-end devices, BenefitsCal appears to <em>almost</em> load at the 22 second mark, only to put up a second loading screen shortly after. Because this takes so long, Chromium's heuristics for Largest Contentful Paint are thrown off, incorrectly reporting the end of the first loading screen as the complete page." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-visual-progress.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/benefitscal.com-visual-progress.webp" alt="On low-end devices, BenefitsCal appears to <em>almost</em> load at the 22 second mark, only to put up a second loading screen shortly after. Because this takes so long, Chromium's heuristics for Largest Contentful Paint are thrown off, incorrectly reporting the end of the first loading screen as the complete page." style="aspect-ratio: 1028 / 542" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>On low-end devices, BenefitsCal appears to <em>almost</em> load at the 22 second mark, only to put up a second loading screen shortly after. Because this takes so long, Chromium's heuristics for Largest Contentful Paint are thrown off, incorrectly reporting the end of the first loading screen as the complete page.</figcaption>      </figure><p></p>
<p>The real-world experience is <em>significantly</em> worse than public CWV metrics suggest.</p>
<p><a href="https://www.getcalfresh.org/">Getcalfresh.org</a> uses a simpler, <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">progressively enhanced,</a> HTML-first architecture to deliver the same account and benefits signup process, driving nearly half of all signups for California benefits (per CalSAWS).</p>
<p>The results are night-and-day:<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-quibbles-2" id="fnref-quibbles-2">2</a></sup></p>
<p></p><figure class="full_wide"><a href="https://treo.sh/sitespeed/www.getcalfresh.org?metrics=cls%2Clcp%2Cr&formFactor=phone" alt="getcalfresh.org generates almost half of the new filings to the CalSAWS system. Its relative usability presumably contributes to that success." target="_blank"><picture style="--lqip: 173795" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/getcalfresh.org-cwv.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/getcalfresh.org-cwv.webp" alt="getcalfresh.org generates almost half of the new filings to the CalSAWS system. Its relative usability presumably contributes to that success." style="aspect-ratio: 1295 / 393" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>getcalfresh.org generates almost half of the new filings to the CalSAWS system. Its relative usability presumably contributes to that success.</figcaption>      </figure><p></p>
<p>And this is <em>after</em> the state <a href="https://www.calsaws.org/wp-content/uploads/2023/11/5d_Deloitte-Portal-Mobile-Change-Order-5-Work-Order-14.pdf">spent a million dollars on work to achieve &quot;GCF parity&quot;.</a></p>
<h3 id="the-truth-is-in-the-trace" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#the-truth-is-in-the-trace">The Truth Is In The Trace</a></h3>
<!-- 
       <figure class="seventy_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240708_BiDcF9_9KA-r%3A1-c%3A0&ival=100&end=visual" alt="You don't have to be a browser engineer or a web performance expert to understand that requesting so many large files is going to lead to a bad time." target="_blank"><picture style="--lqip: 166627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px"                srcset="/.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=3600 2400w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=2400 1600w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=1800 1200w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=1200 800w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=900 600w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=750 500w, /.netlify/images?url=/2024/08/the-landscape/benefits_cal_waterfall.png&fm=avif&w=600 400w" />      <img src="/2024/08/the-landscape/benefits_cal_waterfall.png"        alt="You don't have to be a browser engineer or a web performance expert to understand that requesting so many large files is going to lead to a bad time." style="aspect-ratio: 1012 / 4885" class="seventy_wide preview"        decoding="async" loading="lazy">      </picture>          </a>        <figcaption>You don't have to be a browser engineer or a web performance expert to understand that requesting so many large files is going to lead to a bad time.</figcaption>      </figure>    
-->
<!-- https://www.webpagetest.org/breakdown.php?test=240708_BiDcF9_9KA&run=2&end=visual -->
<p>No failure this complete has a single father. It's easy to enumerate contributing factors from the <a href="https://www.webpagetest.org/video/compare.php?tests=240708_BiDcF9_9KA-r%3A1-c%3A0&amp;ival=100&amp;end=visual">WebPageTest.org trace</a>, and a summary of the site's composition and caching make for <a href="https://www.webpagetest.org/breakdown.php?test=240708_BiDcF9_9KA&amp;run=2&amp;end=visual">a bracing read</a>:</p>
<table class="summary" style="margin: auto; min-width: 100%;" id="kbs">  
  <thead>
    <tr>
      <th rowspan="1">Type</th>
      <th colspan="3">First View</th>
      <th colspan="4">Repeat View</th>
    </tr>
    <tr>
      <th></th>
      <th>Wire (KB)</th>
      <th>Disk</th>
      <th><a href="https://en.wikipedia.org/wiki/Data_compression_ratio" target="_new">D:W</a></th>
      <th>Wire</th>
      <th>Disk</th>
      <th>D:W</th>
      <th>Cache</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>JS</td>
      <td>17,435</td>
      <td>25,865</td>
      <td>1.5</td>
      <td>15,950</td>
      <td>16,754</td>
      <td>1.1</td>
      <td>9%</td>
    </tr>
    <tr>
      <td>Other</td>
      <td>1,341</td>
      <td>1,341</td>
      <td>1.0</td>
      <td>1,337</td>
      <td>1,337</td>
      <td>1.0</td>
      <td>1%</td>
    </tr>
    <tr>
      <td>CSS</td>
      <td>908</td>
      <td>908</td>
      <td>1.0</td>
      <td>844</td>
      <td>844</td>
      <td>1.0</td>
      <td>7%</td>
    </tr>
    <tr>
      <td>Font</td>
      <td>883</td>
      <td>883</td>
      <td>N/A</td>
      <td>832</td>
      <td>832</td>
      <td>N/A</td>
      <td>0%</td>
    </tr>
    <tr>
      <td>Image</td>
      <td>176</td>
      <td>176</td>
      <td>N/A</td>
      <td>161</td>
      <td>161</td>
      <td>N/A</td>
      <td>9%</td>
    </tr>
    <tr>
      <td>HTML</td>
      <td>6</td>
      <td>7</td>
      <td>1.1</td>
      <td>4</td>
      <td>4</td>
      <td>1.0</td>
      <td>N/A</td>
    </tr>
    <tr>
      <td>Total</td>
      <td>20,263</td>
      <td>29,438</td>
      <td>1.45</td>
      <td>18,680</td>
      <td>19,099</td>
      <td>1.02</td>
      <td>7%</td>
    </tr>
  </tbody>
</table>
<p>The first problem is that this site relies on 25 megabytes of JavaScript (uncompressed, 17.4 MB on over the wire) and loads all of it before presenting <em>any</em> content to users. This would be unusably slow for many, even if served well. Users on connections worse than the <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#test-device-recommendations">P75 baseline</a> emulated here experience excruciating wait times. This much script also increases the likelihood of tab crashes on low-end devices.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-covariate-factors-3" id="fnref-covariate-factors-3">3</a></sup></p>
<p>Very little of this code is actually used on the home page, and loading the home page is presumably the most common thing users of the site do:<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-the-its-an-app-lie-4" id="fnref-the-its-an-app-lie-4">4</a></sup></p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2024/08/the-landscape/benefitscal.com-coverage.avif" alt="Red is bad. DevTools shows less than a quarter of the JavaScript downloaded is executed." target="_blank"><picture style="--lqip: -174749" class="preview">      <img src="https://infrequently.org/2024/08/the-landscape/benefitscal.com-coverage.avif" alt="Red is bad. DevTools shows less than a quarter of the JavaScript downloaded is executed." style="aspect-ratio: 1539 / 555" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Red is bad. DevTools shows less than a quarter of the JavaScript downloaded is executed.</figcaption>      </figure><p></p>
<p>As bad as that is, the wait to interact at all is made substantially worse by inept server configuration. Industry-standard gzip compression generally results in 4:1-8:1 data savings for text resources (HTML, CSS, JavaScript, and &quot;other&quot;) depending on file size and contents. That would reduce ~28 megabytes of text, currently served in 19MB of partially compressed resources, to between 3.5MB and 7MB.</p>
<p>But compression is not enabled for most assets, subjecting users to wait for 19MB of content. If CalSAWS built BenefitsCal using progressive enhancement, early HTML and CSS would become interactive while JavaScript filigrees loaded in the background. No such luck for BenefitsCal users on slow connections.</p>
<p></p><figure class="full_wide"><a href="https://broadbandmap.fcc.gov/location-summary/mobile?version=dec2023&zoom=4.98&vlon=-119.671255&vlat=37.829130&env=0&tech=tech4g" alt="For as bad as cell and land-line internet service are in dense California metros, the vast rural population experiences large areas with even less coverage." target="_blank"><picture style="--lqip: -514590" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/ca-fcc-nbm-4g.webp" alt="For as bad as cell and land-line internet service are in dense California metros, the vast rural population experiences large areas with even less coverage." style="aspect-ratio: 1162 / 966" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>For as bad as cell and land-line internet service are in dense California metros, the vast rural population experiences large areas with even less coverage.</figcaption>      </figure><p></p>
<p>Thanks to the site's React-centric, JavaScript-dependent, <a href="https://en.wikipedia.org/wiki/Single-page_application">client-side rendered, single-page-app (SPA) architecture</a>, nothing is usable until nearly the entire payload is downloaded and run, defeating built-in browser mitigations for slow pages. Had progressive enhancement been employed, even egregious server misconfigurations would have had a muted effect by comparison.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-bull-in-a-china-shop-5" id="fnref-bull-in-a-china-shop-5">5</a></sup></p>
<h3 id="zip-it" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#zip-it">Zip It</a></h3>
<p>Gzip compression has been industry standard on the web for more than 15 years, and <a href="https://github.com/google/brotli">more aggressive algorithms</a> are now available. All <a href="https://en.wikipedia.org/wiki/HTTP_compression#Servers_that_support_HTTP_compression">popular web servers</a> support compression, and some <a href="https://httpd.apache.org/docs/current/mod/mod_deflate.html">enable it by default</a>. It's so common that nearly every web performance testing tool checks for it, including Google's <a href="https://pagespeed.web.dev/">PageSpeed Insights</a>.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-blockage-6" id="fnref-blockage-6">6</a></sup></p>
<p>Gzip would have reduced the largest script from 2.1MB to a comparatively svelte 340K; a 6.3x compression ratio:</p>
<pre><code>$ gzip -k main.2fcf663c.js 
$ ls -l
&gt; total 2.5M
&gt; ... 2.1M Aug  1 17:47 main.2fcf663c.js
&gt; ... 340K Aug  1 17:47 main.2fcf663c.js.gz
</code></pre>
<p>Not only does the site require a gobsmacking amount of data on first visit, it taxes users nearly the same amount every time they return.</p>
<p>Because most of the site's payload is static, the fraction cached between first and repeat views should be near 100%. BenefitsCal achieves just 7%.</p>
<p>This isn't just perverse; it's <a href="https://web.dev/articles/http-cache">so far out of the norm</a> that I struggled to understand how CalSAWS managed to so thoroughly misconfigure a web server modern enough to support <a href="https://en.wikipedia.org/wiki/HTTP/2">HTTP/2.</a></p>
<p>The answer? Overlooked <a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html#compressed-content-cloudfront-configuring">turnkey caching options in CloudFront's dashboard.</a><sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-wtf-amazon-7" id="fnref-wtf-amazon-7">7</a></sup></p>
<p>This oversight might have been understandable at launch. The mystery remains how it persisted <a href="https://www.marinhhs.org/sites/default/files/files/servicepages/2021_09/benefitscal_factsheet_0.pdf">for nearly <em>three years</em> (pdf).</a> The slower the device and network, the more sluggish the site feels. Unlike backend slowness, the effects of ambush-by-JavaScript can remain obscured by the fast phones and computers used by managers and developers.</p>
<p>But even if CalSAWS staff never leave the privilege bubble, there has been plenty of feedback:</p>
<p></p><figure><a href="https://www.reddit.com/r/foodstamps/comments/16wuqjl/comment/k2z70kv/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button" alt="A Reddit user responding to product-level concerns with: <br><em>'And it's so f'n slow.'</em>" target="_blank"><picture style="--lqip: -174813" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/benefitscal.com-slowness-report.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/benefitscal.com-slowness-report.webp" alt="A Reddit user responding to product-level concerns with: <br><em>'And it's so f'n slow.'</em>" style="aspect-ratio: 325 / 152" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>A Reddit user responding to product-level concerns with: <br /><em>'And it's so f'n slow.'</em></figcaption>      </figure><p></p>
<p>Having placed a bet on client-side rendering, CalSAWS, <a href="https://www.calsaws.org/procurement/calsaws-maintenance-and-operations-mo-procurement/">Gainwell, and Deloitte</a> staff needed to add additional testing and monitoring to assess the site as customers experience it. This obviously did not happen.</p>
<p>The most generous assumption is they were not prepared to manage the downsides of the complex and expensive JavaScript-based architecture they chose over <a href="https://www.smashingmagazine.com/2009/04/progressive-enhancement-what-it-is-and-how-to-use-it/">progressive enhancement</a>.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-occam-says-8" id="fnref-occam-says-8">8</a></sup><sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-from-each-according-to-his-ability-9" id="fnref-from-each-according-to-his-ability-9">9</a></sup></p>
<h2 id="near-peers" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#near-peers">Near Peers</a></h2>
<p>Analogous sites from other states point the way. For instance, Wisconsin's ACCESS system:</p>
<figure class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-wiaccess.mp4" poster="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-wiaccess.webp" playsinline="" controls="" preload="metadata" style="aspect-ratio: 904 / 680;" loading="lazy">
</video>
<figcaption>
  Six seconds isn't setting records, but it's a fifth as long as it takes to access BenefitsCal.
</figcaption>
</figure>  
<p>There's a lot that could be improved about WI ACCESS's performance. Fonts are loaded too late, and some of the images are too large. They could benefit from <a href="https://developer.chrome.com/docs/lighthouse/performance/uses-webp-images">modern formats like WebP or AVIF</a>. JavaScript could be delay-loaded and served from the same origin to reduce connection setup costs. HTTP/2 would left-shift many of the early resources fetched in this trace.</p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_AiDcKR_CKB-r%3A1-c%3A0&ival=100&end=visual" alt="WI ACCESS harks from simpler times." target="_blank"><picture style="--lqip: 166627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_AiDcKR_CKB/runs/1/firstView/waterfall.png" alt="WI ACCESS harks from simpler times." style="aspect-ratio: 1012 / 1179" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>WI ACCESS harks from simpler times.</figcaption>      </figure><p></p>
<p>But the experience isn't on fire, listing, and taking on water.</p>
<p></p><figure class="full_wide"><a href="https://treo.sh/sitespeed/access.wisconsin.gov?metrics=cls%2Clcp%2Cr&formFactor=phone" alt="Despite numerous opportunities for improvement, WI ACCESS's appropriate architecture keeps the site usable for all." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wiaccess-cwv.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wiaccess-cwv.webp" alt="Despite numerous opportunities for improvement, WI ACCESS's appropriate architecture keeps the site usable for all." style="aspect-ratio: 1303 / 395" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Despite numerous opportunities for improvement, WI ACCESS's appropriate architecture keeps the site usable for all.</figcaption>      </figure><p></p>
<p>Because the site is built in a progressively enhanced way, simple fixes can cheaply and quickly improve on an acceptable baseline.</p>
<p>Even today's &quot;slow&quot; networks and phones are so fast that sites can commit almost every kind of classic error and still deliver usable experiences. Sites like WI ACCESS would have felt sluggish just 5 years ago but work fine today. It takes extra effort to screw up as badly as BenefitsCal has.</p>
<h3 id="blimey" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#blimey">Blimey</a></h3>
<p>To get a sense of what's truly possible, we can compare a similar service from the world leader in accessible, humane digital public services: <a href="https://gov.uk/">gov.uk, a.k.a., the UK Government Digital Service (GDS).</a></p>
<figure class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-govuk-uc.mp4" poster="https://infrequently.org/2024/08/the-landscape/benefitscal-vs-govuk-uc.webp" playsinline="" controls="" preload="metadata" style="aspect-ratio: 904 / 680;" loading="lazy">
</video>
<figcaption>
  gov.uk's Universal Credit page finishes loading before BenefitsCal's first loading screen even starts.
</figcaption>
</figure>  
<p>California <a href="https://www.theguardian.com/us-news/2018/may/04/california-economy-uk-fifth-largest">enjoys a larger GDP</a> and a reputation for technology excellence, and yet the UK consistently outperforms the Golden State's public services.</p>
<p>There are layered reasons for the UK's success:</p>
<ul>
<li><a href="https://www.gov.uk/service-manual/">GDS's Service Manual</a> is an enforceable guide for how government services should be built and delivered continuously. This liberates each department from reinventing processes or rediscovering how best to deliver through trial and error.</li>
<li>The GDS Service Manual <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement"><em>requires</em> progressive-enhancement.</a></li>
<li>Progressive Enhancement is baked into infrastructure and practice by patterns long documented in <a href="https://design-system.service.gov.uk/">the official GDS design system and reference implementation.</a></li>
<li>The parallel <a href="https://www.gov.uk/service-manual/service-standard">Service Standard</a> clearly articulates the egalitarian, open values that every delivery team is held to.</li>
<li>The Service Manual and Service Standard <a href="https://digitaltransformation.blog.gov.uk/2014/12/11/doing-the-right-things-in-the-right-way-agile-governance-at-home-office/#:~:text=5.%20Commercial%0AThe%20model%20of%20engaging%20with%20suppliers%20for%20delivery%20of%20digital%20services%20is%20different%20to%20traditional%20procurement%20models.%20GDS%20and%20the%20IPT%20Commercial%20team%20will%20work%20with%20appropriate%20stakeholders%20at%20the%20Home%20Office%20and%20with%20other%20assurance%20groups%20to%20raise%20awareness%20and%20adoption.">nearly shout</a> <em>&quot;do not write an omnibus contract!&quot;</em> if you can <a href="https://www.gov.uk/guidance/define-your-purchasing-strategy">read between the lines.</a> The interlocking processes, spend controls, and <a href="https://www.gov.uk/service-manual/agile-delivery/governance-principles-for-agile-service-delivery">agile activism</a> serve to <a href="https://www.gov.uk/government/publications/government-digital-strategy-annual-report-2014/government-digital-strategy-annual-report-2014#efficiency-savings">grind down</a> too-big-to-fail procurement into a fine powder, one contract at a time.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-services-schmervices-10" id="fnref-services-schmervices-10">10</a></sup></li>
</ul>
<p>The BenefitsCal omnishambles should trigger a fundamental rethink. Instead, the prime contractors have <a href="https://insider.govtech.com/california/news/gainwell-technologies-deloitte-get-nod-for-massive-calsaws-contract">just been awarded another $1.3BN</a> over a long time horizon. CalSAWS is now locked in an exclusive arrangement with the very folks that broke the site with JavaScript. Any attempt at fixing it now looks set to reward easily-avoided failure.</p>
<p>Too-big-to-fail procurement isn't just flourishing in California; it's thriving across public benefits application projects nationwide. No matter how badly service delivery is bungled, the money keeps flowing.</p>
<h3 id="javascript-masshattery" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#javascript-masshattery">JavaScript Masshattery</a></h3>
<p>CalSAWS is by no means alone.</p>
<p>For years, I have been <a href="https://infrequently.org/series/performance-inequality/">documenting the inequality exacerbating effects of JS-based frontend development</a> based on the parade of private-sector failures that cross my desk.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-disclosure-approach-11" id="fnref-disclosure-approach-11">11</a></sup></p>
<p>Over the past decade, those <a href="https://infrequently.org/2023/02/the-market-for-lemons/">failures have not elicited a change in tone or behaviour from advocates for frameworks</a>, but that <a href="https://web.dev/articles/inp">might be starting to change, at least for high-traffic commercial sites.</a></p>
<p><a href="https://web.dev/blog/inp-cwv-launch">Core Web Vitals</a> is creating pressure on slow sites that value search engine traffic. It's less clear what effect it will have on <a href="https://en.wikipedia.org/wiki/Monopsony">public-sector monopsonies.</a> The spread of unsafe-at-any-scale JavaScript frameworks into government is worrying as it's hard to imagine what will dislodge them. There's no comparison shopping for food stamps.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-gcf-sunset-12" id="fnref-gcf-sunset-12">12</a></sup></p>
<p>The Massachusetts <a href="https://www.mass.gov/orgs/executive-office-of-health-and-human-services">Executive Office of Health and Human Services</a> (EOHHS) seems to have fallen for JavaScript marketing hook, line, and sinker.</p>
<p><a href="https://dtaconnect.eohhs.mass.gov/">DTA Connect</a> is the result, a site so slow that it frequently takes me multiple attempts to load it from a Core i7 laptop attached to a gigabit network.</p>
<p>From the sort of device a smartphone-dependent mom might use to access the site? It's lookin' slow.</p>
<br style="display: none;" />
<figure style="max-width: 727px;" class="full_wide">
<video src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/timeline.mp4" poster="https://infrequently.org/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/screenShot.png" playsinline="" controls="" preload="metadata" style="aspect-ratio: 727 / 680;" loading="lazy">
</video>
<figcaption>
  Introducing the <em>Can You Hold Your Breath Longer Than It Takes to Load DTA Connect?</em> Challenge.
</figcaption>
</figure>
<p>I took this trace multiple times, as WebPageTest.org kept timing out. It's highly unusual for a site to take this long to load. Even tools <em>explicitly designed to emulate low-end devices and networks</em> needed coaxing to cope.</p>
<p>The underlying problem is by now familiar:</p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240804_AiDcFG_31Y-r%3A1-c%3A0&ival=100&end=visual" alt="You don't have to be a web performance expert to understand that <a href='https://www.webpagetest.org/breakdown.php?test=240804_AiDcFG_31Y&run=1&end=visual'>10.2MB of JS</a> is a tad much, particularly when it is served without compression." target="_blank"><picture style="--lqip: 166371" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240804_AiDcFG_31Y/runs/1/firstView/waterfall.png" alt="You don't have to be a web performance expert to understand that <a href='https://www.webpagetest.org/breakdown.php?test=240804_AiDcFG_31Y&run=1&end=visual'>10.2MB of JS</a> is a tad much, particularly when it is served without compression." style="aspect-ratio: 1012 / 482" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>You don't have to be a web performance expert to understand that <a href="https://www.webpagetest.org/breakdown.php?test=240804_AiDcFG_31Y&run=1&end=visual">10.2MB of JS</a> is a tad much, particularly when it is served without compression.</figcaption>      </figure><p></p>
<p>Vexingly, whatever hosting infrastructure Massachusetts uses for this project throttles serving to 750KB/s. This bandwidth restriction combines with server misconfigurations to ensure the site takes <em>forever</em> to load, even on fast machines.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-solidarity-13" id="fnref-solidarity-13">13</a></sup></p>
<p>It's a small mercy that DTA Connect sets caching headers, allowing repeat visits to load in &quot;only&quot; several seconds. Because of the SPA architecture, nothing renders until <em>all</em> the JavaScript gathers its thoughts at the speed of the local CPU.</p>
<p>The slower the device, the longer it takes.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-disaster-tourism-14" id="fnref-disaster-tourism-14">14</a></sup></p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240804_AiDcFG_31Y-r%3A1-c%3A1&ival=100&end=visual" alt="Even when everything is cached, DTA Connect takes multiple seconds to load on a low-end device owing to the time it takes to run this much JavaScript (yellow and grey in the 'Browser main thread' row)." target="_blank"><picture style="--lqip: -357661" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/dta_connect_repeat_view_waterfall.png" alt="Even when everything is cached, DTA Connect takes multiple seconds to load on a low-end device owing to the time it takes to run this much JavaScript (yellow and grey in the 'Browser main thread' row)." style="aspect-ratio: 1012 / 380" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Even when everything is cached, DTA Connect takes multiple seconds to load on a low-end device owing to the time it takes to run this much JavaScript (yellow and grey in the 'Browser main thread' row).</figcaption>      </figure><p></p>
<br style="display: none;" />
<wpt-filmstrip view="repeat" size="medium" waterfall="true" interval="500ms">
      <wpt-test label="DTA Connect, second load">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240804_AiDcFG_31Y","url":"https://dtaconnect.eohhs.mass.gov/","summary":"https://www.webpagetest.org/results.php?test=240804_AiDcFG_31Y","testUrl":"https://dtaconnect.eohhs.mass.gov/","location":"BOS_US_P01:Chrome","from":"Boston, Massachusetts, USA - <b>Chrome</b> - <b>Emulated Google Pixel 5</b> - <b>custom</b>","connectivity":"custom","bwDown":9000,"bwUp":9000,"latency":170,"plr":"0","shaperLimit":0,"mobile":1,"completed":1722753629,"testRuns":1,"testName":"240804_AiDcFG_31Y","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://dtaconnect.eohhs.mass.gov/"},"metrics":{"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.1804},{"start":"0.10","end":"0.25","density":0.0222},{"start":"0.25","density":0.7974}],"percentiles":{"p75":"0.79"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.6404},{"start":800,"end":1800,"density":0.2541},{"start":1800,"density":0.1055}],"percentiles":{"p75":1118}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.4643},{"start":1800,"end":3000,"density":0.2237},{"start":3000,"density":0.312}],"percentiles":{"p75":3932}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9621},{"start":100,"end":300,"density":0.0328},{"start":300,"density":0.005}],"percentiles":{"p75":13}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.8051},{"start":200,"end":500,"density":0.1614},{"start":500,"density":0.0335}],"percentiles":{"p75":165}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.5985},{"start":2500,"end":4000,"density":0.1472},{"start":4000,"density":0.2543}],"percentiles":{"p75":4105}},"navigation_types":{"fractions":{"restore":0,"back_forward":0.0531,"back_forward_cache":0.0891,"prerender":0.0104,"navigate":0.7747,"navigate_cache":0.0046,"reload":0.0681}},"round_trip_time":{"percentiles":{"p75":97}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":6},"lastDate":{"year":2024,"month":8,"day":2}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/details/","checklist":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/breakdown/","domains":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/domains/","screenShot":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240804_AiDcFG_31Y/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/04/AiDcFG/31Y/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/04/AiDcFG/31Y/1_connection.png","checklist":"https://www.webpagetest.org/result/24/08/04/AiDcFG/31Y/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240804_AiDcFG_31Y&file=1_screen.jpg"},"breakdown":{"html":{"bytes":1672,"bytesUncompressed":1672,"requests":1},"js":{"bytes":10218243,"bytesUncompressed":10971029,"requests":7},"css":{"bytes":214549,"bytesUncompressed":214549,"requests":1},"image":{"bytes":0,"bytesUncompressed":0,"requests":0},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":0,"bytesUncompressed":0,"requests":0},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":30,"bytesUncompressed":30,"requests":5}},"loadTime":31592,"docTime":31592,"fullyLoaded":31592,"firstPaint":30466,"firstContentfulPaint":31503.5,"lastVisualChange":30500,"visualComplete":30500,"visualComplete85":30500,"visualComplete90":30500,"visualComplete95":30500,"visualComplete99":30500,"SpeedIndex":30500,"TotalBlockingTime":0,"layoutShifts":[],"lcps":[],"navigationStart":110,"fetchStart":93,"domLoading":1081,"responseEnd":1074,"domInteractive":111,"domContentLoadedEventStart":111,"domContentLoadedEventEnd":111,"domComplete":111,"unloadEventStart":1079,"unloadEventEnd":1079,"markAsMainFrame":1080,"commitNavigationEnd":1080,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":30500,"image":"filmstrip/ms_030500.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":393,"height":720,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":393,"height":720}},"filmstripImageAspectRatio":"393 / 720","gifImageData":{"format":"gif","width":728,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":335,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":728,"height":680}},"gifImageAspectRatio":"728 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>A page this simple, served entirely from cache, should render in much less than a second on a device like this.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-ten-ex-15" id="fnref-ten-ex-15">15</a></sup></p>
<h3 id="maryland-enters-the-chat" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#maryland-enters-the-chat">Maryland Enters The Chat</a></h3>
<p>The correlation between states procuring <em>extremely</em> complex, newfangled JavaScript web apps and fumbling basic web serving is surprisingly high.</p>
<p>Case in point, the residents of Maryland wait <em>seconds</em> on a slow connection for megabytes of uncompressed JavaScript, thanks to the Angular 9-based SPA architecture of <a href="https://xn--mymdthink-g69dbbbbbbbb.xn--maryland-pl3dbbbbbbbb.xn--gov-4m0abbb/">myMDTHINK.</a><sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-grinding-16" id="fnref-grinding-16">16</a></sup></p>
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" interval="500ms">
      <wpt-test label="myMDTHINK">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240805_BiDc66_389","url":"https://mymdthink.maryland.gov/","summary":"https://www.webpagetest.org/results.php?test=240805_BiDc66_389","testUrl":"https://mymdthink.maryland.gov/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722829716,"testRuns":3,"testName":"240805_BiDc66_389","optimizedImages":true,"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240805_BiDc66_389/1/details/","checklist":"https://www.webpagetest.org/result/240805_BiDc66_389/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240805_BiDc66_389/1/breakdown/","domains":"https://www.webpagetest.org/result/240805_BiDc66_389/1/domains/","screenShot":"https://www.webpagetest.org/result/240805_BiDc66_389/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240805_BiDc66_389/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240805_BiDc66_389/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240805_BiDc66_389/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240805_BiDc66_389/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/05/BiDc66/389/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/05/BiDc66/389/1_connection.png","checklist":"https://www.webpagetest.org/result/24/08/05/BiDc66/389/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240805_BiDc66_389&file=1_screen.jpg"},"breakdown":{"html":{"bytes":2869,"bytesUncompressed":2731,"requests":3},"js":{"bytes":5901221,"bytesUncompressed":6422069,"requests":14},"css":{"bytes":274539,"bytesUncompressed":322963,"requests":5},"image":{"bytes":1752734,"bytesUncompressed":1755619,"requests":22},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":1139604,"bytesUncompressed":1139604,"requests":6},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":4103,"bytesUncompressed":4103,"requests":5}},"loadTime":15116,"docTime":15116,"fullyLoaded":15428,"firstPaint":11040,"firstContentfulPaint":11040,"firstMeaningfulPaint":12978,"lastVisualChange":13600,"visualComplete":13600,"visualComplete85":13500,"visualComplete90":13500,"visualComplete95":13600,"visualComplete99":13600,"SpeedIndex":12500,"TotalBlockingTime":942,"layoutShifts":[11804,13270],"lcps":[11230],"navigationStart":93,"redirectStart":55,"domLoading":1174,"responseEnd":1162,"domInteractive":3517,"domContentLoadedEventStart":10752,"domContentLoadedEventEnd":10770,"domComplete":15116,"redirectEnd":971,"fetchStart":971,"unloadEventStart":1173,"unloadEventEnd":1173,"markAsMainFrame":1173,"commitNavigationEnd":1174,"firstMeaningfulPaintCandidate":12978,"firstImagePaint":11040,"loadEventStart":15116,"loadEventEnd":15154,"LargestTextPaint":13430,"LargestImagePaint":11230,"LargestContentfulPaint":11230,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":11200,"image":"filmstrip/ms_011200.jpg","VisuallyComplete":41},{"time":12000,"image":"filmstrip/ms_012000.jpg","VisuallyComplete":39},{"time":13100,"image":"filmstrip/ms_013100.jpg","VisuallyComplete":38},{"time":13200,"image":"filmstrip/ms_013200.jpg","VisuallyComplete":55},{"time":13300,"image":"filmstrip/ms_013300.jpg","VisuallyComplete":80},{"time":13500,"image":"filmstrip/ms_013500.jpg","VisuallyComplete":90},{"time":13600,"image":"filmstrip/ms_013600.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":166,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>Shockingly, Maryland's myMDTHINK loads its 5.2MB of critical-path JS without gzip.</p>
<p>American legislators like to <a href="https://en.wikipedia.org/wiki/Means_test">means test</a> public services. In that spirit, perhaps browsers should decline to load multiple megabytes of JavaScript from developers that feel so well-to-do they can afford to skip zipping content for the benefit of others.</p>
<h3 id="chattanooga-chug-chug" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#chattanooga-chug-chug">Chattanooga Chug Chug</a></h3>
<p>Tennessee, a state with <a href="https://tennesseelookout.com/2023/09/26/census-data-shows-tennessee-poverty-rates-fell-but-stagnated-compared-to-the-national-average/">higher-than-average child poverty,</a> is at least using JavaScript to degrade the accessibility of its public services in unique ways.</p>
<p>Instead of misconfiguring web servers, The Volunteer State uses Angular to <em>synchronously</em> fetch JSON files that define the eventual UI in an <code>onload</code> event handler.</p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_BiDcRJ_3D0-r%3A1-c%3A0&ival=100&end=visual" alt="The enormous purple line represents four full seconds of main thread unresponsiveness." target="_blank"><picture style="--lqip: 165610" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/firstView/waterfall.png" alt="The enormous purple line represents four full seconds of main thread unresponsiveness." style="aspect-ratio: 1012 / 1757" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>The enormous purple line represents four full seconds of main thread unresponsiveness.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_BiDcRJ_3D0-r%3A1-c%3A1&ival=100&end=visual" alt="It's little better on second visit, owing to the CPU-bound nature of the problem." target="_blank"><picture style="--lqip: -423190" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_BiDcRJ_3D0/runs/1/repeatView/waterfall.png" alt="It's little better on second visit, owing to the CPU-bound nature of the problem." style="aspect-ratio: 1012 / 720" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>It's little better on second visit, owing to the CPU-bound nature of the problem.</figcaption>      </figure><p></p>
<p>Needless to say, this does not read to the trained eye as competent work.</p>
<!-- 240805_BiDcRJ_3D0 -->
<h3 id="snap%3F-in-jersey%3F-fuhgeddaboudit" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#snap%3F-in-jersey%3F-fuhgeddaboudit">SNAP? In Jersey? Fuhgeddaboudit</a></h3>
<p>New Jersey's <a href="https://www.mynjhelps.gov/home">MyNJHelps.gov</a> (yes, that's the actual name) mixes the old-timey slowness of multiple 4.5MB background stock photos with a nu-skool render-blocking Angular SPA payload that's 2.2MB on the wire (15.7MB unzipped), leading to first load times north of 20 seconds.</p>
<p>Despite serving the oversized JavaScript payload relatively well, the script itself is so slow that repeat visits take nearly 13 seconds to display fully:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" interval="500ms">
      <wpt-test label="MyNJHelps.gov, first view">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240805_AiDc30_3FM","url":"https://www.mynjhelps.gov/home","summary":"https://www.webpagetest.org/results.php?test=240805_AiDc30_3FM","testUrl":"https://www.mynjhelps.gov/home","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722833137,"testRuns":3,"testName":"240805_AiDc30_3FM","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://www.mynjhelps.gov/home"},"metrics":{"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.4748},{"start":1800,"end":3000,"density":0.2204},{"start":3000,"density":0.3048}],"percentiles":{"p75":3691}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9601},{"start":100,"end":300,"density":0.022},{"start":300,"density":0.018}],"percentiles":{"p75":18}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.6855},{"start":200,"end":500,"density":0.2329},{"start":500,"density":0.0816}],"percentiles":{"p75":247}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.4178},{"start":2500,"end":4000,"density":0.2338},{"start":4000,"density":0.3484}],"percentiles":{"p75":5324}},"round_trip_time":{"percentiles":{"p75":116}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.2584},{"start":"0.10","end":"0.25","density":0.4067},{"start":"0.25","density":0.3349}],"percentiles":{"p75":"0.26"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.9188},{"start":800,"end":1800,"density":0.0569},{"start":1800,"density":0.0243}],"percentiles":{"p75":392}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":7},"lastDate":{"year":2024,"month":8,"day":3}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/details/","checklist":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/breakdown/","domains":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/domains/","screenShot":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_connection.png","checklist":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240805_AiDc30_3FM&file=1_screen.jpg"},"breakdown":{"html":{"bytes":791,"bytesUncompressed":2133,"requests":1},"js":{"bytes":2220735,"bytesUncompressed":15724857,"requests":12},"css":{"bytes":61238,"bytesUncompressed":494014,"requests":2},"image":{"bytes":18717521,"bytesUncompressed":18912947,"requests":15},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":599568,"bytesUncompressed":599568,"requests":8},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":105905,"bytesUncompressed":3833780,"requests":16}},"loadTime":33832,"docTime":33832,"fullyLoaded":33832,"firstPaint":9706,"firstContentfulPaint":9706,"lastVisualChange":24500,"visualComplete":24500,"visualComplete85":16400,"visualComplete90":22700,"visualComplete95":23200,"visualComplete99":23200,"SpeedIndex":15054,"TotalBlockingTime":2347,"layoutShifts":[9778,10971,12859,16028],"lcps":[16002],"navigationStart":66,"fetchStart":20,"domLoading":821,"responseEnd":811,"domInteractive":2460,"domContentLoadedEventStart":9667,"domContentLoadedEventEnd":9667,"domComplete":68,"unloadEventStart":820,"unloadEventEnd":820,"markAsMainFrame":820,"commitNavigationEnd":820,"firstMeaningfulPaintCandidate":15504,"firstImagePaint":10301,"LargestTextPaint":16308,"LargestImagePaint":16002,"LargestContentfulPaint":16002,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":9800,"image":"filmstrip/ms_009800.jpg","VisuallyComplete":10},{"time":10000,"image":"filmstrip/ms_010000.jpg","VisuallyComplete":10},{"time":10400,"image":"filmstrip/ms_010400.jpg","VisuallyComplete":14},{"time":10500,"image":"filmstrip/ms_010500.jpg","VisuallyComplete":14},{"time":10700,"image":"filmstrip/ms_010700.jpg","VisuallyComplete":14},{"time":10900,"image":"filmstrip/ms_010900.jpg","VisuallyComplete":14},{"time":11100,"image":"filmstrip/ms_011100.jpg","VisuallyComplete":16},{"time":11200,"image":"filmstrip/ms_011200.jpg","VisuallyComplete":16},{"time":11300,"image":"filmstrip/ms_011300.jpg","VisuallyComplete":16},{"time":11500,"image":"filmstrip/ms_011500.jpg","VisuallyComplete":0},{"time":12800,"image":"filmstrip/ms_012800.jpg","VisuallyComplete":52},{"time":13100,"image":"filmstrip/ms_013100.jpg","VisuallyComplete":51},{"time":14800,"image":"filmstrip/ms_014800.jpg","VisuallyComplete":57},{"time":15900,"image":"filmstrip/ms_015900.jpg","VisuallyComplete":57},{"time":16100,"image":"filmstrip/ms_016100.jpg","VisuallyComplete":58},{"time":16400,"image":"filmstrip/ms_016400.jpg","VisuallyComplete":88},{"time":22700,"image":"filmstrip/ms_022700.jpg","VisuallyComplete":91},{"time":23200,"image":"filmstrip/ms_023200.jpg","VisuallyComplete":99},{"time":23500,"image":"filmstrip/ms_023500.jpg","VisuallyComplete":99},{"time":24500,"image":"filmstrip/ms_024500.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":275,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
      <wpt-test label="MyNJHelps.gov, repeat view">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240805_AiDc30_3FM","url":"https://www.mynjhelps.gov/home","summary":"https://www.webpagetest.org/results.php?test=240805_AiDc30_3FM","testUrl":"https://www.mynjhelps.gov/home","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722833137,"testRuns":3,"testName":"240805_AiDc30_3FM","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://www.mynjhelps.gov/home"},"metrics":{"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.4748},{"start":1800,"end":3000,"density":0.2204},{"start":3000,"density":0.3048}],"percentiles":{"p75":3691}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9601},{"start":100,"end":300,"density":0.022},{"start":300,"density":0.018}],"percentiles":{"p75":18}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.6855},{"start":200,"end":500,"density":0.2329},{"start":500,"density":0.0816}],"percentiles":{"p75":247}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.4178},{"start":2500,"end":4000,"density":0.2338},{"start":4000,"density":0.3484}],"percentiles":{"p75":5324}},"round_trip_time":{"percentiles":{"p75":116}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.2584},{"start":"0.10","end":"0.25","density":0.4067},{"start":"0.25","density":0.3349}],"percentiles":{"p75":"0.26"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.9188},{"start":800,"end":1800,"density":0.0569},{"start":1800,"density":0.0243}],"percentiles":{"p75":392}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":7},"lastDate":{"year":2024,"month":8,"day":3}}},"view":"repeatView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/details/cached/","checklist":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/performance_optimization/cached/","breakdown":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/breakdown/cached/","domains":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/domains/cached/","screenShot":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/screen_shot/cached/","opportunities":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1/experiments/cached/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_Cached_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_Cached_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240805_AiDc30_3FM/1_Cached_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_Cached_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_Cached_connection.png","checklist":"https://www.webpagetest.org/result/24/08/05/AiDc30/3FM/1_Cached_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240805_AiDc30_3FM&file=1_Cached_screen.jpg"},"breakdown":{"html":{"bytes":0,"bytesUncompressed":0,"requests":0},"js":{"bytes":52228,"bytesUncompressed":191967,"requests":3},"css":{"bytes":0,"bytesUncompressed":0,"requests":0},"image":{"bytes":0,"bytesUncompressed":0,"requests":0},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":0,"bytesUncompressed":0,"requests":0},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":89512,"bytesUncompressed":3782686,"requests":12}},"loadTime":13439,"docTime":13439,"fullyLoaded":15219,"firstPaint":8035,"firstContentfulPaint":8035,"firstMeaningfulPaint":12829,"lastVisualChange":15700,"visualComplete":15700,"visualComplete85":15700,"visualComplete90":15700,"visualComplete95":15700,"visualComplete99":15700,"SpeedIndex":13639,"TotalBlockingTime":1463,"layoutShifts":[9239,15356],"lcps":[12829],"navigationStart":91,"fetchStart":50,"responseEnd":92,"domLoading":114,"domInteractive":3910,"domContentLoadedEventStart":7608,"domContentLoadedEventEnd":7647,"domComplete":13438,"unloadEventStart":108,"unloadEventEnd":108,"markAsMainFrame":108,"commitNavigationEnd":113,"firstImagePaint":8035,"firstMeaningfulPaintCandidate":12829,"loadEventStart":13438,"loadEventEnd":13518,"LargestTextPaint":15427,"LargestImagePaint":12829,"LargestContentfulPaint":12829,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":8300,"image":"filmstrip/ms_008300.jpg","VisuallyComplete":18},{"time":8400,"image":"filmstrip/ms_008400.jpg","VisuallyComplete":18},{"time":8600,"image":"filmstrip/ms_008600.jpg","VisuallyComplete":18},{"time":8800,"image":"filmstrip/ms_008800.jpg","VisuallyComplete":18},{"time":9000,"image":"filmstrip/ms_009000.jpg","VisuallyComplete":18},{"time":9100,"image":"filmstrip/ms_009100.jpg","VisuallyComplete":18},{"time":9300,"image":"filmstrip/ms_009300.jpg","VisuallyComplete":18},{"time":9400,"image":"filmstrip/ms_009400.jpg","VisuallyComplete":18},{"time":9600,"image":"filmstrip/ms_009600.jpg","VisuallyComplete":17},{"time":9700,"image":"filmstrip/ms_009700.jpg","VisuallyComplete":17},{"time":9900,"image":"filmstrip/ms_009900.jpg","VisuallyComplete":17},{"time":10000,"image":"filmstrip/ms_010000.jpg","VisuallyComplete":17},{"time":10100,"image":"filmstrip/ms_010100.jpg","VisuallyComplete":0},{"time":13100,"image":"filmstrip/ms_013100.jpg","VisuallyComplete":67},{"time":13200,"image":"filmstrip/ms_013200.jpg","VisuallyComplete":67},{"time":15700,"image":"filmstrip/ms_015700.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":187,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>What Qualcomm giveth, Angular taketh away.</p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_AiDc30_3FM-r%3A1-c%3A0,240805_AiDc30_3FM-r%3A1-c%3A1&ival=100&end=visual" alt="Despite almost perfect caching, repeat visits take more than 10 seconds to render thanks to a slow JavaScript payload." target="_blank"><picture style="--lqip: 166627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_AiDc30_3FM/runs/1/repeatView/waterfall.png" alt="Despite almost perfect caching, repeat visits take more than 10 seconds to render thanks to a slow JavaScript payload." style="aspect-ratio: 1012 / 499" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Despite almost perfect caching, repeat visits take more than 10 seconds to render thanks to a slow JavaScript payload.</figcaption>      </figure><p></p>
<p>Debugging the pathologies of this specific page are beyond the scope of this post, but it is a mystery how New Jersey managed to deploy an application that triggers a <code>debugger;</code> statement on every page load with DevTools open whilst also serving a 1.8MB (13.8MB unzipped) <code>vendor.js</code> file with <em>no minification of any sort</em>.</p>
<p>One wonders if anyone involved in the deployment of this site are developers, and if not, how it exists.</p>
<h3 id="hoosier-hospitality" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#hoosier-hospitality">Hoosier Hospitality</a></h3>
<p>Nearly half of the 15 seconds required to load Indiana's <a href="https://fssabenefits.in.gov/bp/">FSSA Benefits Portal</a> is consumed by a mountain of main-thread time burned in its <a href="https://www.webpagetest.org/result/240805_AiDcSP_42J/3/breakdown/">4.2MB (16MB unzipped)</a> Angular 8 SPA bundle.</p>
<p>Combined with a failure to set appropriate caching headers, both timelines look identically terrible:</p>
<br style="display: none;" />
<wpt-filmstrip size="medium" waterfall="true" interval="500ms">
      <wpt-test label="IN's FSSA BP, first view">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240805_AiDcSP_42J","url":"https://fssabenefits.in.gov/bp/","summary":"https://www.webpagetest.org/results.php?test=240805_AiDcSP_42J","testUrl":"https://fssabenefits.in.gov/bp/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722836193,"testRuns":3,"testName":"240805_AiDcSP_42J","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://fssabenefits.in.gov/bp/"},"metrics":{"round_trip_time":{"percentiles":{"p75":117}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.1366},{"start":"0.10","end":"0.25","density":0.4147},{"start":"0.25","density":0.4487}],"percentiles":{"p75":"0.39"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8358},{"start":800,"end":1800,"density":0.1082},{"start":1800,"density":0.056}],"percentiles":{"p75":579}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.1174},{"start":1800,"end":3000,"density":0.3035},{"start":3000,"density":0.5791}],"percentiles":{"p75":5777}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9646},{"start":100,"end":300,"density":0.0242},{"start":300,"density":0.0112}],"percentiles":{"p75":13}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.4024},{"start":200,"end":500,"density":0.3779},{"start":500,"density":0.2198}],"percentiles":{"p75":452}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.2853},{"start":2500,"end":4000,"density":0.2904},{"start":4000,"density":0.4243}],"percentiles":{"p75":5759}},"navigation_types":{"fractions":{"reload":0.2757,"restore":0,"back_forward":0.0251,"back_forward_cache":0,"prerender":0.0134,"navigate":0.6858,"navigate_cache":0}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":7},"lastDate":{"year":2024,"month":8,"day":3}}},"view":"firstView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/details/","checklist":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/performance_optimization/","breakdown":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/breakdown/","domains":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/domains/","screenShot":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/screen_shot/","opportunities":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/experiments/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_connection.png","checklist":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240805_AiDcSP_42J&file=1_screen.jpg"},"breakdown":{"html":{"bytes":7102,"bytesUncompressed":25944,"requests":2},"js":{"bytes":4208863,"bytesUncompressed":16033168,"requests":7},"css":{"bytes":160882,"bytesUncompressed":890759,"requests":6},"image":{"bytes":0,"bytesUncompressed":0,"requests":0},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":168864,"bytesUncompressed":168864,"requests":3},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":82869,"bytesUncompressed":187249,"requests":11}},"loadTime":14739,"docTime":14739,"fullyLoaded":15724,"firstPaint":2902,"firstContentfulPaint":12311,"firstMeaningfulPaint":12311,"lastVisualChange":18700,"visualComplete":18700,"visualComplete85":13700,"visualComplete90":13700,"visualComplete95":13900,"visualComplete99":18700,"SpeedIndex":13722,"TotalBlockingTime":1316,"layoutShifts":[12886,13415,17754],"lcps":[12311],"navigationStart":59,"fetchStart":25,"domLoading":988,"responseEnd":987,"domInteractive":12907,"domContentLoadedEventStart":13129,"domContentLoadedEventEnd":13134,"domComplete":14737,"unloadEventStart":984,"unloadEventEnd":984,"markAsMainFrame":984,"commitNavigationEnd":987,"firstMeaningfulPaintCandidate":12311,"firstImagePaint":12311,"loadEventStart":14738,"loadEventEnd":14738,"LargestTextPaint":12311,"LargestImagePaint":12311,"LargestContentfulPaint":12311,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":12300,"image":"filmstrip/ms_012300.jpg","VisuallyComplete":23},{"time":12700,"image":"filmstrip/ms_012700.jpg","VisuallyComplete":23},{"time":13000,"image":"filmstrip/ms_013000.jpg","VisuallyComplete":6},{"time":13100,"image":"filmstrip/ms_013100.jpg","VisuallyComplete":6},{"time":13200,"image":"filmstrip/ms_013200.jpg","VisuallyComplete":6},{"time":13300,"image":"filmstrip/ms_013300.jpg","VisuallyComplete":6},{"time":13400,"image":"filmstrip/ms_013400.jpg","VisuallyComplete":6},{"time":13500,"image":"filmstrip/ms_013500.jpg","VisuallyComplete":6},{"time":13600,"image":"filmstrip/ms_013600.jpg","VisuallyComplete":6},{"time":13700,"image":"filmstrip/ms_013700.jpg","VisuallyComplete":93},{"time":13800,"image":"filmstrip/ms_013800.jpg","VisuallyComplete":93},{"time":13900,"image":"filmstrip/ms_013900.jpg","VisuallyComplete":95},{"time":14000,"image":"filmstrip/ms_014000.jpg","VisuallyComplete":96},{"time":17800,"image":"filmstrip/ms_017800.jpg","VisuallyComplete":92},{"time":18000,"image":"filmstrip/ms_018000.jpg","VisuallyComplete":93},{"time":18100,"image":"filmstrip/ms_018100.jpg","VisuallyComplete":94},{"time":18200,"image":"filmstrip/ms_018200.jpg","VisuallyComplete":95},{"time":18300,"image":"filmstrip/ms_018300.jpg","VisuallyComplete":95},{"time":18400,"image":"filmstrip/ms_018400.jpg","VisuallyComplete":95},{"time":18500,"image":"filmstrip/ms_018500.jpg","VisuallyComplete":95},{"time":18600,"image":"filmstrip/ms_018600.jpg","VisuallyComplete":95},{"time":18700,"image":"filmstrip/ms_018700.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":217,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
      <wpt-test label="IN's FSSA BP, repeat view">        <script type="text/json" dir="/2024/08/the-landscape/wpt-traces/">          {"id":"240805_AiDcSP_42J","url":"https://fssabenefits.in.gov/bp/","summary":"https://www.webpagetest.org/results.php?test=240805_AiDcSP_42J","testUrl":"https://fssabenefits.in.gov/bp/","location":"IAD_US_01:Chrome","from":"Dulles, Virginia USA - <b>Chrome</b> - <b>Emulated Motorola G (gen 4)</b> - <b>4G</b>","connectivity":"4G","bwDown":9000,"bwUp":9000,"latency":170,"plr":null,"shaperLimit":0,"mobile":1,"completed":1722836193,"testRuns":3,"testName":"240805_AiDcSP_42J","optimizedImages":true,"crux":{"key":{"formFactor":"PHONE","url":"https://fssabenefits.in.gov/bp/"},"metrics":{"round_trip_time":{"percentiles":{"p75":117}},"cumulative_layout_shift":{"histogram":[{"start":"0.00","end":"0.10","density":0.1366},{"start":"0.10","end":"0.25","density":0.4147},{"start":"0.25","density":0.4487}],"percentiles":{"p75":"0.39"}},"experimental_time_to_first_byte":{"histogram":[{"start":0,"end":800,"density":0.8358},{"start":800,"end":1800,"density":0.1082},{"start":1800,"density":0.056}],"percentiles":{"p75":579}},"first_contentful_paint":{"histogram":[{"start":0,"end":1800,"density":0.1174},{"start":1800,"end":3000,"density":0.3035},{"start":3000,"density":0.5791}],"percentiles":{"p75":5777}},"first_input_delay":{"histogram":[{"start":0,"end":100,"density":0.9646},{"start":100,"end":300,"density":0.0242},{"start":300,"density":0.0112}],"percentiles":{"p75":13}},"interaction_to_next_paint":{"histogram":[{"start":0,"end":200,"density":0.4024},{"start":200,"end":500,"density":0.3779},{"start":500,"density":0.2198}],"percentiles":{"p75":452}},"largest_contentful_paint":{"histogram":[{"start":0,"end":2500,"density":0.2853},{"start":2500,"end":4000,"density":0.2904},{"start":4000,"density":0.4243}],"percentiles":{"p75":5759}},"navigation_types":{"fractions":{"reload":0.2757,"restore":0,"back_forward":0.0251,"back_forward_cache":0,"prerender":0.0134,"navigate":0.6858,"navigate_cache":0}}},"collectionPeriod":{"firstDate":{"year":2024,"month":7,"day":7},"lastDate":{"year":2024,"month":8,"day":3}}},"view":"repeatView","run":"1","pages":{"details":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/details/cached/","checklist":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/performance_optimization/cached/","breakdown":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/breakdown/cached/","domains":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/domains/cached/","screenShot":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/screen_shot/cached/","opportunities":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1/experiments/cached/"},"thumbnails":{"waterfall":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_Cached_waterfall_thumb.png","checklist":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_Cached_optimization_thumb.png","screenShot":"https://www.webpagetest.org/result/240805_AiDcSP_42J/1_Cached_screen_thumb.png"},"images":{"waterfall":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_Cached_waterfall.png","connectionView":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_Cached_connection.png","checklist":"https://www.webpagetest.org/result/24/08/05/AiDcSP/42J/1_Cached_optimization.png","screenShot":"https://www.webpagetest.org/getfile.php?test=240805_AiDcSP_42J&file=1_Cached_screen.jpg"},"breakdown":{"html":{"bytes":7126,"bytesUncompressed":25944,"requests":2},"js":{"bytes":4208811,"bytesUncompressed":16033168,"requests":7},"css":{"bytes":157674,"bytesUncompressed":831192,"requests":4},"image":{"bytes":0,"bytesUncompressed":0,"requests":0},"flash":{"bytes":0,"bytesUncompressed":0,"requests":0},"font":{"bytes":77160,"bytesUncompressed":77160,"requests":1},"video":{"bytes":0,"bytesUncompressed":0,"requests":0},"other":{"bytes":82877,"bytesUncompressed":187249,"requests":11}},"loadTime":14906,"docTime":14906,"fullyLoaded":15872,"firstPaint":2966,"firstContentfulPaint":12333,"firstMeaningfulPaint":12333,"lastVisualChange":18900,"visualComplete":18900,"visualComplete85":13700,"visualComplete90":13700,"visualComplete95":13700,"visualComplete99":18900,"SpeedIndex":13733,"TotalBlockingTime":811,"layoutShifts":[12560,13004,17912],"lcps":[12333],"navigationStart":122,"fetchStart":82,"domLoading":1040,"responseEnd":1034,"domInteractive":13066,"domContentLoadedEventStart":13218,"domContentLoadedEventEnd":13227,"domComplete":14904,"unloadEventStart":1039,"unloadEventEnd":1039,"markAsMainFrame":1039,"commitNavigationEnd":1040,"firstMeaningfulPaintCandidate":12333,"firstImagePaint":12333,"loadEventStart":14906,"loadEventEnd":14906,"LargestTextPaint":12333,"LargestImagePaint":12333,"LargestContentfulPaint":12333,"waterfall":"waterfall.png","connectionView":"connectionView.png","checklist":"checklist.png","screenShot":"screenShot.png","filmstripFrames":[{"time":0,"image":"filmstrip/ms_000000.jpg","VisuallyComplete":0},{"time":12400,"image":"filmstrip/ms_012400.jpg","VisuallyComplete":23},{"time":12600,"image":"filmstrip/ms_012600.jpg","VisuallyComplete":23},{"time":12800,"image":"filmstrip/ms_012800.jpg","VisuallyComplete":23},{"time":13100,"image":"filmstrip/ms_013100.jpg","VisuallyComplete":6},{"time":13200,"image":"filmstrip/ms_013200.jpg","VisuallyComplete":6},{"time":13300,"image":"filmstrip/ms_013300.jpg","VisuallyComplete":6},{"time":13400,"image":"filmstrip/ms_013400.jpg","VisuallyComplete":6},{"time":13500,"image":"filmstrip/ms_013500.jpg","VisuallyComplete":6},{"time":13600,"image":"filmstrip/ms_013600.jpg","VisuallyComplete":6},{"time":13700,"image":"filmstrip/ms_013700.jpg","VisuallyComplete":95},{"time":13800,"image":"filmstrip/ms_013800.jpg","VisuallyComplete":95},{"time":13900,"image":"filmstrip/ms_013900.jpg","VisuallyComplete":95},{"time":14000,"image":"filmstrip/ms_014000.jpg","VisuallyComplete":95},{"time":14100,"image":"filmstrip/ms_014100.jpg","VisuallyComplete":96},{"time":18000,"image":"filmstrip/ms_018000.jpg","VisuallyComplete":92},{"time":18200,"image":"filmstrip/ms_018200.jpg","VisuallyComplete":93},{"time":18300,"image":"filmstrip/ms_018300.jpg","VisuallyComplete":94},{"time":18400,"image":"filmstrip/ms_018400.jpg","VisuallyComplete":95},{"time":18500,"image":"filmstrip/ms_018500.jpg","VisuallyComplete":95},{"time":18600,"image":"filmstrip/ms_018600.jpg","VisuallyComplete":95},{"time":18700,"image":"filmstrip/ms_018700.jpg","VisuallyComplete":95},{"time":18800,"image":"filmstrip/ms_018800.jpg","VisuallyComplete":95},{"time":18900,"image":"filmstrip/ms_018900.jpg","VisuallyComplete":100}],"filmstripImageData":{"format":"jpeg","width":360,"height":510,"space":"b-w","channels":1,"density":72,"isProgressive":false,"hasAlpha":false,"autoOrient":{"width":360,"height":510}},"filmstripImageAspectRatio":"360 / 510","gifImageData":{"format":"gif","width":520,"height":680,"space":"srgb","channels":4,"isPalette":true,"bitsPerSample":8,"paletteBitDepth":8,"pages":219,"loop":0,"background":{"r":0,"g":255,"b":0},"autoOrient":{"width":520,"height":680}},"gifImageAspectRatio":"520 / 680"}        </script>      </wpt-test>    
</wpt-filmstrip>
<p>Can you spot the difference?</p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_AiDcSP_42J-r%3A1-c%3A0&ival=100&end=visual" alt="First view." target="_blank"><picture style="--lqip: 166627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/firstView/waterfall.png" alt="First view." style="aspect-ratio: 1012 / 754" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>First view.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://www.webpagetest.org/video/compare.php?tests=240805_AiDcSP_42J-r%3A1-c%3A1&ival=100&end=visual" alt="Repeat visit." target="_blank"><picture style="--lqip: 166627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/wpt-traces/240805_AiDcSP_42J/runs/1/repeatView/waterfall.png" alt="Repeat visit." style="aspect-ratio: 1012 / 669" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Repeat visit.</figcaption>      </figure><p></p>
<p>Neither can I.</p>
<p>Entirely defeating browser caching in 2024 takes serious effort, but Indiana has pulled it off.</p>
<h2 id="deep-breaths" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/object-lesson/#deep-breaths">Deep Breaths</a></h2>
<p>The good news is that not every digital US public benefits portal has been so thoroughly degraded by JavaScript frameworks. Code for America's <a href="https://codeforamerica.org/explore/benefits-enrollment-field-guide/">2023 Benefits Enrolment Field Guide study</a> helpfully ran numbers on many benefits portals, and a spot check shows that those that looked fine last year are generally in decent shape today.</p>
<p>Still, considering just the states examined in this post, one in five US residents will hit underperforming services, should they need them.</p>
<p>None of these sites need to be user hostile. All of them would be significantly faster if states abandoned client-side rendering, along with the legacy JavaScript frameworks (React, Angular, etc.) built to enable the SPA model.</p>
<p>GetCalFresh, Wisconsin, and the UK demonstrate a better future is possible today. To deliver that better future and make it stick, organisations need to learn the limits of their carrying capacity for complexity. They also need to study how different architectures fail in order to select solutions that degrade more gracefully.</p>
<p><em><strong>Next:</strong> <a href="https://infrequently.org/2024/08/caprock/">Caprock: Development without constraints isn't engineering.</a></em></p>
<div style="font-size: 1rem;">
<p><em>Thanks to <a href="https://polotek.net/">Marco Rogers</a>, and <a href="https://fberriman.com/">Frances Berriman</a> for their encouragement in making this piece a series and for their thoughtful feedback on drafts.</em></p>
<p><em>If you work on a site discussed in this post, I offer (free) consulting to public sector services. <a href="https://infrequently.org/about-me/">Please get in touch</a>.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-receipts-1" class="footnote-item"><p>The JavaScript required to render <em>anything</em> on BenefitsCal embodies nearly every anti-pattern popularised (sometimes inadvertently, but no less predictably) by JavaScript influencers over the past decade, along with the most common pathologies of NPM-based, React-flavoured frontend development.</p>
<p>A perusal of the code reveals:</p>
<ul>
<li>Multiple reactive systems, namely React, Vue, and RxJS.</li>
<li>&quot;Client-side routing&quot; metadata <em>for the entire site</em> bundled into the main script.</li>
<li>React components for all UI surfaces across the site, including:
<ul>
<li>Components for every form, frontloaded. No forms are displayed on the home page.</li>
<li>An entire <a href="https://draftjs.org/">rich-text editing library.</a> No rich-text editing occurs on the home page.</li>
<li>A <a href="https://www.chartjs.org/">complete charting library.</a> No charts appear on the home page.</li>
<li>Sizable custom scrolling and <a href="https://github.com/atlassian/react-beautiful-dnd/tree/master">drag-and-drop libraries.</a> No custom scrolling or drag-and-drop interactions occur on the home page.</li>
</ul>
</li>
<li>A so-called &quot;CSS-in-JS&quot; library <a href="https://github.com/emotion-js/emotion/blob/main/docs/extract-static.mdx">that does not support compilation to an external stylesheet.</a> This is categorically the slowest and least efficient way to style web-based UIs. On its own, it would justify remediation work.</li>
<li>Unnecessary <a href="https://www.smashingmagazine.com/2018/10/smart-bundling-legacy-code-browsers/">polyfills and transpilation overhead,</a> including:
<ul>
<li><a href="https://caniuse.com/es6-class"><code>class</code> syntax</a> transpilation.</li>
<li><a href="https://caniuse.com/es6-generators">Generator function</a> transpilation and polyfills <em>independently added to dozens of files.</em></li>
<li><a href="https://caniuse.com/mdn-javascript_builtins_iterator">Iterator transpilation</a> and polyfills.</li>
<li>Standard library polyfills, including obsolete userland implementations of <a href="https://caniuse.com/mdn-javascript_builtins_arraybuffer"><code>ArrayBuffer</code>,</a> <a href="https://caniuse.com/mdn-javascript_builtins_object_assign"><code>Object.assign()</code></a> and repeated inlining of polyfills for many others, including a litany of outdated TypeScript-generated polyfills, bloating every file.</li>
<li>Obselete DOM polyfills, including a copy of Sizzle to provide emulation for <a href="https://caniuse.com/mdn-api_element_queryselectorall"><code>document.querySelectorAll()</code></a> and a sizable colourspace conversion system, along with userland easing functions for all animations supported natively by modern CSS.</li>
</ul>
</li>
<li>No fewer than <s>2...wait...5</s>...no, <em>6</em> large — seemingly different! — <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent"><code>User-Agent</code></a> parsing libraries that support browsers as weird and wonderful as WebOS, Obigo, and iCab. What a delightful and unexpected <a href="https://infrequently.org/06/EuroOSCON/MobileAjax.pdf">blast from the past! (pdf)</a></li>
<li>What <em>appears</em> to be an HTML parser and <a href="https://framework7.io/docs/dom7">userland DOM implementation!?!</a></li>
<li>A full copy of <a href="https://underscorejs.org/">Underscore.</a></li>
<li>A full copy of <a href="https://lodash.com/">Lodash.</a></li>
<li>A full copy of <a href="https://https//github.com/zloirock/core-js"><code>core-js</code>.</a></li>
<li>A <a href="https://github.com/indutny/elliptic">userland elliptic-curve cryptography implementation.</a> Part of an on-page chatbot, naturally.</li>
<li>A full copy of <a href="https://https//momentjs.com//">Moment.js.</a> <em>in addition</em> to the <a href="https://www.npmjs.com/package/@wojtekmaj/date-utils">custom date and time parsing</a> functions already added via bundling of the (overlarge) <a href="https://projects.wojtekmaj.pl/react-date-picker/"><code>react-date-picker</code> library.</a></li>
<li>An unnecessary <a href="https://backstage.forgerock.com/docs/sdks/latest/sdks/tutorials/javascript/index.html">OAuth library</a>.</li>
<li>An emulated version of the Node.js <code>buffer</code> class, entirely redundant on modern browsers.</li>
<li>The entire <a href="https://aws.amazon.com/chime/chime-sdk/">Amazon Chime SDK,</a> which includes all the code needed to do videoconferencing. This is loaded in the critical path and alone adds multiple megabytes of JS spread across dozens of webpack-chunked files. No features of the home page appear to trigger videoconferencing.</li>
<li>A full copy of the AWS JavaScript SDK, weighing 2.6MB, served separately.</li>
<li>Obviously, nothing this broken would be complete without a Service Worker <em>that only caches image files</em>.</li>
</ul>
<p>This is, to use the technical term, whack.</p>
<p>The users of BenefitsCal are folks on the margins — often working families — trying to feed, clothe, and find healthcare for kids they want to give a better life. I can think of few groups that would be more poorly served by such baffling product and engineering mismanagement. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-receipts-1" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/08/object-lesson/#fnref-receipts-1:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-quibbles-2" class="footnote-item"><p><a href="https://www.getcalfresh.org/">getcalfresh.org</a> isn't perfect from a performance standpoint.</p>
<p>The site would feel considerably snappier if the heavy chat widget it embeds were loaded on demand with the <a href="https://developer.chrome.com/docs/lighthouse/performance/third-party-facades">facade pattern</a> and if the Google Tag Manager bundle were audited to cut cruft. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-quibbles-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-covariate-factors-3" class="footnote-item"><p>Browser engineers sweat the low end because that's where users are<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-mac-ports-17" id="fnref-mac-ports-17">17</a></sup>, and when we do a good job for them, it generally translates into better experiences for everyone else too. One of the most durable lessons of that focus has been that users having a bad time in one dimension are <em>much</em> more likely to be experiencing slowness in others.</p>
<p>Slow networks correlate heavily with older devices that have less RAM, slower disks, and higher taxes from &quot;potentially unwanted software&quot; (PUS). These machines may experience malware fighting with invasive antivirus, slowing disk operations to a crawl. Others may suffer from background tasks for app and OS updates that feel fast on newer machines but which drag on for hours, stealing resources from the user's real work the whole time.</p>
<p>Correlated badness also means that users in these situations benefit from any part of the system using fewer resources. Because browsers are dynamic systems, reduced RAM consumption can make the system faster, both through reduced CPU load from <a href="https://en.wikipedia.org/wiki/Zram">zram</a>, as well as rebalancing in auto-tuning algorithms to optimise for speed rather than space.</p>
<p>The pursuit of excellent experiences at the margins is deep teacher about the systems we program, and a frequently humbling experience. If you want to become a better programmer or product manager, I recommend focusing on those cases. You'll always learn something. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-covariate-factors-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-its-an-app-lie-4" class="footnote-item"><p>It's not surprising to see low code coverage percentages on the first load of an <a href="https://developer.mozilla.org/en-US/docs/Glossary/SPA">SPA</a>. What's shocking is that the developers of BenefitsCal confused it with a site that could benefit from this architecture.</p>
<p>To recap: the bet that SPA-oriented JavaScript frameworks make is that it's <em>possible</em> to deliver better experiences for users when the latency of going to the server can be shortcut by client-side JavaScript.</p>
<p>I cannot stress this enough: the premise of this <em>entire wing</em> of web development practice is that expensive, complex, hard-to-operate, and wicked-to-maintain JavaScript-based UIs lead to <em>better user experiences</em>.</p>
<p>It is more than fair to ask: do they?</p>
<p>In the case of BenefitsCal and DTA Connect, the answer is &quot;no&quot;.</p>
<p>The contingent claim of potentially improved UI requires dividing any additional up-front latency by the number of interactions, then subtracting the average improvement-per-interaction from that total. It's almost impossible to imagine any app with sessions long enough to make 30-second up-front waits worthwhile, never mind a benefits application form.</p>
<p>These projects should never have allowed &quot;frontend frameworks&quot; within a mile of their git repos. That they both picked React (a system with a lurid history of congenital failure) is not surprising, but it is dispiriting.</p>
<p><a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/">Previous</a> <a href="https://infrequently.org/2023/02/the-market-for-lemons/">posts</a> here have noted that site structure and critical user journeys largely constrain which architectures make sense:</p>
<figure class="full_wide">
  <picture>
    <img src="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.png" alt="Sites with shorter average sessions can afford less JS up-front." decoding="async" loading="lazy" style="aspect-ratio: 3528 / 1478; width: 100%;" />
  </picture>
  <figcaption style="text-align: center;">
    Sites with short average sessions cannot afford much JS up-front.
  </figcaption>
</figure>
<p>These portals serve many functions: education, account management, benefits signup, and status checks. None of these functions exhibit the sorts of 50+ interaction sessions of a lived-in document editor (Word, Figma) or email client (Gmail, Outlook). They are not &quot;toothbrush&quot; services that folks go to every day, or which they use over long sessions.</p>
<p>Even the sections that might benefit from additional client-side assistance (rich form validation, e.g.) cannot justify loading all of that code up-front for all users.</p>
<p>The failure to recognise how inappropriate JavaScript-based SPA architectures are for most sites is an industry-wide scandal. In the case of these services, that scandal takes on whole new dimension of reckless irresponsibility. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-the-its-an-app-lie-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-bull-in-a-china-shop-5" class="footnote-item"><p>JavaScript-based SPAs yank the reins away from the browser while simultaneously frontloading code at the most expensive time.</p>
<p>SPA architectures and the frameworks built to support them put total responsibility for all aspects of site performance squarely on the shoulders of the developer. Site owners who are even occasionally less than omniscient can quickly end up in trouble. It's no wonder many teams I work with are astonished at how quickly these tools lead to disastrous results.</p>
<p>SPAs are &quot;YOLO&quot; for web development.</p>
<p>Their advocates' assumption of developer perfection is reminiscent of C/C++'s approach to memory safety. The predictable consequences should be enough to disqualify them from use in most new work. The sooner these tools and architectures are banned from the public sector, the better. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-bull-in-a-china-shop-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-blockage-6" class="footnote-item"><p>Confoundingly, while CalSAWS has not figured out how to enable basic caching and compression, it <em>has</em> rolled out firewall rules that prevent many systems like PageSpeed Insights from evaluating the page through IP blocks.</p>
<p>The same rules also prevent access from IPs geolocated to be outside the US. Perhaps it's <em>also</em> a misconfiguration? Surely CalSAWS isn't trying to cut off access to services for users who are temporarialy visiting family in an emergency, right? <a href="https://infrequently.org/2024/08/object-lesson/#fnref-blockage-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-wtf-amazon-7" class="footnote-item"><p>There's a lot to say about BenefitsCal's CloudFront configuration debacle.</p>
<p>First, and most obviously: WTF, Amazon?</p>
<p>It's great that these options are single-configuration and easy to find when customers go looking for them, <em>but they should not have to go looking for them.</em> The default for egress-oriented projects should be to enable this and then alert on easily detected double-compression attempts.</p>
<p>Second: WTF, Deloitte?</p>
<p>What sort of C-team are you stringing CalSAWS along with? Y'all should be ashamed. And the taxpayers of California should be looking to claw back funds for obscenely poor service.</p>
<p>Lastly: this is on you, CalSAWS.</p>
<p>As the procurer and approver of delivered work items, the failure to maintain a minimum level of in-house technical skill necessary to call BS on vendors is inexcusable.</p>
<p>New and more appropriate metrics for user success should be integrated into public reporting. That conversation could consume an entire blog post; the current reports are little more than vanity metrics. The state should also redirect money it is spending with vendors to enhance in-house skills in building and maintaining these systems directly.</p>
<p>It's an embarrassment that this site is as broken as it was when I began tracing it three years ago. It's a scandal that good money is being tossed after bad. Do better. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-wtf-amazon-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-occam-says-8" class="footnote-item"><p>It's more likely that CalSAWS are inept procurers and that Gainwell + Deloitte are hopeless developers.</p>
<p>The alternative requires accepting that one or all of these parties <em>knew better</em> and did not act, undermining the struggling kids and families of California in the process. I can't square that with the idea of going to work every day for years to build and deliver these services. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-occam-says-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-from-each-according-to-his-ability-9" class="footnote-item"><p>In fairness, <a href="https://treo.sh/sitespeed/www.deloitte.com?formFactor=phone">building great websites doesn't seem to be Deloitte's passion.</a></p>
<figure class="full_wide">
  <picture>
    <img src="https://infrequently.org/2024/08/the-landscape/deloitte.com-cwv.webp" alt="Deloitte.com performs poorly for real-world users, a population that presumably includes a higher percentage of high-end devices than other sites traced in this post." decoding="async" loading="lazy" style="aspect-ratio: TODO / TODO; width: 100%;" />
  </picture>
  <figcaption style="text-align: center;">
    Deloitte.com performs poorly for real-world users, a population that presumably includes a higher percentage of high-end devices than other sites traced in this post.
  </figcaption>
</figure>
<p>But <em>even Deloitte</em> could have fixed the BenefitsCal mess had CalSAWS demanded better. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-from-each-according-to-his-ability-9" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-services-schmervices-10" class="footnote-item"><p>It rankles a bit that what the UK's GDS has put into action for the last decade <a href="https://www.eatingpolicy.com/p/yes-virginia-there-really-are-products">is only now being recognised in the US.</a></p>
<p>If US-centric folks need to call these things &quot;products&quot; instead of &quot;services&quot; to make the approach legible, so be it! Better late than never. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-services-schmervices-10" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-disclosure-approach-11" class="footnote-item"><p>I generally have not not posted traces of the private sector sites I have spent much of the last decade assisting, preferring instead to work quietly to improve their outcomes.</p>
<p>The exception to this rule is the public sector, where I feel deeply cross-pressured about the sort of blow-back that underpaid civil servants may face. However, sunlight is an effective disinfectant, particularly for services we all pay for. The tipping point in choosing to post these traces is that by doing so, we might spark change across the whole culture of frontend development. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-disclosure-approach-11" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-gcf-sunset-12" class="footnote-item"><p>getcalfresh.org is the only direct competitor I know of to a state's public benefits access portal, and today it drives nearly half of all SNAP signups in California. Per <a href="https://www.calsaws.org/wp-content/uploads/2023/12/02_CalSAWS-BenefitsCal-Weekly-Status-Report_11262023-1.pdf">BenefitsCal meeting notes (pdf),</a> it is scheduled to be decommissioned next year.</p>
<p>Unless BenefitsCal improves dramatically, the only usable system for SNAP signup in the most populous state will disappear when it goes. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-gcf-sunset-12" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-solidarity-13" class="footnote-item"><p>Capping the effective bandwidth of a server is certainly <em>one</em> way to build solidarity between users on fast and slow devices.</p>
<p>It does not appear to have worked.</p>
<p>The glacial behaviour of the site for all implies managers in EOHHS must surely have experienced DTA Connect's slowness for themselves and declined to do anything about it. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-solidarity-13" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-disaster-tourism-14" class="footnote-item"><p>The content and structure of DTA Connect's JavaScript are just as horrifying as BenefitsCal's<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/object-lesson/#fn-receipts-1" id="fnref-receipts-1:1">1:1</a></sup> and served just as poorly. Pretty-printed, the main bundle runs to 302,316 lines.</p>
<p>I won't attempt nearly as exhaustive inventory of the #fail it contains, but suffice to say, it's a Create React App special. CRAppy, indeed.</p>
<p>Many obsolete polyfills and libraries are bundled, including (but not limited to):</p>
<ul>
<li>A full copy of core-js</li>
<li>Polyfills for features as widely supported as <a href="https://caniuse.com/fetch"><code>fetch()</code></a></li>
<li>Transpilation down to ES5, with polyfills to match</li>
<li>A full userland elliptic-curve cryptography library</li>
<li>A userland implementation of BigInt</li>
<li>A copy of zlib.js</li>
<li>A full copy of the <a href="https://publicsuffix.org/list/">Public Suffix List</a></li>
<li>A full list of mime types (thousands of lines).</li>
<li>What <em>appears</em> to be a relatively large <a href="https://en.wikipedia.org/wiki/Rainbow_table">rainbow table.</a></li>
</ul>
<p>Seasoned engineers reading this list may break out in hives, and that's an understandable response. None of this is necessary, and none of it is useful in a modern browser. Yet all of it is in the critical path.</p>
<p>Some truly unbelievable bloat is the result of <em>all</em> localized strings for the entire site occurring in the bundle. In <em>every supported language</em>.</p>
<p>Any text ever presented to the user is included in English, Spanish, Portuguese, Chinese, and Vietnamese, adding megabytes to the download.</p>
<p>A careless disregard for users, engineering, and society permeates this artefact. Massachusetts owes citizens better. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-disaster-tourism-14" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ten-ex-15" class="footnote-item"><p>Some junior managers still believe in the myth of the &quot;10x&quot; engineer, but this isn't what folks mean when they talk about &quot;productivity&quot;. Or at least I hope it isn't. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-ten-ex-15" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-grinding-16" class="footnote-item"><p>Angular is now on version 18, meaning Maryland faces a huge upgrade lift whenever it next decides to substantially improve myMDTHINK. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-grinding-16" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-mac-ports-17" class="footnote-item"><p>Browsers port to macOS for CEOs, hipster developers, and the tech press. Macs are <a href="https://gs.statcounter.com/os-market-share"><em>extremely</em> niche devices</a> owned exclusively by the <a href="https://ourworldindata.org/the-history-of-global-economic-inequality">1-2%.</a> Its ~5% browsing share is inflated by the <a href="https://www.itu.int/en/ITU-D/Statistics/Pages/stat/default.aspx">30% not yet online</a>, almost none of whom will be able to afford Macs.</p>
<p>Wealth-related factors also multiply the visibility of high-end devices (like Macs) in summary statistics. These include better networks and faster hardware, both of which correlate with heavier browsing. Relatively high penetration in geographies with strong web use also helps. For example, Macs have <a href="https://www.statista.com/statistics/272667/market-share-held-by-operating-systems-in-the-us-since-2009/">30% share of desktop-class sales in the US</a>, vs <a href="https://www.statista.com/statistics/218089/global-market-share-of-windows-7/">15% worldwide.</a>.</p>
<p>The overwhelming predominance of smartphones vs. desktops seals the deal. In 2023, <a href="https://www.pcgamer.com/analysts-are-calling-2023s-decline-in-pc-shipments-unparalleled-in-the-industrys-recorded-history-but-suggest-the-only-way-now-is-up/">smartphones outsold</a> <a href="https://www.canalys.com/newsroom/worldwide-smartphone-market-2023">desktops and laptops</a> by more than 4:1. This means that smartphones outnumber laptops and desktops to an even greater degree worldwide than they do in the US.</p>
<p>Browser makers keep Linux ports ticking over because that's where developers live (including many of their own). It's also critical for the CI/CD systems that power much of the industry.</p>
<p>Those constituencies are vocal and wealthy, giving them outsized influence. But iOS and and macOS aren't real life; Android and Windows are, particularly their low-end, bloatware-filled expressions.</p>
<p>Them's the breaks. <a href="https://infrequently.org/2024/08/object-lesson/#fnref-mac-ports-17" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Reckoning: Part 1 — The Landscape</title>
    <link href="https://infrequently.org/2024/08/the-landscape/"/>
    <updated>2024-08-12T00:00:00Z</updated>
    <id>https://infrequently.org/2024/08/the-landscape/</id>
    <content type="html"><![CDATA[
      <div style="font-size: 1rem;">
<p><em>Instead of an omnibus mega-post, this investigation into JavaScript-first frontend culture and how it broke US public services has been released in four parts. Other posts in the series:</em></p>
<ul>
<li><em><a href="https://infrequently.org/2024/08/object-lesson/">Reckoning: Part 2 — Object Lesson</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/caprock/">Reckoning: Part 3 — Caprock</a></em></li>
<li><em><a href="https://infrequently.org/2024/08/the-way-out/">Reckoning: Part 4 — The Way Out</a></em></li>
</ul>
</div>
<hr />
<p>When you live in the shadow of a slow-moving crisis, it's natural to tell people about it. <a href="https://vimeo.com/364402896">At volume.</a> Doubly so when engineers can cheaply and easily address the root causes with minor tweaks. As things worsen, it's also hard not to build empathy for Cassandra.</p>
<p>In late 2011, I moved to London, where the Chrome team was beginning to build Google's first &quot;real&quot; browser for Android.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-to-each-their-own-1" id="fnref-to-each-their-own-1">1</a></sup> The system default <a href="https://developer.android.com/about/versions/android-3.0-highlights#updated-set-of-standard-apps">Android Browser</a> had, up until that point, been based on the system WebView, locking its rate of progress to the glacial pace of device replacement.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-familiar-problems-2" id="fnref-familiar-problems-2">2</a></sup></p>
<p>In a world where the <a href="https://en.wikipedia.org/wiki/Nexus_4">Nexus 4's 2GB of RAM</a> and <a href="https://www.anandtech.com/show/6112/qualcomms-quadcore-snapdragon-s4-apq8064adreno-320-performance-preview">32-bit, 4-core CPU</a> were the high-end, the memory savings the Android Browser achieved by reusing WebView code mattered immensely.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-bom-bom-bom-3" id="fnref-bom-bom-bom-3">3</a></sup> Those limits presented enormous challenges for Chromium's safer (but memory-hungry) <a href="https://www.chromium.org/developers/design-documents/multi-process-architecture/">multi-process sandboxing.</a> Android wasn't just spicy Linux; it was an entirely new ballgame.</p>
<p>Even then, it was clear the iPhone wasn't a fluke. Mobile was <em>clearly</em> on track to be the dominant form-factor, and we needed to adapt. Fast.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-reset-4" id="fnref-reset-4">4</a></sup></p>
<p>Browsers made that turn, and by 2014, we had made enough progress to consider how the web could participate in mobile's app-based model. This work culminated in <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">2015's introduction of PWAs and Push Notifications.</a></p>
<p>Disturbing patterns emerged as we worked with folks building on this new platform. A surprisingly high fraction of them brought slow, desktop-oriented JavaScript frameworks with them to the mobile web. These modern, mobile-first projects neither needed nor could afford the extra bloat frameworks included to paper over the problems of legacy desktop browsers. Web developers needed to adapt the way browser developers had, but consistently failed to hit the mark.</p>
<p>By 2016, frontend practice had fully lapsed into wish-thinking. Alarms were pulled, claxons sounded, but nothing changed.</p>
<p><lite-youtube videoid="4bZvq3nodf4" videotitle="Chrome DevSummit 2016: Progressive Performance" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=4bZvq3nodf4">Chrome DevSummit 2016: Progressive Performance</a>              </lite-youtube></p>
<p>It could not have come at a worse time.</p>
<p>By then, explosive growth at the low end was baked into the cake. Billions of feature-phone users had begun to trade up. Different brands endlessly reproduced 2016's mid-tier Androids under a dizzying array of names. The only constants were the middling specs and ever-cheaper prices. Specs that would set punters back $300 in 2016, sold for only $100 a few years later, opening up the internet to hundreds of millions along the way. The battle between the web and apps as the dominant platform was well and truly on.</p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments.<br><br>Nearly all growth in smartphone sales volume since the mid '10s occured in the 'budget' and 'low-end' categories." target="_blank"><picture style="--lqip: 172771" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments.<br><br>Nearly all growth in smartphone sales volume since the mid '10s occured in the 'budget' and 'low-end' categories." style="padding: 15px; background-color: white;; aspect-ratio: 1438 / 812" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments.<br /><br />Nearly all growth in smartphone sales volume since the mid '10s occured in the 'budget' and 'low-end' categories.</figcaption>      </figure><p></p>
<p>But the low-end revolution barely registered in web development circles. Frontenders <a href="https://httparchive.org/reports/state-of-javascript#bytesJs">poured JavaScript into the mobile web</a> at the same rate as desktop, destroying any hope of a good experience for folks on a budget.</p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/state-of-javascript#bytesJs" alt="Median JavaScript bytes for Mobile and Desktop sites. <br>As this blog has <a href='/series/performance-inequality/'>covered at length,</a> median device specs were largely stagnant between 2014 and 2022. Meanwhile, web developers made sure the 'i' in 'iPhone' stood for 'inequality.'" target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/js-bytes-2011-2024-http-archive.webp" alt="Median JavaScript bytes for Mobile and Desktop sites. <br>As this blog has <a href='/series/performance-inequality/'>covered at length,</a> median device specs were largely stagnant between 2014 and 2022. Meanwhile, web developers made sure the 'i' in 'iPhone' stood for 'inequality.'" style="aspect-ratio: 1251 / 654" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Median JavaScript bytes for Mobile and Desktop sites. <br />As this blog has <a href="https://infrequently.org/series/performance-inequality/">covered at length,</a> median device specs were largely stagnant between 2014 and 2022. Meanwhile, web developers made sure the 'i' in 'iPhone' stood for 'inequality.'</figcaption>      </figure><p></p>
<p>Prices at the high end accelerated, yet average selling prices remained stuck between $300 and $350. The only way the emergence of the $1K phone didn't bump the average up was the explosive growth at the low end. To keep the average selling price at $325, <em>three</em> $100 low-end phones needed to sell for each $1K iPhone; which is exactly what happened.</p>
<p>And yet, the march of JavaScript-first, framework-centric dogma continued, no matter how incompatible it was with the new reality. Predictably, tools sold on the promise they would deliver &quot;app-like experiences&quot; did anything but.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-app-like-5" id="fnref-app-like-5">5</a></sup></p>
<p>Billions of cheap phones that <em>always</em> have up-to-date browsers found their CPUs and networks clogged with bloated scripts designed to work around platform warts they don't have.</p>
<h2 id="environmental-factors" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/08/the-landscape/#environmental-factors">Environmental Factors</a></h2>
<p>In 2019, <a href="https://www.codeforamerica.org/">Code for America</a> published the <a href="https://www.codeforamerica.org/explore/bringing-social-safety-net-benefits-online/">first national-level survey</a> of online access to benefits programs, which are built and operated by each state. The <a href="https://codeforamerica.org/explore/benefits-enrollment-field-guide/">follow-up 2023 study</a> provides important new data on the spread of digital access to benefits services.</p>
<p>One valuable artefact from CFA's 2019 research <a href="https://codeforamerica.org/explore/benefits-enrollment-field-guide/">is a post</a> by <a href="https://codeforamerica.org/people/dustin-palmer/">Dustin Palmer</a>, documenting the missed opportunity among many online benefits portals to design for the coming mobile-first reality that was already the status quo in the rest of the world.</p>
<!-- TODO: move above? -->
<p></p><figure class="full_wide"><a href="https://gs.statcounter.com/platform-market-share/desktop-mobile/worldwide/#yearly-2009-2024" alt="Worldwide mobile browsing surpassed desktop browsing sometime in 2016." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/StatCounter-comparison-ww-yearly-2009-2024.webp" alt="Worldwide mobile browsing surpassed desktop browsing sometime in 2016." style="aspect-ratio: 1280 / 720" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Worldwide mobile browsing surpassed desktop browsing sometime in 2016.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://gs.statcounter.com/platform-market-share/desktop-mobile/united-states-of-america/#yearly-2009-2024" alt="US browsing exhibited the same trend, slightly delayed, owing to comparatively high desktop and laptop ownership vs emerging markets." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/StatCounter-comparison-US-yearly-2009-2024.webp" alt="US browsing exhibited the same trend, slightly delayed, owing to comparatively high desktop and laptop ownership vs emerging markets." style="aspect-ratio: 1280 / 720" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>US browsing exhibited the same trend, slightly delayed, owing to comparatively high desktop and laptop ownership vs emerging markets.</figcaption>      </figure><p></p>
<p>Moving these systems online only reduces <a href="https://www.rsfjournal.org/content/9/5/1">administrative burdens</a> in a contingent sense; if portals fail to work well on phones, smartphone-dependent folks are predictably excluded:</p>
<p></p><figure class="full_wide"><a href="https://www.pewresearch.org/internet/fact-sheet/mobile/?tabId=tab-011fca0d-9756-4f48-b352-d58f343696bf" alt="28% of US adults in households with less than $30K/yr income are smartphone-dependent, falling to only 19% for families making 30-70K/yr." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/pew-smartphone-dependence-2023.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/pew-smartphone-dependence-2023.webp" alt="28% of US adults in households with less than $30K/yr income are smartphone-dependent, falling to only 19% for families making 30-70K/yr." style="aspect-ratio: 916 / 634" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>28% of US adults in households with less than $30K/yr income are smartphone-dependent, falling to only 19% for families making 30-70K/yr.</figcaption>      </figure><p></p>
<p>But poor design isn't the only potential administrative burden for smartphone-dependent users.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-performance-isnt-everything-6" id="fnref-performance-isnt-everything-6">6</a></sup></p>
<p>The networks and devices folks use to access public support aren't latest-generation or top-of-the-line. They're squarely in the tail of the device price, age, and network performance distributions. Those are the overlapping conditions where the <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-great-branch-mispredict">consistently falsified assumptions of frontend's lost decade have played out disastrously.</a></p>
<p></p><figure class="full_wide"><a href="https://broadbandmap.fcc.gov/location-summary/mobile?version=dec2023&zoom=4.98&vlon=-119.671255&vlat=37.829130&env=0&tech=tech4g" alt="California is a rich mix of urban and hard-to-reach rural areas. Some of the poorest residents are in the least connected areas, ensuring they will struggle to use bloated sites." target="_blank"><picture style="--lqip: -514590" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/08/the-landscape/ca-fcc-nbm-4g.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/08/the-landscape/ca-fcc-nbm-4g.webp" alt="California is a rich mix of urban and hard-to-reach rural areas. Some of the poorest residents are in the least connected areas, ensuring they will struggle to use bloated sites." style="aspect-ratio: 1162 / 966" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>California is a rich mix of urban and hard-to-reach rural areas. Some of the poorest residents are in the least connected areas, ensuring they will struggle to use bloated sites.</figcaption>      </figure><p></p>
<p>It would be tragic if public sector services adopted the JavaScript-heavy stacks that frontend influencers have popularised. Framework-based, &quot;full-stack&quot; development is now the default in Silicon Valley, but should obviously be avoided in universal services. Unwieldy and expensive stacks that have caused agony in the commercial context could never be introduced to the public sector with any hope of success.</p>
<p>Right?</p>
<p><em><strong>Next:</strong> <a href="https://infrequently.org/2024/08/object-lesson/">Object Lesson: a look at California's digital benefits services.</a></em></p>
<div style="font-size: 1rem;">
<p><em>Thanks to <a href="https://polotek.net/">Marco Rogers</a>, and <a href="https://fberriman.com/">Frances Berriman</a> for their encouragement in making this piece a series and for their thoughtful feedback on drafts.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-to-each-their-own-1" class="footnote-item"><p>A &quot;real browser&quot;, as the Chrome team understood the term circa 2012, included:</p>
<ul>
<li>Chromium's memory-hungry multi-process architecture which dramatically improved security and stability</li>
<li>Winning JavaScript performance using our own V8 engine</li>
<li>The Chromium network stack, including support for <a href="https://en.wikipedia.org/wiki/SPDY">SPDY</a> and experiments like WebRTC</li>
<li>Updates that were not locked to OS versions</li>
</ul>
 <a href="https://infrequently.org/2024/08/the-landscape/#fnref-to-each-their-own-1" class="footnote-backref">⇐</a></li>
<li id="fn-familiar-problems-2" class="footnote-item"><p>Of course, the Chrome team had wanted to build a proper mobile browser sooner, but Android was a paranoid fiefdom separate from Google's engineering culture and systems. And the Android team were <em>intensely</em> suspicious of the web, verging into outright hostility at times.</p>
<p>But internal Google teams kept hitting the limits of what the Android Browser could do, including Search. And when Search says &quot;jump&quot;, the only workable response is &quot;how high?&quot;</p>
<p>WebKit-based though it was (as was Chrome), OS-locked features presented a familiar problem, one the Chrome team had solved with auto-update and <a href="https://en.wikipedia.org/wiki/Google_Chrome_Frame">Chrome Frame.</a> A deal was eventually struck, and when Chrome for Android was delivered, the system WebView also became a Chromium-based, multi-process, sandboxed, auto-updating system. For most, that was job done.</p>
<p>This made a certain sort of sense. From the perspective of Google's upper management, Android's role was to put a search box in front of everyone. If letting Andy <em>et al.</em> play around with an unproven Java-based app model was the price, OK. If that didn't work, the web would still be there. If it did, then Google could go from accepting someone else's platform to having one it owned outright.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-unease-7" id="fnref-unease-7">7</a></sup> Win/win.</p>
<p>Anyone trying to suggest a more web-friendly path for Android got shut down <em>hard</em>. The Android team always had legitimate system health concerns that they could use as cudgels, and they weilded them with abandon.</p>
<p>The <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">launch of PWAs in 2015</a> was an outcome Android saw coming a mile away and worked hard to prevent. But that's a story for another day. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-familiar-problems-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-bom-bom-bom-3" class="footnote-item"><p>Android devices were already being spec'd with more RAM than contemporary iPhones, thanks to Dalvik's chonkyness. This, in turn, forced many OEMs to cut corners in other areas, including slower CPUs.</p>
<p>This effect has been a silent looming factor in the past decade's divergence in CPU performance between top-end Android and iPhones. Not only did Android OEMs have to pay a distinct profit margin to Qualcomm for their chips, but they also had to dip into the <a href="https://en.wikipedia.org/wiki/Bill_of_materials">Bill Of Materials (BOM)</a> budget to afford more memory to keep things working well, leaving less for the CPU.</p>
<p>Conversely, Apple's relative skimpiness on memory and burning desire to keep BOM costs low for parts it doesn't manufacture are reasons to oppose browser engine choice. If real browsers were allowed, end users might expect phones with decent specs. Apple keeps that in check, in part, by maximising <a href="https://en.wikipedia.org/wiki/Page_cache">code page reuse</a> across browsers and apps that are forced to use the system WebView.</p>
<p>That might dig into margins <em>ever so slightly</em>, and we can't have that, can we? <a href="https://infrequently.org/2024/08/the-landscape/#fnref-bom-bom-bom-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-reset-4" class="footnote-item"><p>It took browsers that were originally architected in a desktop-only world many years to digest the radically different hardware that mobile evolved. Not only were CPU speeds and memory budgets cut dramatically — nevermind the need to port to ARM, including JS engine JITs that were heavily optimised for x86 — but networks suddenly became intermittent and variable-latency.</p>
<p>There were also upsides. Where GPUs had been rare on the desktop, every phone had a GPU. Mobile CPUs were slow enough that what had felt like a leisurely walk away from CPU-based rendering on desktop became an absolute necessity on phones. Similar stories played out across input devices, sensors, and storage.</p>
<p>It's no exaggeration to say that the transition to mobile force-evolved browsers in a compressed time frame. If only websites had made the same transition. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-reset-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-app-like-5" class="footnote-item"><p>Let's take a minute to unpack what the JavaScript framework claims of <em>&quot;app-like experiences&quot;</em> were meant to convey.</p>
<p>These were code words for more responsive UI, building on the Ajax momentum of the mid-naughties. Many boosters claimed this explicitly and built <a href="https://create-react-app.dev/">popular tools to support these specific architectures.</a></p>
<p>As we wander through the burning wreckage of public services that adopted these technologies, remember one thing: they were supposed to make UIs <em>better</em>. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-app-like-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-performance-isnt-everything-6" class="footnote-item"><p>When confronted with nearly unusable results from tools sold on the idea that they make sites easier, better, and faster to use, many technologists offer the variants of <em>&quot;but at least it's online!&quot;</em> and <em>&quot;it's fast enough for most people&quot;</em>. The most insipid version implies causality, constructing a <a href="https://en.wikipedia.org/wiki/Proximate_cause">strawman <em>but-for</em> defense;</a> <em>&quot;but these sites might not have even been built without these frameworks.&quot;</em><sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-cruelly-stupid-9" id="fnref-cruelly-stupid-9">9</a></sup></p>
<p>These points can be both true and immaterial at the same time. It isn't necessary for poor performance to <em>entirely</em> exclude folks at the margins for it to be a significant disincentive to accessing services.</p>
<p>We know this because it has been proven and continually reconfirmed in <a href="https://wpostats.com/">commercial</a> and <a href="https://www.nytimes.com/2012/08/19/opinion/sunday/why-waiting-in-line-is-torture.html?unlocked_article_code=1.Bk4.c_y7.EhyNmle0_aTb&amp;smid=url-share">lab</a> settings. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-performance-isnt-everything-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-unease-7" class="footnote-item"><p>The web is unattractive to every Big Tech company in a hurry, even the ones that owe their existence to it.</p>
<p>The web's joint custody arrangement rankles. The standards process is inscrutable and frustrating to PMs and engineering managers who have only ever had to build technology inside one company's walls. Playing on hard mode is unappealing to high-achievers who are used to running up the score.</p>
<p>And then there's the technical prejudice. The web's languages offend &quot;serious&quot; computer scientists. In the <a href="https://xkcd.com/378/">bullshit hierarchy</a> of programming language snobbery, <em>everyone</em> looks down on JavaScript, HTML, and CSS (in that order).</p>
<p>The web's <em>overwhelmingly</em> successful languages present a paradox: for the comfort of the snob, they must simultaneously be unserious toys beneath the elevated palettes of &quot;generalists&quot; and also Gordian Knots too hard for anyone to possibly wield effectively. This dual posture justifies treating frontend as a less-than discipline, and browsers as anything but a serious application platform.</p>
<p>This isn't universal, but it is common, particularly in Google's C++/Java-pilled upper ranks.<sup class="footnote-ref"><a href="https://infrequently.org/2024/08/the-landscape/#fn-self-limiting-8" id="fnref-self-limiting-8">8</a></sup> Endless budgetary space for projects like the Android Framework, Dart, and Flutter were the result. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-unease-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-self-limiting-8" class="footnote-item"><p>Someday I'll write up the tale of how Google so thoroughly devalued frontend work that it couldn't even retain the <em>unbelievably</em> good web folks it hired in the mid-'00s. Their inevitable departures after years of being condescended to went hand-in-hand with an inability to hire replacements.</p>
<p>Suffice to say, by the mid '10s, things were <em>bad</em>. So bad an exec finally noticed. This created a bit of space to fix it. A team of volunteers answered the call, and for more than a year we met to rework recruiting processes and collateral, interview loop structures, interview questions, and promotion ladder criteria.</p>
<p>The hope was that folks who work in the cramped confines of someone else's computer could finally be recognised for their achievements. And for a few years, Google's frontends got markedly better.</p>
<p>I'm told the mean has reasserted itself. Prejudice is an insidious thing. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-self-limiting-8" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-cruelly-stupid-9" class="footnote-item"><p>The <em>but-for</em> defense for underperforming frontend frameworks requires us to ignore both the 20 years of web development practice that preceeded these tools <em>and</em> the higher OpEx and CapEx costs associated with React-based stacks.</p>
<p>Managers sometimes offer a hireability argument, suggesting they need to adopt these univerally more expensive and harder to operate tools <em>because they need to be able to hire</em>. This was always nonsense, but never more so than in 2024. Some of the best, most talented frontenders I know are looking for work and would <em>leap</em> at the chance to do good things in an organisation that puts user experience first.</p>
<p>Others sometimes offer the idea that it would be too hard to retrain their teams. Often, these are engineering groups comprised of folks who recently retrained from other stacks to the new React hotness or who graduated boot camps armed only with these tools. The idea that either cohort cannot learn anything else is as inane as it is self-limiting.</p>
<p>Frontenders can learn any framework and are constantly retraining just to stay on <a href="https://polotek.net/posts/the-frontend-treadmill/">the treadmill.</a> The idea that there are savings to be had in <em>&quot;following the herd&quot;</em> into Next.js or similar JS-first development cul-de-sacs has to meet an evidentiary burden that I have rarely seen teams clear.</p>
<p>Managers who want to avoid these messes have options.</p>
<p>First, they can <a href="https://kellanem.com/notes/new-tech">crib Kellan's tests for new technologies.</a> Extra points for <a href="https://blog.glyph.im/2024/07/against-innovation-tokens.html">digesting Glyph's thoughts on &quot;innovation tokens.&quot;</a></p>
<p>Next, they should identify the critical user journeys in their products. Technology choices are always situated in product constraints, but until the critical user journeys are enunciated, the selection of <em>any</em> specific architecture is likely to be wrong.</p>
<p>Lastly, they should always run bakeoffs. Once critical user journeys are outlined and agreed, bakeoffs can provide teams with essential data about how different technology options will perform under those conditions. For frontend technologies, that means evaluating them under <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/">representative market conditions.</a></p>
<p>And yes, there's almost always time to do several small prototypes. It's a damn sight cheaper than the months (or years) of painful remediation work. I'm sick to death of having to hand-hold teams whose products are suffocating under unusably large piles of cruft, slowly nursing their  code-bases back to something like health as their management belatedely <a href="https://infrequently.org/2022/05/performance-management-maturity/">learns the value of knowing their systems deeply.</a></p>
<p>Managers that do honest, user-focused bakeoffs for their frontend choices can avoid adding their teams to the dozens I've consulted with who adopted extremely popular, fundamentally inappropriate technologies that have had disasterous effects on their businesses and team velocity. Discarding popular stacks from consideration through evidence isn't a career risk; it's literally the reason to hire engineers and engineering leaders in the first place. <a href="https://infrequently.org/2024/08/the-landscape/#fnref-cruelly-stupid-9" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Misfire</title>
    <link href="https://infrequently.org/2024/07/misfire/"/>
    <updated>2024-07-30T00:00:00Z</updated>
    <id>https://infrequently.org/2024/07/misfire/</id>
    <content type="html"><![CDATA[
      <p>The <a href="https://www.w3.org/2001/tag/">W3C Technical Architecture Group</a><sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-past-service-1" id="fnref-past-service-1">1</a></sup> is out with a <a href="https://www.w3.org/blog/2024/third-party-cookies-have-got-to-go/">blog post</a> and an <a href="https://www.w3.org/2001/tag/doc/web-without-3p-cookies/">updated Finding</a> regarding Google's recent announcement that <a href="https://privacysandbox.com/news/privacy-sandbox-update/">it will not be imminently removing third-party cookies.</a></p>
<p>The current TAG members are competent technologists who have a long history of nuanced advice that looks past the shouting to get at the technical bedrock of complex situations. The TAG also plays a uniquely helpful role in boiling down the guidance it issues into <a href="https://www.w3.org/TR/design-principles/">actionable principles that developers can easily follow.</a></p>
<p>All of which makes these pronouncements seem like weak tea. To grok why, we need to walk through the threat model, look at the technology options, and try to understand the limits of technical interventions.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/07/misfire/#unmasking-the-problem">Unmasking The Problem</a></li><li><a href="https://infrequently.org/2024/07/misfire/#fire-and-movement">Fire And Movement</a></li><li><a href="https://infrequently.org/2024/07/misfire/#finding-a-way-forward">Finding A Way Forward</a></li></ul></nav>
<p>But before that, I should stipulate my personal position on third-party cookies: they aren't great!</p>
<p>They should be removed from browsers when replacements are good and ready, and  Google's climbdown isn't helpful. That said, we have seen nothing of the hinted-at alternatives, so the jury's out on what the impact will be in practice.<sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-also-2" id="fnref-also-2">2</a></sup></p>
<p>So why am I dissapointed in the TAG, given that my position is essentially what they wrote? Because it failed to acknowledge the limited and contingent upside of removing third-party cookies, or the thorny issues we're left with after they're gone.</p>
<h2 id="unmasking-the-problem" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/07/misfire/#unmasking-the-problem">Unmasking The Problem</a></h2>
<p>So, what do third-party cookies do? And how do they relate to the privacy theat model?</p>
<p>Like a lot of web technology, third-party cookies have both positive and negative uses. Owing to a historcal lack of platform-level identity APIs, they form the backbone of nearly every large Single Sign-On (SSO) system. Thankfully, <a href="https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API">replacements have been developed and are being iterated on</a>.</p>
<p>Unfortunately, some browsers have <a href="https://support.okta.com/help/s/article/FAQ-How-Blocking-Third-Party-Cookies-Can-Potentially-Impact-Your-Okta-Environment?language=en_US">unilaterally removed them without developing such replacements, disrupting sign-in flows across the web,</a> harming users and pushing businesses toward native mobile apps. That's bad, as native apps face no limits on communicating with third parties and are generally worse for tracking. They're not even subject to pro-user interventions like browser extensions. The TAG should have called out this aspect of the current debate in its Finding, encouraging vendors to adopt APIs that will make the transition smoother.</p>
<p>The creepy uses of third-party cookies relate to advertising. Third-party cookies provide ad networks and data brokers the ability to silently reidentify users as they browse the web. Some <a href="https://en.wikipedia.org/wiki/Shadow_profile">build &quot;shadow profiles&quot;</a>, and most target ads based on sites users visit. This targeting is at the core of the debate around third-party cookies.</p>
<p>Adtech companies like to claim targeting based on these dossiers allows them to put ads in front of users most likely to buy, reducing wasted ad spending. The industry even has a shorthand: <em>&quot;right people, right time, right place.&quot;</em></p>
<p>Despite the bold claims and a consensus that &quot;targeting works,&quot; there's reason <a href="https://www.mi-3.com.au/18-06-2024/ex-um-privacy-chief-lifts-lid-google-has-captured-trade-associations-and-holdcos">to believe pervasive surveillence doesn't deliver,</a> and even when it does, <a href="https://www.mi-3.com.au/26-06-2024/data-delusion-does-using-data-target-specific-audiences-advertising-actually-make">isn't more effective.</a></p>
<p>Assuming the social utility of targeted ads is low — likely <em>much</em> lower than adtech firms claim — shouldn't we support the TAG's finding? Sadly, no. The TAG missed a critical opportunity to call for legislative fixes to the technically unfixable problems it failed to enumerate.</p>
<p>Privacy isn't just about collection, it's about correlation across time. Adtech can and will migrate to the server-side, meaning publishers will become active participants in tracking, funneling data back to ad networks directly from their own logs. Targeting pipelines will still work, with the largest adtech vendors consolidating market share in the process.</p>
<p>This is why <em>&quot;give us your email address for 30% discount&quot;</em> popups and account signup forms are suddenly everywhere. Email addresses are stable, long-lived reidentifiers. Overt mechanisms like this are already replacing third-party cookies. Make no mistake: post-removal, tracking will continue for as long as reidentification has perceived positive economic value. The only way to change that equation is legislation; anything else is a band-aid.</p>
<p>Pulling tracking out of the shadows is good, but a limited and contingent good. Users have a <em>terrible</em> time recognising and mitigating risk on the multi-month time-scales where privacy invasions play out. There's virtually no way to control or predict where collected data will end up in most jurisdictions, and long-term collection gets cheaper by the day.</p>
<p>Once correlates are established, or &quot;consent&quot; is given to process data in ways that facilitate unmasking, re-identification becomes trivial. It only takes giving a phone number to one delivery company, or an email address to one e-commerce site to suddenly light up a shadow profile, linking a vast amount of previously un-attributed browsing to a user. Clearing caches can reset things for a little while, but any tracking vendor that can observe a large proportion of browsing will eventually be able to join things back up.</p>
<p>Removal of third-party cookies <em>can</em> temporarily disrupt this reidentification while collection funnels are rebuilt to use &quot;first party&quot; data, but that's not going to improve the situation over the long haul. The problem isn't just what's being collected <em>now</em>, it's the ocean of dormant data that was previously slurped up.<sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-a-digression-on-native-apps-3" id="fnref-a-digression-on-native-apps-3">3</a></sup> The only way to avoid pervasive collection and reidentification over the long term is to change the economics of correlation.</p>
<p>The TAG surely understands the only way to make that happen is for more jurisdictions to pass privacy laws worth a damn. It should say so.</p>
<h2 id="fire-and-movement" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/07/misfire/#fire-and-movement">Fire And Movement</a></h2>
<p>The goal of tracking is to pick users out of crowds, or at least bucket them into small unique clusters. As <a href="https://toot.cafe/@slightlyoff/112870912050930748">I explained on Mastodon</a>, this boils down to bits of entropy, and <a href="https://coveryourtracks.eff.org/">those bits are <em>everywhere</em>.</a> From screen resolution and pixel density, to the intrinsic properties of the networks, to extensions, to language and accessibility settings that folks rely on to make browsing liveable. Every attribute that is even subtly different can be a building block for silent reidentification; A.K.A., &quot;fingerprinting.&quot;<sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-a-truly-private-browser-4" id="fnref-a-truly-private-browser-4">4</a></sup></p>
<p>In jurisdictions where laws allow collected data to remain the property of the collector, the risks posed by data-at-rest is only slightly attenuated by narrowing the funnel through which collection takes place.</p>
<p>It's possible to imagine computing that isn't fingerprintable, but that isn't what anyone is selling. For complex reasons, even the most cautious use of commodity computers is likely to be uniquely identifiable with enough time. This means that the question to answer isn't <em>&quot;do we think tracking is bad?&quot;</em>, it's <em>&quot;given that we can't technically eliminate it, how can we rebuild privacy?&quot;</em>. The TAG's new Finding doesn't wrestle with that question, doing the community a disservice in the process.</p>
<p>The most third-party cookie removal can deliver is temporary disruption. That disruption will affect distasteful collectors, costing them money in the short run. Many think of this as a win, I suspect because they fail to think through the longer-term consequences. The predictable effect will be a recalibration and entrenchment of surveillence methods. It will not put the panopticon out of business; only laws can do that.</p>
<p>For a preview of what this will look like, think back on Apple's <a href="https://mobiledevmemo.com/apple-robbed-the-mobs-bank/">&quot;App Tracking Transparency&quot;</a> kayfabe, <a href="https://www.businessofapps.com/data/facebook-statistics/">which did not visibly dent Facebook's long-term profits.</a></p>
<p>So this is not a solution to privacy, it's <a href="https://en.wikipedia.org/wiki/Fire_and_movement">fire-and-movement tactics</a> against corporate enemies. Because of the deep technical challenges in defeating fingerprinting<sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-a-truly-private-browser-4" id="fnref-a-truly-private-browser-4:1">4:1</a></sup>, even the most outspoken vendors have given up, <a href="https://www.apple.com/privacy/labels/">introducing &quot;nutrition labels&quot; to shift responsibility for privacy onto consumers.</a></p>
<p>If the best vertically-integrated native ecosystems can do is to shift blame, the TAG should call out posturing about ineffective changes and push for real solutions. Vendors should loudly lobby for stronger laws that can truly change the game and the TAG should join those calls. The TAG should also advocate for the web, rather than playing into technically ungrounded fearmongering by folks trying to lock users into proprietary native apps whilst <a href="https://open-web-advocacy.org/apple-browser-ban/">simultaneously depriving users of more private browsers.</a></p>
<h2 id="finding-a-way-forward" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/07/misfire/#finding-a-way-forward">Finding A Way Forward</a></h2>
<p>The most generous take I can muster is that the TAG's work is half-done. Calling on vendors to drop third-party cookies has the virtue of being technical and actionable, properties I believe all TAG writing should embody.  But having looked deeply at the situation, the TAG should have also called on browser vendors to support further reform along several axes — particularly vendors that also make native OSes.</p>
<p>First, if the TAG is serious about preventing tracking and improving the web ecosystem, it should call on all OS vendors <a href="https://open-web-advocacy.org/blog/in-app-browsers-the-worst-erosion-of-user-choice-you-havent-heard-of/">to prohibit the use of &quot;in-app browsers&quot;</a> when displaying third-party content within native apps.</p>
<p>It is not sufficient to <a href="https://webkit.org/blog/10882/app-bound-domains/">prevent JavaScript injection</a> because the largest native apps can simply convince the sites to include their scripts directly. For browser-based tracking attenuation to be effective, these side-doors must be closed. Firms grandstanding about browser privacy features without ensuring users can reliably enjoy the protections of their browser need to do better. The TAG is uniquely positioned to call for this erosion of privacy and the web ecosystem to end.</p>
<p>Next, the TAG should have outlined the limits of technical approaches to attenuating data collection. It should also call on browser vendors to adopt scale-based interventions (rather than <a href="https://www.zdnet.com/article/apple-declined-to-implement-16-web-apis-in-safari-due-to-privacy-concerns/">absolutism</a>) in mitigating high-entropy API use.<sup class="footnote-ref"><a href="https://infrequently.org/2024/07/misfire/#fn-but-does-it-scale-5" id="fnref-but-does-it-scale-5">5</a></sup> The TAG should go first in moving past debates that don't acknowledge impossibilities in removing all reidentification, and encourage vendors to do the same. There's no solution to the privacy puzzle that can be solved by the purchase of a new phone, and the TAG should be clarion about what <em>will</em> end our privacy nightmare: privacy laws worth a damn.</p>
<p>Lastly, the TAG should highlight discrepancies between privacy marketing and the failure of vendors to push for strong privacy laws and enforcement. Because the threat model of privacy intrusion renders solely techincal interventions ineffective on long timeframes, this is the rare case in which the TAG should push past providing technical advice.</p>
<p>The TAG's role is to explain complex things with rigor and signpost credible ways forward. It has not done that yet regarding third-party cookies, but it's not too late.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-past-service-1" class="footnote-item"><p>Praise, as well as concern, in this post is specific to today's TAG's, not the output of the group <a href="https://infrequently.org/2012/12/reforming-the-w3c-tag/">while I served</a>. I surely got a lot of things wrong, and the current TAG is providing a lot of value. My hope here is that it can extend this good work by expanding its new Finding. <a href="https://infrequently.org/2024/07/misfire/#fnref-past-service-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-also-2" class="footnote-item"><p>Also, <a href="https://www.theregister.com/2024/07/30/googles_cookie_w3c_criticism/">James Roswell</a> can go suck eggs. <a href="https://infrequently.org/2024/07/misfire/#fnref-also-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-a-digression-on-native-apps-3" class="footnote-item"><p>It's neither here nor there, but the TAG <em>also</em> failed in these posts to encourage users and developers to move their use of digital technology into real browsers and out of native apps which invasively track and fingerprint users to a degree web adtech vendors only fantasize about.</p>
<p>A balanced finding would call on Apple to stop stonewalling the technologies needed to bring users to safer waters, <a href="https://caniuse.com/?search=beforeinstallprompt">including PWA installation prompts.</a> <a href="https://infrequently.org/2024/07/misfire/#fnref-a-digression-on-native-apps-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-a-truly-private-browser-4" class="footnote-item"><p>As part of the drafting of the <a href="https://www.w3.org/2001/tag/doc/unsanctioned-tracking/">2015 finding on Unsanctioned Web Tracking</a>, the then-TAG (myself included) spent a great deal of time working through the details of potential fingerprinting vectors. What we came to realise was that only the <a href="https://www.torproject.org/">Tor Browser</a> had done the work to credibly analyse fingerprinting vectors and produce a coherent threat model. To the best of my knowledge, that remains true today.</p>
<p>Other vendors continue to publish <a href="https://webkit.org/tracking-prevention-policy/">gussied-up marketing documents</a> and <a href="https://webkit.org/blog/15697/private-browsing-2-0/">stroppy blog posts</a> that purport to cover the same ground, but consistently fail to do so. It's <em>truly</em> objectionable that those same vendors also prevent users from choosing disciplined privacy-focused browsers.</p>
<p>To understand the difference, we can do a small thought experiment, enumerating what would be necessary to sand off currently-identifiable attributes of individual users. Because only 31 or 32 bits are needed to uniquely identify anybody (often less), we want a high safety factor. This means bundling users into very large crowds by removing distinct observable properties. To sand off variations between users, a truly private browser might:</p>
<ul>
<li>Run the entire browser in a VM in order to:
<ul>
<li>Cap the number of CPU cores, frequency, and centralise on a single instruction set (e.g., emulating ARM when running on x86). Will likely result in a 2-5x slowdown.</li>
<li>Ensure (high) fixed latency for all disk access.</li>
<li>Set a uniform (low) cap on total memory.</li>
</ul>
</li>
<li>Disable hardware acceleration for all graphics and media.</li>
<li>Disable JIT. Will slow JavaScript by 3-10x.</li>
<li>Only allow a fixed set of fonts, screen sizes, pixel densities, gamuts, and refresh rates; no more resizing browsers with a mouse. The web will pixelated and drab and animations will feel choppy.</li>
<li>Remove most accessibility settings.</li>
<li>Remove the ability to install extensions.</li>
<li>Eliminate direct typing and touch-based interactions, as those can leak timing information that's unique.</li>
<li>Run all traffic through Tor or a similarly high-latency VPN egress nodes.</li>
<li>Disable all reidentifying APIs (no more web-based video conferencing!)</li>
</ul>
<p>Only the Tor project is shipping a browser anything like this today, and it's how you can tell that most of what passes for &quot;privacy&quot; features in other browsers are anti-annoyance and anti-creep-factor interventions; they matter, but won't end the digital panopticon. <a href="https://infrequently.org/2024/07/misfire/#fnref-a-truly-private-browser-4" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/07/misfire/#fnref-a-truly-private-browser-4:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-but-does-it-scale-5" class="footnote-item"><p>It's not a problem that sign-in flows need third-party cookies today, but it <em>is</em> a problem that they're used for pervasive tracking.</p>
<p>Likewise, the privacy problems inherent in email collection or camera access or filesystem folders aren't absolute, they're related to scale of use. There are important use-cases that demand these features, and computers aren't going to stop supporting them. This means the debate is only whether or not users can use the web to meet those needs. Folks who push an absolutist line are, in effect, working against the web's success. This is anti-user, as the alternatives are generally much more invasive native apps.</p>
<p>Privacy problems arise at scale and across time. Browsers should be doing more to discourage high-quality reidentifiaction across cache clearing and in ways that escalate with risk. The first site you grant camera access isn't the issue; it's the 10th. Similarly, speed bumps should be put in place for use of reidentifying APIs on sites across cache clearing where possible.</p>
<p>The TAG can be instrumental is calling for this sort of change in approach. <a href="https://infrequently.org/2024/07/misfire/#fnref-but-does-it-scale-5" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Why Browsers Get Built</title>
    <link href="https://infrequently.org/2024/03/why-browsers-get-built/"/>
    <updated>2024-03-10T00:00:00Z</updated>
    <id>https://infrequently.org/2024/03/why-browsers-get-built/</id>
    <content type="html"><![CDATA[
      <p>There are only two-and-a-half reasons to build a browser, and they couldn't be more different in intent and outcome, even when they look superficially similar. Learning to tell the difference is helpful for browser project managers and engineers, but also working web developers who struggle to develop <a href="https://en.wikipedia.org/wiki/Theory_of_Change">theories of change</a> for affecting browser teams.</p>
<p>Like <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">Platform Adjacency Theory</a> and <a href="https://infrequently.org/2021/07/the-core-web-loop/">The Core Web Platform Loop</a>, this post started<sup class="footnote-ref"><a href="https://infrequently.org/2024/03/why-browsers-get-built/#fn-why-now-1" id="fnref-why-now-1">1</a></sup> as a set of framing devices that I've been sketching on whiteboards for the best part of a decade. These lenses aren't perfect, but they provide starting points for thinking about the complex dynamics of browsers, <abbr title="Operating Systems">OSes</abbr>, &quot;native&quot; platforms, and the standards-based web platform.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#web-as-platform">Web As Platform</a><ul><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits">Distinguishing Traits</a></li></ul></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#the-os-agenda">The OS Agenda</a><ul><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#bridges">Browsers as Bridges</a></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#moats">Browsers as Moats</a></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#tipping-points">Tipping Points</a></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits-1">Distinguishing Traits</a></li></ul></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#searchbox-pirates">Searchbox Pirates</a><ul><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits-2">Distinguishing Traits</a></li></ul></li><li><a href="https://infrequently.org/2024/03/why-browsers-get-built/#implications">Implications</a></li></ul></nav>
<p>The reasons to build browsers are most easily distinguished by the <abbr title="Operating Systems">OSes</abbr> they support and the size and composition of their teams (&quot;platform&quot; vs. &quot;product&quot;). Even so, there are subtleties that throw casual observers for a loop. In industrial-scale engineering projects like browser construction, <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#headcount-is-destiny">headcount is destiny</a>, but it isn't the whole story.</p>
<h2 id="web-as-platform" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#web-as-platform">Web As Platform</a></h2>
<p>This is simultaneously the simplest and most vexing reason to build a browser.</p>
<p>Under this logic, browsers are strategically important to a broader business, and investments in platforms are investments in their future competitiveness compared with other platforms, not just other browsers. But none of those investments come good until the project has <em>massive</em> scale.</p>
<p>This strategy is exemplified by the ambitions of Netscape, crisply captured by Andreesen's quip that the goal was to <a href="https://cyber.harvard.edu/msdoj/transcript/summaries1.html#:~:text=%C2%B7%20Bill%20Gates%20wasn%27t%20the%20only%20corporate%20executive%20threatening%20a%20rival.%20Mark%20Andreessen%20was%20quoted%20as%20saying%20that%20Netscape%20would%20%22reduce%20Windows%20to%20a%20set%20of%20poorly%20debugged%20device%20drivers.%22%20Barksdale%20shrugged%20off%20these%20and%20other%20such%20comments%20as%20a%20young%20man%20making%20jokes.">render Windows <em>&quot;a poorly debugged set of device drivers&quot;</em>.</a></p>
<p>The idea is that the web is where the action is, and that the browser winning more user <a href="https://hbr.org/2016/09/know-your-customers-jobs-to-be-done">Jobs To Be Done</a> follows from increasing the web platform's capability. This developer-enabling flywheel aims to liberate computing from any single <abbr title="Operating System">OS</abbr>, supporting a services model.</p>
<p>A Web As Platform play depends on <a href="https://infrequently.org/2020/06/platform-adjacency-theory/">credibly keeping up with expansions in underlying <abbr title="Operating System">OS</abbr> features.</a> The goal is to deliver safe portable, interoperable, and effective versions of important capabilities at a fast enough clip to maintain faith in the web as a viable ongoing investment.</p>
<p>In some sense it's a <a href="https://infrequently.org/2021/07/the-core-web-loop/">confidence-management exercise</a>. A Web As Platform endgame requires the platform increases expressive capacity year over year. It must do as many new things each year as new devices can, even if the introduction of those features is delayed for the web by several years; the price of standards.</p>
<p>Platform-play browsers aim to grow and empower the web ecosystem, rather than contain it or treat it as a dying legacy. Examples of this strategic orientation include Netscape, Mozilla (before it lost the plot), Chrome, and Chromium-based Edge (on a good day).</p>
<h3 id="distinguishing-traits" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits">Distinguishing Traits</a></h3>
<ul>
<li>Ship on many <abbr title="Operating Systems">OSes</abbr> and not just those owned by the sponsor</li>
<li>Large platform teams (&gt;200 people and/or &gt;40% of the browser team)</li>
<li>Visible, consistent investments in API leadership and capability expansion</li>
<li>Balanced benchmark focus</li>
<li>Large standards engagement footprint</li>
</ul>
<h2 id="the-os-agenda" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#the-os-agenda">The <abbr title="Operating System">OS</abbr> Agenda</a></h2>
<p>There are two primary tactical modes of this strategic posture, both serving the same goal: to make an operating system look good by enabling a corpus of web content to run well on it while maintaining a competitive distance between the <em>preferred</em> (i.e., native, <abbr title="Operating System">OS</abbr>-specific) platform and the hopefully weaker web platform.</p>
<p>The two sub-variants differ in ambition owing to the market positions of their <abbr title="Operating System">OS</abbr> sponsors.</p>
<p></p><figure><picture style="--lqip: 466020" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/03/why-browsers-get-built/moat-with-bridge-med.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/03/why-browsers-get-built/moat-with-bridge-med.webp" alt="OSes treat browsers they sponsor as bridges or moats, but never the main object." style="aspect-ratio: 1000 / 700" class="preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption><a href="https://unsplash.com/photos/aV3kUuXwvQk" class="credit">Photo by Paul Arky</a><br /></figcaption>      </figure><p></p>
<h3 id="bridges" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#bridges">Browsers as Bridges</a></h3>
<p><abbr title="Operating Systems">OSes</abbr> deploy browsers as a bridge for users <em>into</em> their environment when they're underdogs or fear disruption.</p>
<p>Of course, it would be <em>better</em> from the <abbr title="Operating System">OS</abbr> vendor's perspective if everyone simply wrote software specifically tailored to their proprietary platform, maximising <abbr title="Operating System">OS</abbr> feature differentiation. But smart vendors also know that's not possible when an <abbr title="Operating System">OS</abbr> isn't dominant.</p>
<p><abbr title="Operating System">OS</abbr> challengers, therefore, strike a bargain. For the price of developing a browser, they gain the web's corpus of essential apps and services, serving to &quot;de-risk&quot; the purchase of a niche device by offering broad compatibility with existing software through the web. If they do a good job, a conflicted short-term investment can yield enough browser share to enable a future turn towards moat tactics (see below). Examples include Internet Explorer 3-6 as well as Safari on Mac <abbr title="Operating System">OS</abbr> X and the first iPhone.<sup class="footnote-ref"><a href="https://infrequently.org/2024/03/why-browsers-get-built/#fn-heel-turns-2" id="fnref-heel-turns-2">2</a></sup></p>
<p>Conversely, incumbents fearing disruption may lower their API drawbridges and allow the web's power to expand far enough that the incumbent can gain share, even if it's not for their favoured platform; the classic example here being Internet Explorer in the late 90s. Once Microsoft knew it had Netscape well and truly beat, it simply disbanded the <abbr title="Microsoft Internet Explorer">IE</abbr> team, leaving the slowly rusting husk of <abbr title="Microsoft Internet Explorer">IE</abbr> to decay. And it would have worked, too, if it weren't for those pesky Googlers pushing IE6 beyond what was &quot;possible&quot;!</p>
<h3 id="moats" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#moats">Browsers as Moats</a></h3>
<p>Without meaningful regulation, powerful incumbents can use anticompetitive tactics to suppress the web's potential to disrupt the <abbr title="Operating System">OS</abbr> and tilt the field towards the incumbent's proprietary software ecosystem.</p>
<p>This strategy works by maintaining sufficient browser share to influence developer choices while never allowing the browser team to deliver features sufficient to disrupt <abbr title="Operating System">OS</abbr>-specific alternatives.</p>
<p>In practice, moats are arbitrage on the unwillingness of web developers to understand or play the game, e.g. by loudly demanding timely features or recommending better browsers to users. Incumbents know that web developers are easily convinced to avoid <em>&quot;non standard&quot;</em> features and are happy to invent excuses for them. It's cheap to add a few features here and there to show you're <em>&quot;really trying,&quot;</em> despite underfunding browser teams so much they can never do more than a glorified PR for the <abbr title="Operating System">OS</abbr>. This was the strategy behind <abbr title="Microsoft Internet Explorer">IE</abbr> 7-11 and EdgeHTML. Even relatively low share browsers can serve as effective moats if they can't be supplanted by competitive forces.</p>
<p>Apple has perfected the strategy, preventing competitors from even <em>potentially</em> offering disruptive features. This adds powerfully to the usual moat-digger's weaponisation of consensus processes. Engineering stop-energy in standards and quasi-standards bodies is nice, but it is <em>so</em> much more work than simply denying anyone the ability to ship the features that might threaten the proprietary agenda.</p>
<h3 id="tipping-points" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#tipping-points">Tipping Points</a></h3>
<p>Bridge and moat tactics appear very different, but the common thread is control with an intent to suppress web platform expansion. In both cases, the <abbr title="Operating System">OS</abbr> will task the browser team to heavily prioritise integrations with the latest <abbr title="Operating System">OS</abbr> and hardware features at the expense of more broadly useful capabilities — e.g. shipping &quot;notch&quot; CSS and &quot;force touch&quot; events while neglecting Push.</p>
<p>Browser teams tasked to build bridges can grow quickly and have remit that <em>looks</em> similar to a browser with a platform agenda. Still, the overwhelming focus starts (and stays) on <em>existing</em> content, seldom providing time or space to deliver powerful new features to the Web. A few brave folks bucked this trend, using the fog of war to smuggle out powerful web platform improvements under a more limited bridge remit; particularly the <abbr title="Microsoft Internet Explorer">IE</abbr> 4-6 crew.</p>
<p>Teams tasked with defending (rather than digging) a moat will simply be starved by their <abbr title="Operating System">OS</abbr> overlords. Examples include <abbr title="Microsoft Internet Explorer">IE</abbr> 7+ and Safari from 2010 onward. It's the simplest way to keep web developers from getting uppity without leaving fingerprints. The &quot;soft bigotry of low expectations&quot;, to quote a catastrophic American president.</p>
<h3 id="distinguishing-traits-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits-1">Distinguishing Traits</a></h3>
<ul>
<li>Shipped only to the sponsor's <abbr title="Operating Systems">OSes</abbr></li>
<li>Browser versions tied to <abbr title="Operating System">OS</abbr> versions</li>
<li>Small platform teams (&lt;100 people and/or &lt;30% of the browser team)</li>
<li>Skeleton standards footprint</li>
<li>Extreme focus on benchmarks of <em>existing</em> content</li>
<li>Consistent developer gaslighting regarding new capabilities</li>
<li>Anti-competitive tactics against competitors to maintain market share</li>
<li>Inconsistent feature leadership, largely focused on highlighting new <abbr title="Operating System">OS</abbr> and hardware features</li>
<li>Lagging quality</li>
</ul>
<h2 id="searchbox-pirates" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#searchbox-pirates">Searchbox Pirates</a></h2>
<p>This is the &quot;half-reason&quot;; it's not so much a strategic posture as it is environment-surfing.</p>
<p>Over the years, many browsers that provide little more than searchboxes atop someone else's engine have come and gone. They lack staying power because their teams lack the skills, attitudes, and management priorities necessary to avoid being quickly supplanted by a fast-following competitor pursuing one of the other agendas.</p>
<p>These browsers also tend to be short-lived because they do not build platform engineering capacity. Without agency in most of their codebase, they either get washed away in unmanaged security debt, swamped by rebasing challenges (i.e., a failure to &quot;work upstream&quot;). They also lack the ability to staunch bleeding when their underlying engine fails to implement table-stakes features, which leads to lost market share.</p>
<p>Historical examples have included UC Browser, and more recently, the current crop of &quot;secure enterprise browsers&quot; (Chromium + keyloggers). Perhaps more controversially, I'd include Brave and Arc in this list, but their engineering chops make me think they could cross the chasm and choose to someday become platform-led browsers. They certainly have leaders who understand the difference.</p>
<h3 id="distinguishing-traits-2" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#distinguishing-traits-2">Distinguishing Traits</a></h3>
<ul>
<li>Shipped to many <abbr title="Operating Systems">OSes</abbr></li>
<li>Tiny platform teams (&lt;20 people or &lt;10% of the browser team)</li>
<li>Little benchmark interest or focus</li>
<li>No platform feature leadership</li>
<li>No standards footprint</li>
<li>Platform feature availability lags the underlying engine (e.g., UI and permissions not hooked up)</li>
<li>Platform potentially languishes multiple releases behind &quot;upstream&quot;</li>
</ul>
<h2 id="implications" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/03/why-browsers-get-built/#implications">Implications</a></h2>
<p>This model isn't perfect, but it has helped me tremendously in reliably predicting the next moves of various browser players, particularly regarding standards posture and platform feature pace.<sup class="footnote-ref"><a href="https://infrequently.org/2024/03/why-browsers-get-built/#fn-the-mozilla-conundrum-3" id="fnref-the-mozilla-conundrum-3">3</a></sup></p>
<p>The implications are only sometimes actionable, but they can help us navigate. Should we hope that a vendor in a late-stage browser-as-moat crouch will suddenly turn things around? Well, that depends on the priorities and fortunes of the <em><abbr title="Operating System">OS</abbr></em>, which dictate the strategy of their browser team.</p>
<p>Similarly, a Web As Platform strategy will maximise a browser's reach and its developers' potential, albeit at the occasional expense of end-user features.</p>
<p>The most important takeaway for developers may be what this model implies about browser choice. Products with an <abbr title="Operating System">OS</abbr>-first agenda are always playing second fiddle to a larger goal that does not put web developers first, second, or even third. Coming to grips with this reality lets us more accurately recommend browsers to users that align with our collective interests in a vibrant, growing Web.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-why-now-1" class="footnote-item"><p>I hadn't planned to write this now, but an unruly footnote in an upcoming post, along with <a href="https://fberriman.com/blog/">Frances'</a> constant advice to break things up, made me realise that I already had 90% of it of ready. <a href="https://infrequently.org/2024/03/why-browsers-get-built/#fnref-why-now-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-heel-turns-2" class="footnote-item"><p><abbr title="Microsoft Internet Explorer">IE</abbr> and iOS Safari demonstrate the capacity of <abbr title="Operating System">OS</abbr> vendors to burn bridges, stranding web developers in an unattractive bind through of disinvestment in browsers they control which retain <a href="https://infrequently.org/2024/03/why-browsers-get-built/#moats">blocking market share.</a></p>
<p>As a result, it is not fear of engine monoculture that keeps me up at night, but rather the difficulty of displacing entrenched browsers from vendors with a proprietary agenda. <a href="https://infrequently.org/2024/03/why-browsers-get-built/#fnref-heel-turns-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-the-mozilla-conundrum-3" class="footnote-item"><p>Modern-day Mozilla presents a puzzle within this model.</p>
<p>In theory, Mozilla's aims and interests align with growing the web as a platform; expanding its power to enable a larger market for browsers, and through it, a larger market for Firefox.</p>
<p>In practice, that's not what's happening. Despite <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/">investing almost everything it makes back into browser development</a>, Mozilla has also begun to slow-walk platform improvements. It <a href="https://www.fastcompany.com/90597411/mozilla-firefox-no-ssb-pwa-support">walked away from PWAs</a> and has continued to spread FUD about device APIs and other features that would indicate an appetite for an expansive vision of the platform.</p>
<p>In a sense, it's playing the <abbr title="Operating System">OS</abbr> Agenda, but without an <abbr title="Operating System">OS</abbr> to profit from or a proprietary platform to benefit with delay and deflection. This is vexing, but perhaps expected within an organisation that has entered a revenue-crunch crouch. Another way to square the circle is to note that the <a href="https://www.mozilla.org/en-US/about/manifesto/details/">Mozilla Manifesto</a> doesn't actually speak about the web <em>at all</em>. If the web is just another fungible application running atop the internet (which the manifesto <em>does</em> centre), then it's fine for the web to be frozen in time, or even shrink.</p>
<p>Still, Mozilla leadership should be thinking hard about the point of maintaining an engine. Is it to hold the coats of proprietary-favouring <abbr title="Operating System">OS</abbr> vendors? Or to make the web a true competitor? <a href="https://infrequently.org/2024/03/why-browsers-get-built/#fnref-the-mozilla-conundrum-3" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Home Screen Advantage</title>
    <link href="https://infrequently.org/2024/02/home-screen-advantage/"/>
    <updated>2024-02-25T00:00:00Z</updated>
    <id>https://infrequently.org/2024/02/home-screen-advantage/</id>
    <content type="html"><![CDATA[
      <aside class="update">
<p><strong>Update:</strong>  OWA is out with an <a href="https://letter.open-web-advocacy.org/">open letter appealing to Apple to do better.</a> If you care about the future of the web, I encourage you to sign it, particularly if you live in the EU or build products for the common market.</p>
</aside>
<p>After weeks of confusion and chaos, Apple's plan to kneecap the web <a href="https://open-web-advocacy.org/blog/its-official-apple-kills-web-apps-in-the-eu/">has crept into view,</a> menacing a PWApocalypse as the March 6th deadline approaches for compliance with the EU's Digital Markets Act (DMA).</p>
<p></p><figure><picture style="--lqip: -174557" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/02/home-screen-advantage/SW4-SE-YavinOrbit3.jpg" alt="The view from Cupertino." style="aspect-ratio: 608 / 256" class="preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>The view from Cupertino.</figcaption>      </figure><p></p>
<p>The DMA requires Apple to open the iPhone to competing app stores, and its lopsided proposal for &quot;enabling&quot; them is <a href="https://on.ft.com/3wsiYZd">getting most of the press.</a> But Apple knows it has native stores right where it wants them. Cupertino's <a href="https://www.theverge.com/2024/1/25/24050696/epic-games-tim-sweeney-apple-app-store-response">noxious requirements</a> will take years to litigate. Meanwhile, potential competitors are only that.</p>
<p>But Cupertino can't delay the DMA's other mandate: <a href="https://www.theverge.com/2024/1/25/24050478/apple-ios-17-4-browser-engines-eu">real browsers,</a> downloaded from Apple's own app store. Since it can't bar them outright, it's trying to raise costs on competitors and lower their potential to disrupt Apple's cozy monopoly. How? By geofencing browser choice and kneecapping web apps, all while gaslighting users about who is breaking their web apps.</p>
<p>The immediate impact of iOS 17.4 in the EU will be broken apps and lost data, affecting schools, governments, startups, gamers, and anyone else with the temerity to look outside the one true app store for even a second. None of this is required by the DMA, as demonstrated by continuing presence of PWAs and the important features they enable on Windows and Android, both of which are in the same regulatory boat.</p>
<p>The data loss will be catastrophic for many, as will the removal of foundational features. Here's what the landscape looks like today vs. what Apple is threatening:</p>
<style>
  #feature-list {
    & td:not(:first-of-type) {
      text-align: center;
    }

    & thead td:not(:first-of-type),
      thead td:not(:last-of-type) {
        padding: 0.3rem;
      }
  }
</style>
<table class="summary" style="margin: auto; min-width: 75%;" id="feature-list">  
  <thead>
    <tr>
      <td>PWA Capability</td>
      <td style="text-align: center;">Windows</td>
      <td style="text-align: center;">Android</td>
      <td style="text-align: center;">iOS 17.3</td>
      <td style="text-align: center;">iOS 17.4</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><a href="https://web.dev/learn/pwa/app-design">App-like UI</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/ux">Settings Integration</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://web.dev/articles/storage-for-the-web">Reliable Storage</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://web.dev/explore/notifications">Push Notifications</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://developer.chrome.com/docs/capabilities/web-apis/badging-api">Icon Badging</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target">Share-to PWA</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/How_to/Expose_common_actions_as_shortcuts">App Shortcuts</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
    <tr>
      <td><a href="https://developer.chrome.com/docs/capabilities/fugu-showcase">Device APIs</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
  </tbody>
</table>
<p>Apple's support for powerful web apps wasn't stellar, but this step in the wrong direction will <em>just so happen</em> to render PWAs useless to worldwide businesses looking to reach EU users.</p>
<p>Apple's interpretation of the DMA <em>appears</em> to be that features not available on March 6th don't need to be shared with competitors, and it doesn't want to share web apps. The solution almost writes itself: sabotage PWAs ahead of the deadline and give affected users, businesses, and competitors minimal time to react.</p>
<p>Cupertino's not just trying to vandalise PWAs and critical re-engagement features for Safari; it's working to prevent <em>any</em> browser from <em>ever</em> offering them on iOS. If Apple succeeds in the next two weeks, it will cement a future in which the mobile web will never be permitted to grow beyond marketing pages for native apps.</p>
<p>By hook or by crook, Apple's going to maintain its home screen advantage.</p>
<p>The business goal is obvious: force firms back into the app store Apple taxes and out of the only ecosystem it can't — <a href="https://www.theverge.com/2023/10/26/23933206/google-apple-search-deal-safari-18-billion">at least not directly.</a> Apple's <a href="https://developer.apple.com/support/dma-and-apps-in-the-eu#8">justifications range from unfalsifiable smokescreens to blatant lies,</a> but to know it you have to have a background in browser engineering and the <a href="https://eur-lex.auropa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022R1925&amp;qid=1708824200885">DMA's legalese.</a> The rest of this post will provide that context. Apologies in advance for the length.</p>
<p>If you'd like to stop reading here, take with you the knowledge that Cupertino's attempt to scuttle PWAs under cover of chaos is exactly what it appears to be: a shocking attempt to keep the web from <em>ever</em> emerging as a true threat to the App Store and <a href="https://www.theregister.com/2024/02/16/apple_web_apps/">blame regulators for Apple's own malicious choices.</a></p>
<p>And they just might get away with it if we don't all <a href="https://open-web-advocacy.org/apple-attempts-killing-webapps/">get involved ASAP.</a></p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#chaos-monkey-business">Chaos Monkey Business</a></li><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#but-wait!-there's-more!">But Wait! There's More!</a><ul><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#what's-at-risk%3F">What's At Risk?</a></li><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#not-with-a-bang%2C-but-with-a-beta">Not With A Bang, But With A Beta</a></li></ul></li><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#lies%2C-damned-lies%2C-and-%22still%2C-we-regret...%22">Lies, Damned Lies, and &quot;Still, we regret...&quot;</a><ul><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#the-point">The Point</a></li></ul></li><li><a href="https://infrequently.org/2024/02/home-screen-advantage/#the-mask-is-off">The Mask Is Off</a></li></ul></nav>
<h2 id="chaos-monkey-business" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#chaos-monkey-business">Chaos Monkey Business</a></h2>
<p>Two weeks ago, Apple sprung its <a href="https://www.wired.com/story/developers-revolt-apple-dma/">EU Digital Markets Act (DMA) compliance plans on the world as a <em>fait accomplis</em>.</a></p>
<p>The last-minute unveil after months of radio silence were calculated to give competitors minimal time to react to the complex terms, conditions, and APIs. This tactic tries to set Apple's proposal as a negotiating baseline, forcing competitors to burn time and money arguing down plainly unacceptable terms before they can enter the market.</p>
<p>For native app store hopefuls, this means years of expensive disputes before they can begin to access an artificially curtailed market. This was all wrapped in <a href="https://www.apple.com/newsroom/2024/01/apple-announces-changes-to-ios-safari-and-the-app-store-in-the-european-union/#:~:text=the%20best%2C%20most%20secure%20experience%20possible%20for%20EU%20users.-,The%20new%20options%20for%20processing%20payments%20and%20downloading%20apps%20on%20iOS,the%20EU.%20Even%20with%20these%20safeguards%20in%20place%2C%20many%20risks%20remain.,-Developers%20can%20learn%20about%20these%20changes%20on%20the%20Apple">a peevish, belligerant presentation,</a> which the good folks over at <a href="https://theplatformlaw.blog/2024/01/26/when-apple-takes-the-european-commission-for-fools-an-initial-overview-of-apples-new-terms-and-conditions-for-ios-app-distribution-in-the-eu/">The Platform Law Blog have covered in depth.</a></p>
<p>Much of the analysis <a href="https://www.techmeme.com/240125/p30#a240125p30">has focused on the raw deal Apple is offering native app store competitors,</a> missing the forest for the trees: <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/">the threat Apple can't delay by years comes from within.</a></p>
<p>Deep in the sub-basement of Apple's tower of tomfoolery are APIs and policies that purport to enable browser engine choice. If you haven't been working on browsers for 15 years, <a href="https://developer.apple.com/support/alternative-browser-engines/">the terms</a> might seem reasonable, but to these eyes they're <a href="https://techcrunch.com/2024/01/26/apple-dma-webkit/amp/">anything but.</a> OWA <a href="https://open-web-advocacy.org/blog/owa-review-apple-dma-compliance-for-web/">has a lengthy dissection of the tricks Apple's trying to pull.</a></p>
<p></p><figure><picture style="--lqip: -168413" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/02/home-screen-advantage/pray-i-do-not-comply-further.webp" alt="Apple's message of hope and optimism for a better web." style="aspect-ratio: 684 / 538" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Apple's message of hope and optimism for a better web.</figcaption>      </figure><p></p>
<p>The proposals are maximally onerous, but you don't have to take my word for it; here's Mozilla:</p>
<blockquote>
<p>We are ... extremely disappointed with Apple’s proposed plan to restrict the newly-announced BrowserEngineKit to EU-specific apps. The effect of this would be to force an independent browser like Firefox to build and maintain two separate browser implementations — a burden Apple themselves will not have to bear.</p>
<p>Apple’s proposals fail to give consumers viable choices by making it as painful as possible for others to provide competitive alternatives to Safari.</p>
<p>This is another example of Apple creating barriers to prevent true browser competition on iOS.</p>
<p>— <a href="https://www.theverge.com/2024/1/26/24052067/mozilla-apple-ios-browser-rules-firefox">Mozilla spokesperson</a></p>
</blockquote>
<p>The strategy is to raise costs and lower the value of porting browsers to iOS. Other browser vendors have cited exactly these concerns when asked about plans to bring their best products to iOS. Apple's play is to engineer an unusable alternative then cite the lack of adoption to <em>other</em> regulators as proof that mandating real engine choice is unwise.</p>
<p>Instead of facilitating worldwide browser choice in good faith, Apple's working to geofence progress; classic &quot;divide and conquer&quot; stuff, justified with <a href="https://www.theregister.com/2021/05/27/safari_webkit_bug/">serially falsified security excuses.</a> Odious, brazen, and likely in violation of the DMA, but to the extent that it will now turn into a legal dispute, that's a feature (not a bug) from Apple's perspective.</p>
<p>When you're the monopolist, delay is winning.</p>
<h2 id="but-wait!-there's-more!" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#but-wait!-there's-more!">But Wait! There's More!</a></h2>
<p>All of this would be stock <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#apple's-long-standing-policies-are-anti-diversity">FruitCo doing anti-competitive FruitCo things,</a> but they went further, <a href="https://open-web-advocacy.org/blog/did-apple-just-break-web-apps-in-ios17.4-beta-eu/">attempting to silently shiv PWAs and blame regulators for it.</a> And they did it in the dead of the night, silently disabling important features as close to the DMA compliance deadline as possible.</p>
<p>It's challenging, verging on impossible, to read this as anything but <em>extrordinary</em> bad faith, but Apple's tactics require context to understand.</p>
<p>The <a href="https://digital-markets-act.ec.europa.eu/about-dma_en#:~:text=The%20DMA%20entered%20into%20force,and%20provide%20all%20relevant%20information.">DMA came into force in 2022,</a> putting everyone (including Apple) on notice that their biggest platforms and products would probably be &quot;designated&quot;, and after designation, they would have six months to &quot;comply&quot;. The first set of designation decisions <a href="https://theplatformlaw.blog/2023/09/06/european-commission-adopts-first-dma-designation-decisions/">went out last Sept</a>, obligating Android, Windows, iOS, Chrome, and Safari to comply <em>no later</em> than March 6th, 2024.</p>
<p></p><figure><a href="https://digital-markets-act.ec.europa.eu/about-dma_en" alt="Apple tried everything to <a href='https://www.theregister.com/2023/11/02/apple_safari_browser/'>shrink the scope of enforcement</a> and <a href='https://www.theverge.com/2024/1/8/23961923/apple-app-store-appeal-european-union-digital-markets-act-core-platform-service-gatekeeper'>delay compliance,</a> but in the end had the same two-years of notice and six-months warning from designation as everyone else." target="_blank"><picture style="--lqip: 174554" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/02/home-screen-advantage/digital_markets_act_timeline_0.png" alt="Apple tried everything to <a href='https://www.theregister.com/2023/11/02/apple_safari_browser/'>shrink the scope of enforcement</a> and <a href='https://www.theverge.com/2024/1/8/23961923/apple-app-store-appeal-european-union-digital-markets-act-core-platform-service-gatekeeper'>delay compliance,</a> but in the end had the same two-years of notice and six-months warning from designation as everyone else." style="aspect-ratio: 712 / 287" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Apple tried everything to <a href="https://www.theregister.com/2023/11/02/apple_safari_browser/">shrink the scope of enforcement</a> and <a href="https://www.theverge.com/2024/1/8/23961923/apple-app-store-appeal-european-union-digital-markets-act-core-platform-service-gatekeeper">delay compliance,</a> but in the end had the same two-years of notice and six-months warning from designation as everyone else.</figcaption>      </figure><p></p>
<p>A maximally aggressive legal interpretation might try to exploit ambiguity in what it means to comply and when responsibilities <em>actually</em> attach.</p>
<p>Does compliance mean providing open and fair access starting from when iOS and Safari were <em>designated</em>, or does compliance obligation only attach six months later? The DMA's text is not ironclad here:</p>
<blockquote>
<p>10: The gatekeeper shall comply with the obligations laid down in Articles 5, 6 and 7 within 6 months after a core platform service has been listed in the designation decision pursuant to paragraph 9 of this Article.</p>
<p><a href="https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022R1925&amp;qid=1708824200885#003.010">DMA Article 3, Clause 10</a></p>
</blockquote>
<p>Firms looking to comply maliciously might try to remove troublesome features just before a compliance deadline, then argue they don't need to share them with competitors becuse they weren't available before the deadline set in. Apple looks set to argue, contra everyone else subject to the DMA, that the moment from which features must be made interoperable is the end of the fair-warning period, not the date of designation.</p>
<p>This appears to be Apple's play, and it stinks to high heavens.</p>
<h3 id="what's-at-risk%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#what's-at-risk%3F">What's At Risk?</a></h3>
<p>Apple's change isn't merely cosmetic. In addition to immediate data loss, FruitCo's change will destroy:</p>
<ul>
<li>
<p><strong>App-like UI:</strong></p>
<p>Web apps are no longer going to look or work like apps in the task manager, systems settings, or any other surface. Homescreen web apps will be demoted to tabs in the default browser.</p>
</li>
<li>
<p><strong>Reliable storage:</strong></p>
<p>PWAs were the only exemption to Apple's (frankly silly) <a href="https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria#proactive_eviction">seven day storage eviction policy,</a> meaning the last safe harbour for anyone trying to build a serious, offline-first experience just had the rug pulled out from under them.</p>
</li>
<li>
<p><strong>Push Notifications:</strong></p>
<p>Remember how Apple gaslit web developers over Web Push for the best part of a decade? And remember how, when they finally got around to it, <a href="https://webventures.rejh.nl/blog/2024/web-push-ios-one-year/">did a comically inept job?</a> Recall fretting and about how shite web Push Notifications look and work for iOS users? Well, rest easy, because they're going away too.</p>
</li>
<li>
<p><strong>App Icon Badging:</strong></p>
<p>A kissing cousin of Push, Icon Badging allows PWAs to ambiently notify users of new messages, something iOS native apps have been able to do for nearly 15 years.</p>
</li>
</ul>
<p>Removal of one would be a crisis. Together? Apple's engineering the PWApocalypse.</p>
<p>You can't build credible mobile experiences without these features. A social network without notifications? A notetaking app that randomly loses data? Businesses will get the message worldwide: if you want to be on the homescreen and deliver services that aren't foundationally compromised, the only game in town is Apple's app store.</p>
<p>Apple understands even the most aggressive legal theories about DMA timing wouldn't support kneecapping PWAs <em>after</em> March 6th. Even if you believe (as I do) their obligations attached back in September, there's at least an argument to be tested. Cupertino's white-shoe litigators would be laughed out of court and <a href="https://ec.europa.eu/commission/presscorner/detail/en/qanda_20_2349#:~:text=In%20case%20a,systemic%20non%2Dcompliance.">Apple would get fined ridiculous amounts</a> for non-compliance if it denied these features to other browsers after the fair-warning period. To preserve the argument for litigation, it was necessary to do the dirty deed ahead of the last plausible deadline.</p>
<h3 id="not-with-a-bang%2C-but-with-a-beta" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#not-with-a-bang%2C-but-with-a-beta">Not With A Bang, But With A Beta</a></h3>
<p>The first indication something was amiss was a conspicuous lack of APIs for PWA support in the <a href="https://developer.apple.com/documentation/browserenginekit"><code>BrowserEngineKit</code></a> documentation, released Feb 1st alongside Apple's <a href="https://www.apple.com/newsroom/2024/01/apple-announces-changes-to-ios-safari-and-the-app-store-in-the-european-union/">peevish, deeply misleading note</a> that attempted to whitewash malicious compliance in a thin coat of security theatre.</p>
<p>Two days later, after developers inside the EU got their hands on the iOS 17.4 Beta, <a href="https://mastodon.social/@mysk/111857830238574891">word leaked out that PWAs were broken.</a> Nothing about the change was documented in iOS Beta or Safari release notes. Developers filed <a href="https://bugs.webkit.org/show_bug.cgi?id=268643">plaintive bugs</a> and some directly pinged Apple employees, but Cupertino remained shtum. This created panic and confusion as the windows closed for DMA compliance and the inevitable iOS 17.4 final release ahead of March 6th.</p>
<p><lite-youtube videoid="AST12aDGf0Q" videotitle="iOS 17.4 beta: Progressive Web Apps (PWAs) are entirely disabled in the EU" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=AST12aDGf0Q">iOS 17.4 beta: Progressive Web Apps (PWAs) are entirely disabled in the EU</a>              </lite-youtube></p>
<!-- 
beta 1: https://mastodon.social/@mysk/111857830238574891
        https://www.youtube.com/watch?v=AST12aDGf0Q&feature=youtu.be
beta 2: https://mastodon.social/@mysk/111892461059533933
beta 3: https://mastodon.social/@mysk/111926735141742246 
-->
<p><a href="https://mastodon.social/@mysk/111926735141742246">Two more betas followed,</a> but no documentation or acknowledgement of the &quot;bug.&quot; Changes to the broken PWA behavior were introduced, but Apple failed to acknowledge the issue or confirm that it was intentional and therefore likely to persist. After two weeks of <a href="https://open-web-advocacy.org/blog/did-apple-just-break-web-apps-in-ios17.4-beta-eu/">growing panic from web developers</a>, <a href="https://open-web-advocacy.org/blog/its-official-apple-kills-web-apps-in-the-eu/">Apple finally copped to crippling the only open, tax-free competitor to the app store.</a></p>
<p>Apple's Feb 15th statement is a masterclass in deflection and deceit. To understand why requires a deep understanding of browsers internals and how Apple's closed PWA — sorry, <em>&quot;home screen web app&quot;</em> — system for iOS works.</p>
<p><em>TL;DR</em>? Apple's cover story is horseshit, stem to stern. Cupertino ought to be ashamed and web developers are excused for glowing incandescent with rage over being used as pawns; first ignored, then gaslit, and finally betrayed.</p>
<h2 id="lies%2C-damned-lies%2C-and-%22still%2C-we-regret...%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#lies%2C-damned-lies%2C-and-%22still%2C-we-regret...%22">Lies, Damned Lies, and <em>&quot;Still, we regret...&quot;</em></a></h2>
<p>I really, really hate to do this, but <a href="https://en.wikipedia.org/wiki/Brandolini%27s_law">Brandolini's Law</a> dictates that to refute Apple's <a href="https://en.wikipedia.org/wiki/On_Bullshit">bullshit,</a> I'm going to need to go through <a href="https://developer.apple.com/support/dma-and-apps-in-the-eu#8">their gibberish excuses</a> line-by-line to explain and translate.</p>
<blockquote>
<p>Q: Why don’t users in the EU have access to Home Screen web apps?</p>
</blockquote>
<p>Translation: <em>&quot;Why did you break functionality that has been a foundational part of iOS since 2007, but only in the EU?&quot;</em></p>
<blockquote>
<p>To comply with the Digital Markets Act, Apple has done an enormous amount of engineering work to add new functionality and capabilities for developers and users in the European Union — including more than 600 new APIs and a wide range of developer tools.</p>
</blockquote>
<p>Translation: <em>&quot;We're so very tired, you see. All of this litigating to avoid compliance tuckered us right out. Plus, those big meanies at the EU made us do <em>work</em>. It's all very unfair.&quot;</em></p>
<p>It goes without saying, but Apple's burden to add APIs it should have long ago provided for competing native app stores has no bearing whatsoever on its obligation to provide fair access to APIs that browser competitors need. Apple also had the same two years warning as everyone else. It knew this was coming, and 11th hour special pleading has big <em>&quot;the dog ate my homework&quot;</em> energy.</p>
<blockquote>
<p>The iOS system has traditionally provided support for Home Screen web apps by building directly on WebKit and its security architecture. That integration means Home Screen web apps are managed to align with the security and privacy model for native apps on iOS, including isolation of storage and enforcement of system prompts to access privacy impacting capabilities on a per-site basis.</p>
</blockquote>
<p>Finally! A recitation of facts.</p>
<p>Yes, iOS <em>has</em> historically forced a uniquely underpowered model on PWAs, but iOS is not unique in providing system settings integration or providing durable storage or managing PWA permissions. Many OSes and browsers have created the sort of integration infrastructure that Apple describes. These systems leave the question of how PWAs are actually run (and where their storage lives) to the browser that installs them, and the sky has yet to fall. Apple is trying to gussy up preferences and present them as hard requirements without justification.</p>
<p>Apple is insinuating that it can't provide API surface areas to allow the sorts of integrations that others already have. Why? Because it might involve writing a lot of code.</p>
<p><a href="https://support.apple.com/guide/iphone/whats-new-in-ios-17-iphfed2c4091/ios">Bless their hearts.</a></p>
<blockquote>
<p>Without this type of isolation and enforcement, malicious web apps could read data from other web apps and recapture their permissions to gain access to a user’s camera, microphone or location without a user’s consent.</p>
</blockquote>
<p>Keeping one website from abusing permissions or improperly accessing data from another website is what browsers <em>do</em>. It's Job #1.</p>
<p>Correctly separating principals is the very defintion of a &quot;secure&quot; browser. Every vendor (<a href="https://mspoweruser.com/after-ignoring-it-for-6-weeks-apple-starts-testing-fix-for-major-apple-safari-privacy-bug-that-leaks-your-google-id/">save Apple</a>) treats subversion of the <a href="https://en.wikipedia.org/wiki/Same-origin_policy">Same Origin Policy</a> as a showstopping bug to be fixed ASAP. Unbelieveable amounts of engineering go to ensuring browsers overlay stronger sandboxing and more restrictive permissions on top of the universally weaker OS security primitives — iOS very much included.</p>
<p>Browser makers have become masters of origin separation because they run totally untrusted code from all over the internet. Security is paramount because browsers have to be paranoid. They can't just <a href="https://www.darkreading.com/cyberattacks-data-breaches/malicious-apps-millions-downloads-apple-google-app-stores">posture about how store reviews</a> will keep users safe; they have to <em>do the work</em>.</p>
<p>Good browsers separate web apps better than bad ones. It's rich that Apple of all vendors is directly misleading this way. Its decade+ of under-investment in WebKit ensured Safari was less prepared for <a href="https://meltdownattack.com/">Spectre and Meltdown</a> and <a href="https://9to5mac.com/2021/07/14/zero-day-exploit-allowed-solarwinds-hackers-to-extract-login-information-from-ios-devices/">Solar Winds</a> than alternative engines. Competing browsers had invested hundreds of engineer years into more advanced <a href="https://www.chromium.org/Home/chromium-security/site-isolation/">Site Isolation</a>. To this day, Apple's underfunding and coerced engine monoculture put all iOS users at risk.</p>
<p>With that as background, we can start to unpack Apple's garbled claims.</p>
<p>Cupertino is saying that it <em>does not want</em> to create APIs for syncing permission state through the thin shims every PWA-supporting OS uses to make websites first class. It doesn't <em>want</em> to add APIs for attributing storage use, clearing state, toggling notifications, and other common management tasks. This is a <em>preference</em>, but it is not responsive to Apple's DMA obligations.</p>
<p>If those APIs existed, Apple would still have permission management questions to work through, which its misdirections also allude to. But these aren't a problem in practice. Every browser offering PWA support would <em>happily</em> sign up to terms that required accurate synchronization of permission state between OS surfaces and web origins, in exactly the same way they treat cross-origin subversion as a fatal bug to be hot-fixed.</p>
<p>Apple's excusemaking is a mirror of Cupertino's years of scaremongering about alternate browser engine security, only to <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#the-abandonware-problem">take up my proposal more-or-less wholesale when the rubber hit the road.</a></p>
<p>Nothing about this is monumental to build or challenging to manage; FruitCo's just hoping you don't know better. And why would you? The set of people who understand these details generously number in the low dozens.</p>
<blockquote>
<p>Browsers also could install web apps on the system without a user’s awareness and consent.</p>
</blockquote>
<p>Apple know this is a lie.</p>
<p>They retain full control over the system APIs that are called to add icons to the homescreen, install apps, and much else. They can shim in interstitial UI if they feel like doing so. If iOS left this to Safari and did not include these sorts of precautions, those are choices Apple has made and has been given two years notice to fix.</p>
<p>Cupertino seems to be saying <em>&quot;bad things might happen if we continued to do a shit job&quot;</em> and one can't help but agree. However, that's no way out of the DMA's obligations.</p>
<blockquote>
<p>Addressing the complex security and privacy concerns associated with web apps using alternative browser engines would require building an entirely new integration architecture that does not currently exist in iOS and was not practical to undertake given the other demands of the DMA and the very low user adoption of Home Screen web apps.</p>
</blockquote>
<p>[CITATION NEEDED]</p>
<p>Note the lack of data? Obviously this sort of unsubstantiated bluster fails <a href="https://en.wikipedia.org/wiki/Hitchens%27s_razor">Hitchen's Razor</a>, but that's not the full story.</p>
<p>Apple is counting on the opacity of its own web suppression to keep commenters from understanding the game that's afoot. Through an enervating combination of <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#choices%2C-choices">strategic underinvestment</a> and coerced monoculture, Apple created (and still maintains) a huge gap in discoverability and friction for installing web apps vs. their native competition. Stacking the deck for native has taken many forms:</p>
<ul>
<li>
<p>Preventing web apps from gaining distribution in the app store <a href="https://developer.apple.com/app-store/review/guidelines/#4.2">by explicit policy.</a></p>
</li>
<li>
<p><a href="https://developer.apple.com/documentation/webkit/promoting_apps_with_smart_app_banners">&quot;Smart Banners&quot;</a> that let sites easily offer installation of their native counterparts.</p>
</li>
<li>
<p>Steadfast refusal to implement <a href="https://web.dev/articles/promote-install#browser-promotion">analagous features for PWAs</a> or provide competing browsers <a href="https://web.dev/learn/pwa/installation-prompt">the OS and DOM APIs they need to do so.</a></p>
</li>
<li>
<p><a href="https://www.cdc.gov/niosh/mining/content/hearingloss/installPWA.html">Burying Web App installation behind a &quot;Share Sheet&quot; UI</a> that users and developers complain is incredibly hard to discover, <a href="https://documentation.onesignal.com/docs/getting-your-audience-to-add-to-home-screen">forcing site owners to build clunky intersitials.</a></p>
</li>
<li>
<p>Denying competitors the necessary API access to offer better install UI and only providing the underwhelming &quot;Share Sheet&quot; option <a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/">last year,</a> a full <em>15 years</em> after Safari.</p>
</li>
</ul>
<p>This campaign of suppression has been wildly effective. If users don't know they can install PWAs, it's because <em>Safari never tells them</em>, and until this time last year, neither could any other browser. Developers also struggled to justify building them because Apple's repression extended to neglect of critical features, opening and maininting a substantial capability gap.</p>
<p>If PWAs use on iOS is low, that's a consequence of Apple's own actions. On every other OS where I've seen the data, not only are PWAs a success, they are growing rapidly. Perhaps that's why Apple feels a need to mislead by omission and fail to provide data to back their claim.</p>
<blockquote>
<p>And so, to comply with the DMA’s requirements, we had to remove the Home Screen web apps feature in the EU.</p>
</blockquote>
<p>Bullshit.</p>
<p>Apple's embedded argument expands to:</p>
<ul>
<li>
<p>We don't want to comply with the plain-letter language of the law.</p>
</li>
<li>
<p>To avoid that, we've come up with a legal theory of compliance that's favourable to us.</p>
</li>
<li>
<p>To comply with <em>that</em> (dubious) theory, and to avoid doing any of the work we don't want to do, we've been <em>forced</em> to bump off the one competitor we can't tax.</p>
</li>
</ul>
<p>Neat, tidy, and comprised entirely of bovine excrement.</p>
<blockquote>
<p>EU users will be able to continue accessing websites directly from their Home Screen through a bookmark with minimal impact to their functionality. We expect this change to affect a small number of users. Still, we regret any impact this change — that was made as part of the work to comply with the DMA — may have on developers of Home Screen web apps and our users.</p>
</blockquote>
<p>Translation: <em>&quot;Because fuck you, that's why&quot;</em></p>
<p>The DMA doesn't require Apple to torpedo PWAs.</p>
<p>Windows and Android will continue supporting them just fine. Apple apparently hopes it can convince users to blame regulators for its own choices. Cupertino's counting on the element of surprise plus the press's poorly developed understanding of the situation to keep blowback from snowballing into effective oppostion.</p>
<h3 id="the-point" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#the-point">The Point</a></h3>
<p>There's no possible way to justify a <a href="https://developer.apple.com/support/core-technology-fee/">&quot;Core Technology Fee&quot;</a> tax on an open, interoperable, standardsized platform that competitors would provide secure implementations of for free. What Apple's attempting isn't just some hand-wavey removal of a &quot;low use&quot; feature ([CITATION NEEDED]), it's sabotage of the only credible alternative to its app store monopoly.</p>
<p></p><figure><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2021/08/webkit-ios-deep-dive/epic_v_apple.jpg" alt="A slide from Apple's presentation in Apple v. Epic, attempting to make the claim Epic could have just made a PWA if they didn't like the App Store terms because circa '20 Safari was <em>so</em> capable. <br><br><a href='/2021/04/progress-delayed/'>LOL.</a>" style="aspect-ratio: 2134 / 1164" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>A slide from Apple's presentation in Apple v. Epic, attempting to make the claim Epic could have just made a PWA if they didn't like the App Store terms because circa '20 Safari was <em>so</em> capable. <br /><br /><a href="https://infrequently.org/2021/04/progress-delayed/">LOL.</a></figcaption>      </figure><p></p>
<p>Businesses will get the message: from now on, the only reliable way to get your service under the thumb, or in the notification tray, of the most valuable users in the world is to capitulate to Apple's extortionate App Store taxes.</p>
<p>If the last 15 years are anything to judge by, developers will take longer to understand what's going on, but this is an attempt to pull a <em>&quot;Thoughts on Flash&quot;</em> for the web. Apple's suppression of the web has <a href="https://infrequently.org/2021/04/progress-delayed/">taken many forms</a> over the past decade, but the common thread has been inaction and anti-competitive scuppering of more capable engines. With one of those pillars crumbling, the knives glint a bit more brightly. This is Apple once and for all trying to relegate web development skills to the dustbin of the desktop.</p>
<p>Not only will Apple render web apps unreliable for Safari users, FruitCo is setting up an argument to prevent competitors from ever delivering features that challenge the app store in future. And it doesn't care who it hurts along the way.</p>
<h2 id="the-mask-is-off" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/02/home-screen-advantage/#the-mask-is-off">The Mask Is Off</a></h2>
<p>This is exactly what it looks like: a single-fingered salute to the web and web developers. The removal of features that <a href="https://en.wikipedia.org/wiki/IPhone_OS_1">allowed the iPhone to exist at all.</a> The end of <a href="https://www.macstories.net/stories/before-the-app-store-the-sweet-solution-of-web-apps-and-developers-relentless-passion/">Steve Jobs' promise that you'd be able to make great apps out of HTML, CSS, and JS.</a></p>
<p>For the past few years Apple has gamely sent $1,600/hr lawyers and <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">astroturf lobbyists</a> to argue it didn't need to be regulated. That Apple was really on the developer's side. That even if it overstepped occasionally, it was all in the best interest of users.</p>
<p>Tell that to the millions of EU PWA users about to lose data. Tell that to the public services built on open technology. Tell it to the businesses that will fold, having sweated to deliver compelling experiences using the shite tools Apple provides web developers. Apple's rug pull is anti-user, anti-developer, and anti-competition.</p>
<p>Now we see the whole effort in harsh relief. A web Apple can't sandbag and degrade is one it can't abide. FruitCo's fear and loathing of an open platform it can't tax is palpable. The lies told to cover for avarice are ridiculous — literally, <a href="https://www.etymonline.com/word/ridiculous">&quot;worthy of ridicule&quot;.</a></p>
<p>It's ok to withhold the benefit of the doubt from Safari and Apple. It's ok to be livid. These lies aren't little or white; they're directly aimed at our future. They're designed to influence the way software will be developed and delivered for decades to come.</p>
<p>If you're as peeved about this as I am, go <a href="https://open-web-advocacy.org/apple-attempts-killing-webapps/">join OWA in the fight</a> and help them create the sort of pressure in the next 10 days that might actually stop a monopolist with money on their mind.</p>
<p><em>Thanks to <a href="https://www.kryogenix.org/days/">Stuart Langride</a>, <a href="https://brucelawson.co.uk/">Bruce Lawson</a>, and <a href="https://webventures.rejh.nl/">Roderick Gadellaa</a> for their feedback on drafts of this post.</em></p>

    ]]></content>
  </entry>
  <entry>
    <title>The Performance Inequality Gap, 2024</title>
    <link href="https://infrequently.org/2024/01/performance-inequality-gap-2024/"/>
    <updated>2024-01-31T00:00:00Z</updated>
    <id>https://infrequently.org/2024/01/performance-inequality-gap-2024/</id>
    <content type="html"><![CDATA[
      <p>The global device and network situation continues to evolve, and this series is an effort to provide an an up-to-date understanding for working web developers. So what's changed since last year? And how much HTML, CSS, and (particularly) JavaScript can a new project afford?</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-budget%2C-2024">The Budget, 2024</a><ul><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#javascript-heavy">JavaScript-Heavy</a></li><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#markup-heavy">Markup-Heavy</a></li><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#calculate-your-own">Calculate Your Own</a></li></ul></li><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#situation-report">Situation Report</a><ul><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#mobile">Mobile</a></li><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#desktop">Desktop</a></li></ul></li><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#takeaways">Takeaways</a><ul><li><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-great-branch-mispredict">The Great Branch Mispredict</a></li></ul></li></ul></nav>
<h2 id="the-budget%2C-2024" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-budget%2C-2024">The Budget, 2024</a></h2>
<p>In a departure from previous years, two sets of baseline numbers are presented for first-load under five seconds on 75<sup>th</sup> (P75) percentile devices and networks<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-why-five-seconds-1" id="fnref-why-five-seconds-1">1</a></sup>; one set for JavaScript-heavy content, and another for markup-centric stacks.</p>
<table class="summary" style="margin: auto; min-width: 75%;" id="budgets">  
  <thead>
    <tr>
      <th rowspan="2">Budget @ P75</th>
      <th colspan="3">Markup-based</th>
      <th colspan="3">JS-based</th>
    </tr>
    <tr>
      <th>Total</th>
      <th>Markup</th>
      <th>JS</th>
      <th>Total</th>
      <th>Markup</th>
      <th>JS</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>3 seconds</td>
      <td style="font-weight: bold;">1.4MiB</td>
      <td>1.3MiB</td>
      <td>75KiB</td>
      <td style="font-weight: bold;">730KiB</td>
      <td>365KiB</td>
      <td>365KiB</td>
    </tr>
    <tr>
      <td>5 seconds</td>
      <td style="font-weight: bold;">2.5MiB</td>
      <td>2.4MiB</td>
      <td>100KiB</td>
      <td style="font-weight: bold;">1.3MiB</td>
      <td>650KiB</td>
      <td>650KiB</td>
    </tr>
  </tbody>
</table>
<p>This was data was available via <a href="https://infrequently.org/2022/12/performance-baseline-2023/">last year's update</a>, but was somewhat buried. Going forward, I'll produce both as top-line guidance. The usual caveats apply:</p>
<ul>
<li>Performance is a deep and nuanced domain, and much can go wrong beyond content size and composition.</li>
<li>How sites manage resources after-load can have a big impact on perceived performance.</li>
<li>Your audience may justify more stringent, or more relaxed, limits.</li>
</ul>
<p>Global baselines matter because many teams have low <a href="https://infrequently.org/2022/05/performance-management-maturity/">performance management maturity</a>, and today's popular frameworks – including some that market performance as a feature – <a href="https://infrequently.org/2023/02/the-market-for-lemons/">fail to ward against catastrophic results</a>.</p>
<p><em>Until and unless teams have better data about their audience, the global baseline budget should be enforced.</em></p>
<p>This isn't charity; it's how products stay functional, accessible, and reliable in a market <a href="https://infrequently.org/2023/02/the-market-for-lemons/">awash in bullshit</a>. Limits help teams steer away from complexity and towards tools that generate simpler output that's easier to manage and repair.</p>
<h3 id="javascript-heavy" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#javascript-heavy">JavaScript-Heavy</a></h3>
<p>Since at least 2015, building JavaScript-first websites has been a predictably terrible idea, yet most of the sites I trace on a daily basis remain mired in script.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-lottery-ticket-engineering-2" id="fnref-lottery-ticket-engineering-2">2</a></sup> For these sites, we have to factor in the heavy cost of running JavaScript on the client when describing how much content we can afford.</p>
<p>HTML, CSS, images, and fonts can all be parsed and run at near wire speeds on low-end hardware, but JavaScript is at least three times more expensive, byte-for-byte.</p>
<p>Most sites, even those that aspire to be &quot;lived in&quot;, are generally experienced through short sessions, which means they can't justify much in the way of up-front code. First impressions always matter.</p>
<p></p><figure class="full_wide"><picture style="--lqip: -521501" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/depth-and-frequency-small.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.png" alt="Most sorts of sites have shallow sessions, making up-front script costs hard to justify." style="background: white; padding: 0 1em;; aspect-ratio: 1000 / 455" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>                  <figcaption>Most sorts of sites have shallow sessions, making up-front script costs hard to justify.</figcaption>      </figure><p></p>
<p>Targeting the slower of our two representative devices, and opening only two connections over a P75 network, we can afford ~1.3MiB of compressed content to get interactive in five seconds. A page fitting this budget can afford:</p>
<ul>
<li>650KiB of HTML, CSS, images, and fonts</li>
<li>650KiB of JavaScript</li>
</ul>
<p>If we set the target a more reasonable three seconds, the budget shrinks to ~730KiB, with no more than 365KiB of compressed JavaScript.</p>
<p>Similarly, if we keep the five second target but open five TLS connections, the budget falls to ~1MiB. Sites trying to load in three seconds but which open five connections can afford only ~460KiB total, leaving only ~230KiB for script.</p>
<h3 id="markup-heavy" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#markup-heavy">Markup-Heavy</a></h3>
<p>Sites largely comprised of HTML and CSS can afford a <em>lot</em> more, although CSS complexity and poorly-loaded fonts can still slow things down. Conservatively, to load in five seconds over two connections, we should try to keep content under 2.5MiB, including:</p>
<ul>
<li>2.4MiB of HTML, CSS, images, and fonts, and</li>
<li>100KiB of JavaScript.</li>
</ul>
<p>To hit the three second first-load target, we should aim for a max 1.4MiB transfer, made up of:</p>
<ul>
<li>1.325MiB of HTML, CSS, etc., and</li>
<li>75KiB of JavaScript.</li>
</ul>
<p>These are generous targets. The blog you're reading <a href="https://www.webpagetest.org/video/compare.php?tests=240130_AiDcW6_5QC-r%3A1-c%3A0&amp;thumbSize=200&amp;ival=100&amp;end=full">loads in ~1.2 seconds over a single connection on the target device and network profile. It consumes 120KiB of critical path resources to become interactive, only 8KiB of which is script</a>.</p>
<h3 id="calculate-your-own" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#calculate-your-own">Calculate Your Own</a></h3>
<p>As in years past, you can use <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart/index.html">the interactive estimator</a> to understand how connections and devices impact budgets. This the tool has been updated to let you select from JavaScript-heavy and JavaScript-light content composition and defaults to the updated network and device baseline (see below).</p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart/index.html" alt="<em>Tap to try the interactive version.</em>" target="_blank"><picture style="--lqip: 170714" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/chart.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart.png" alt="<em>Tap to try the interactive version.</em>" style="aspect-ratio: 1224 / 642" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap to try the interactive version.</em></figcaption>      </figure><p></p>
<p>It's straightforward to understand the number of critical path network connections and to eyeball the content composition from DevTools or <a href="https://webpagetest.org/">WebPageTest</a>. Armed with that information, it's possible to use this estimator to quickly understand what sort of first-load experience users at the margins can expect. Give it a try!</p>
<h2 id="situation-report" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#situation-report">Situation Report</a></h2>
<p>These recommendations are not context-free, and folks can reasonably disagree.</p>
<p>Indeed, many critiques are possible. The five second target first load)<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-why-five-seconds-1" id="fnref-why-five-seconds-1:1">1:1</a></sup> is arbitrary. A sample population comprised of all internet users may be inappropriate for some services (in both directions). A methodology of &quot;informed reckons&quot; leaves much to be desired. The methodological critiques write themselves.</p>
<p>The rest of this post works to present the thinking behind the estimates, both to spark more informed points of departure and to contextualise the low-key freakout taking place as <a href="https://web.dev/articles/inp">INP begins to put a price on JavaScript externalities.</a></p>
<p>Another aim of this series is to build empathy. Developers <a href="https://rviscomi.dev/2023/11/a-faster-web-in-2024/">are clearly out of touch with market ground-truth</a>. Building an understanding of the differences in the experiences of the wealthy vs. working-class users can make the privilege bubble's one-way mirror perceptible from the inside.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-self-preservation-3" id="fnref-self-preservation-3">3</a></sup></p>
<h3 id="mobile" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#mobile">Mobile</a></h3>
<p>The &quot;i&quot; in iPhone stands for &quot;inequality&quot;.</p>
<p>Premium devices are largely absent in markets with billions of users thanks to the chasm of global wealth inequality. India's iOS share has <a href="https://economictimes.indiatimes.com/tech/technology/apple-set-to-end-2023-with-7-market-share-for-iphones-in-android-dominated-india/articleshow/103532336.cms?from=mdr">surged to an all-time high of 7%</a> on the back of last-generation and refurbished devices. That's a market of 1.43 billion people where Apple <a href="https://www.counterpointresearch.com/insights/india-smartphone-share/">doesn't even crack the top five in terms of shipments</a>.</p>
<p>The Latin American (LATAM) region, home to more than 600 million people and <a href="https://www.statista.com/topics/7195/smartphone-market-in-latin-america/#topicOverview">nearly 200 million smartphones</a>, shows a <a href="https://www.canalys.com/newsroom/latam-smartphone-market-q3-2023">similar market composition</a>:</p>
<p></p><figure><a href="https://www.counterpointresearch.com/research_portal/counterpoint-quarterly-smartphone-q4-2023/" alt="In LATAM, iPhones make up less than 6% of total device shipments." target="_blank"><picture style="--lqip: 172771" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/latam_share_yoy_counterpoint.webp" alt="In LATAM, iPhones make up less than 6% of total device shipments." style="aspect-ratio: 1513 / 879" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>In LATAM, iPhones make up less than 6% of total device shipments.</figcaption>      </figure><p></p>
<p>Everywhere wealth is unequally distributed, the haves <a href="https://www.statista.com/statistics/512863/smartphones-cell-phones-tablets-and-ereaders-brands-owned-by-affluent-americans/">read about it in Apple News over 5G while the have-nots struggle to get reliable 4G coverage for their Androids.</a> In <a href="https://assets.publishing.service.gov.uk/media/62a1cb0b8fa8f50395c0a0e7/Consumer_purchasing_behaviour_in_the_UK_smartphone_market_-_CMA_research_report_new.pdf">country after country (PDF)</a> the embedded inequality of our societies sorts ownership of devices by price. This, in turn, sorts by brand.</p>
<p>This matters because the properties of devices defines what we can deliver. In the U.S., the term &quot;smartphone dependence&quot; has been coined to describe folks without other ways to access the increasing fraction of essential services only available through the internet. Unsurprisingly, those who can't afford other internet-connected devices, or a fixed broadband subscription, are also likely to buy less expensive smartphones:</p>
<p></p><figure><a href="https://www.pewresearch.org/internet/fact-sheet/mobile/?tabId=tab-011fca0d-9756-4f48-b352-d58f343696bf" alt="undefined" target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/us_smartphone_dependence_pew.webp" alt="Missing alt text" style="aspect-ratio: 1121 / 671" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption></figcaption>      </figure><p></p>
<p>As smartphone ownership and use grow, the frontends we deliver remain mediated by the properties of those devices. The inequality between the high-end and low-end is only growing, even in wealthy countries. What we choose to do in response defines what it means to practice UX engineering ethically.</p>
<h4 id="device-performance" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#device-performance">Device Performance</a></h4>
<p>Extending the SoC performance-by-price series with 2023's data, the picture remains ugly:</p>
<p></p><figure><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments." target="_blank"><picture style="--lqip: 172771" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/single_core_scores.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments." style="padding: 15px; background-color: white;; aspect-ratio: 1438 / 812" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Geekbench 5 single-core scores for 'fastest iPhone', 'fastest Android', 'budget', and 'low-end' segments.</figcaption>      </figure><p></p>
<p>Not only have fruity phones extended their single-core CPU performance lead over contemporary high-end Androids to <em>a four year advantage</em>, the performance-per-dollar curve remains unfavourable to Android buyers.</p>
<p>At the time of publication, the cheapest iPhone 15 Pro (the only device with the A17 Pro chip) is $999 MSRP, while the S23 (using the Snapdrago 8 gen 2) can be had for $860 from Samsung. This nets out to 2.32 points per dollar for the iPhone, but only 1.6 points per dollar for the S23.</p>
<p>Meanwhile, a $175 (new, unlocked) Samsung A24 scores a more reasonable 3.1 points per dollar on single-core performance, but is more than 4.25× slower than the leading contemporary iPhone.</p>
<p>The delta between the fastest iPhones and moderately price new devices rose from 1,522 points last year to 1,774 today.</p>
<p>Put another way, the performance gap between wealthy users and budget shoppers grew more this year (252 points) than the gains from improved chips delivered at the low end (174 points). Inequality is growing faster than the bottom-end can improve. This is particularly depressing because single-core performance tends to determine the responsiveness of web app workloads.</p>
<p>A less pronounced version of the same story continues to play out in multi-core performance:</p>
<p></p><figure><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/multi_core_scores.png" alt="<em>Tap for a larger version.</em><br>Round and round we go: Android ecosystem SoCs are improving, but the Performance Inequality Gap continues to grow. Even the fastest Androids are 18 months (or more) behind equivalently priced iOS-ecosystem devices." target="_blank"><picture style="--lqip: 524122" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/multi_core_scores.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/multi_core_scores.png" alt="<em>Tap for a larger version.</em><br>Round and round we go: Android ecosystem SoCs are improving, but the Performance Inequality Gap continues to grow. Even the fastest Androids are 18 months (or more) behind equivalently priced iOS-ecosystem devices." style="padding: 15px; background-color: white;; aspect-ratio: 1438 / 812" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Round and round we go: Android ecosystem SoCs are improving, but the Performance Inequality Gap continues to grow. Even the fastest Androids are 18 months (or more) behind equivalently priced iOS-ecosystem devices.</figcaption>      </figure><p></p>
<p>Recent advances in high-end Android multi-core performance have closed the previous three-year gap to 18 months. Meanwhile, budget segment devices have finally started to see improvement (<a href="https://infrequently.org/2021/03/the-performance-inequality-gap/#:~:text=The%20good%20news%20is%20that%20this%20will%20change%20rapidly%20in%20the%20next%20few%20years.">as this series predicted</a>), thanks to hand-me-down architecture and process node improvements. That's where the good news ends.</p>
<p>The multi-core performance gap between i-devices and budget Androids grew considerably, with the score delta rising from 4,318 points last year to 4,936 points in 2023.</p>
<p>Looking forward, we can expect high-end Androids to at least stop falling further behind owing to <a href="https://www.androidauthority.com/snapdragon-8-gen-3-dimensity-9300-benchmarked-3395385/">a new focus on performance by Qualcomm's Snapdragon 8 gen 3 and MediaTek's Dimensity 9300 offerings</a>. This change is long, long overdue and will take years to filter down into positive outcomes for the rest of the ecosystem. Until that happens, the gap in experience for the wealthy versus the rest will not close.</p>
<p>iPhone owners experience a different world than high-end Android buyers, and live galaxies apart from the bulk of the market. No matter how you slice it, the performance inequality gap is growing for CPU-bound workloads like JavaScript-heavy web apps.</p>
<h4 id="networks" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#networks">Networks</a></h4>
<p>As ever, 2023 re-confirmed an essential product truth: <a href="https://www.opensignal.com/2023/05/11/poor-connectivity-damages-the-mobile-app-business">when experiences are slow, users engage less.</a> Doing a good job in an uneven network environment requires thinking about connection availability and engineering for resilience. It's always better to avoid testing the radio gods than spend weeks or months appeasing them after the damage is done.</p>
<p>5G network deployment continues apace, but as with the arrival of 4G, it is happening unevenly and in ways and places that exacerbate (rather than lessen) performance inequality.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-5g-lumpiness-4" id="fnref-5g-lumpiness-4">4</a></sup></p>
<p>Data on mobile network evolution is sketchy,<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-a-plea-to-ookla-and-opensignal-5" id="fnref-a-plea-to-ookla-and-opensignal-5">5</a></sup> and the largest error bars in this series' analysis continue to reside in this section. Regardless, we can look industry summaries like the <a href="https://www.gsma.com/mobileeconomy/wp-content/uploads/2023/03/270223-The-Mobile-Economy-2023.pdf">GSMA's report on &quot;The Mobile Economy 2023&quot; (PDF)</a> for a directional understanding that we can triangulate with other data points to develop a strong intuition.</p>
<p>For instance, GSMA predicts that 5G will only comprise half of connections by 2030. Meanwhile, McKinsey <a href="https://www.techtarget.com/whatis/feature/5-Predictions-about-5G-Adoption-in-2021-and-Beyond#:~:text=Regardless%20of%20the,the%205G%20revolution.%22">predicts</a> that high-quality 5G (networks that use 6GHz bands) will only cover a quarter of the world's population by 2030. Regulatory roadblocks are <a href="https://economictimes.indiatimes.com/industry/telecom/telecom-news/itu-reaches-agreement-to-open-new-6-ghz-spectrum-band-for-5g-6g/articleshow/106000126.cms">still being cleared</a>.</p>
<p>As we said in 2021, <em>&quot;<a href="https://infrequently.org/2021/03/the-performance-inequality-gap/#oh-em-gee">4G is a miracle, 5G is a mirage</a>.&quot;</em></p>
<p>This doesn't mean that 4G is one thing, or that it's deployed evenly, or even that the <a href="https://www.opensignal.com/2023/06/29/more-usable-spectrum-boosts-the-4g-and-5g-experience">available spectrum will remain stable</a> within a single generation of radio technology. For example, India's network environment has continued to evolve since the <a href="https://www.kaiostech.com/reliance-jio-became-worlds-fastest-growing-mobile-network/">Reliance Jio revolution</a> that drove 4G into the mainstream and pushed the price of a mobile megabyte down by ~90% on <em>every</em> subcontinental carrier.</p>
<p><a href="https://www.speedtest.net/global-index/india#mobile">Speedtest.net's recent data shows dramatic gains, for example</a>, and <a href="https://www.financialexpress.com/business/industry/mobile-download-speeds-india-moves-up-72-spots-in-global-ranking/3260813/">analysts credit this to improved infrastructure density, expanded spectrum, and back-haul improvements related to the 5G rollout</a> — 4G users are getting better experiences than they did last year <em>because of</em> 5G's role in reducing contention.</p>
<p></p><figure><a href="https://www.speedtest.net/global-index/india#mobile" alt="India's speed test medians are moving quickly, but variance is orders-of-magnitude wide, with 5G penetration below 25% in the most populous areas." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/india_mobile_speedtest_data.webp" alt="India's speed test medians are moving quickly, but variance is orders-of-magnitude wide, with 5G penetration below 25% in the most populous areas." style="aspect-ratio: 646 / 721" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>India's speed test medians are moving quickly, but variance is orders-of-magnitude wide, with 5G penetration below 25% in the most populous areas.</figcaption>      </figure><p></p>
<p>These gains are easy to miss looking only at headline &quot;4G vs. 5G&quot; coverage. Improvements arrive unevenly, with the &quot;big&quot; story unfolding slowly. These effects reward us for looking at P75+, not just means or medians, and intentionally updating priors on a regular basis.</p>
<p>Events can turn our intuitions on their heads, too. Japan is famously well connected. I've personally experienced rock-solid 4G through entire Tokyo subway journeys, <a href="https://en.wikipedia.org/wiki/Roppongi_Station">more than 40m underground</a> and with no hiccups. And yet, the network environment has been largely unchanged by the introduction of 5G. Having provisioned more than adequately in the 4G era, new technology isn't having the same impact from pent-up demand. But despite consistent performance, the quality of service for all users is distributed in a <em>much</em> more egalitarian way:</p>
<p></p><figure><a href="https://www.speedtest.net/global-index/japan#mobile" alt="Japan's network environment isn't the fastest, but is much more evenly distributed." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/japan_mobile_speedtest_data.webp" alt="Japan's network environment isn't the fastest, but is much more evenly distributed." style="aspect-ratio: 645 / 727" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Japan's network environment isn't the fastest, but is much more evenly distributed.</figcaption>      </figure><p></p>
<p>Fleet device composition has big effects, owing to differences in signal-processing compute availability and spectrum compatibility. At a population level, these influences play out slowly as devices age out, but still have impressively positive impacts:</p>
<p></p><figure><a href="https://www.opensignal.com/2023/09/25/users-should-upgrade-their-iphone-to-have-the-best-mobile-network-experience" alt="Device impact on network performance is visible in Opensignal's iPhone dataset." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/opensignal_iphone_relative_network_speed.webp" alt="Device impact on network performance is visible in Opensignal's iPhone dataset." style="aspect-ratio: 3200 / 1671" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Device impact on network performance is visible in Opensignal's iPhone dataset.</figcaption>      </figure><p></p>
<p>As inequality grows, <a href="https://www.financialexpress.com/business/industry/mobile-download-speeds-india-moves-up-72-spots-in-global-ranking/3260813/#:~:text=In%20fact%2C%20in,of%20385.50%20Mbps.">averages and &quot;generation&quot; tags can become illusory and misleading</a>. Our own experiences are no guide; we've got to keep our hands in the data to understand the texture of the world.</p>
<p>So, with all of that as prelude, what <em>can</em> we say about where the mobile network baseline should be set? In a departure from years prior, I'm going to use a unified network estimate (see below). You'll have to read on for what it is! But it won't be based on the sort of numbers that folks explicitly running speed tests see; those aren't real life.</p>
<h4 id="market-factors" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#market-factors">Market Factors</a></h4>
<p>The market forces this series <a href="https://infrequently.org/2017/10/can-you-afford-it-real-world-web-performance-budgets/#global-ground-truth">previewed in 2017</a> have played out in roughly a straight line: smartphone penetration in emerging markets is approaching saturation, ensuring a growing fraction of purchases are made by upgrade shoppers. Those who upgrade see more value in their phones and save to buy better second and third devices. Combined with the <a href="https://en.wikipedia.org/wiki/IPhone_X#:~:text=At%20the%20time%20of%20its,local%20sales%20and%20import%20taxes.">emergence</a> and <a href="https://www.counterpointresearch.com/insights/premium-smartphone-asp-reaches-record-q2-high/">growth of the &quot;ultra premium&quot; segment</a>, average selling prices (ASPs) have risen.</p>
<p>2022 and 2023 have established an inflection point in the regard, with worldwide average selling prices <a href="https://www.idc.com/getdoc.jsp?containerId=prUS51430223">jumping to more than $430</a>, up from $300-$350 for much of the decade prior. Some price appreciation has been <a href="https://www.technavio.com/report/smartphone-market-industry-analysis">due to transient impacts of the U.S./China trade wars</a>, but most of it appears driven by iOS ASPs which peaked above $1,000 for the first time in 2023. Android ASPs, meanwhile, continued a gradual rise to nearly $300, up from $250 five years ago.</p>
<p></p><figure><a href="https://www.idc.com/getdoc.jsp?containerId=prUS51430223" alt="undefined" target="_blank"><picture style="--lqip: 522138" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/idc_forecast.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/idc_forecast.png" alt="Missing alt text" style="aspect-ratio: 1433 / 1137" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption></figcaption>      </figure><p></p>
<p>A <a href="https://www.counterpointresearch.com/insights/global-smartphone-market-reaches-its-lowest-q3-levels-in-a-decade-apples-share-at-16/">weak market for handsets in 2023</a>, plus stable sales for iOS, had an notable impact on prices. IDC expects global average prices to fall back below $400 by 2027 as Android volumes increase from an unusually soft 2023.</p>
<p></p><figure><a href="https://www.counterpointresearch.com/research_portal/counterpoint-quarterly-smartphone-q4-2023/" alt="Counterpoint data shows declining sales in both 2022 and 2023." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/smartphone_shipments_2023.webp" alt="Counterpoint data shows declining sales in both 2022 and 2023." style="aspect-ratio: 1582 / 846" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Counterpoint data shows declining sales in both 2022 and 2023.</figcaption>      </figure><p></p>
<p></p><figure><a href="https://www.counterpointresearch.com/research_portal/counterpoint-quarterly-smartphone-q4-2023/" alt="Shipment growth in late 2023 and beyond is coming from emerging markets like the Middle East and Africa. Samsung's A-series mid-tier is doing particularly well." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/return_to_growth_driven_by_em.webp" alt="Shipment growth in late 2023 and beyond is coming from emerging markets like the Middle East and Africa. Samsung's A-series mid-tier is doing particularly well." style="aspect-ratio: 1513 / 544" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Shipment growth in late 2023 and beyond is coming from emerging markets like the Middle East and Africa. Samsung's A-series mid-tier is doing particularly well.</figcaption>      </figure><p></p>
<p>Despite falling sales, distribution of Android versus iOS sales remains largely unchanged:</p>
<p></p><figure><a href="https://www.counterpointresearch.com/insights/global-smartphone-os-market-share/" alt="Android sales reliably constitute 80-85% of worldwide volume." target="_blank"><picture style="--lqip: 174307" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/counterpoint_smartphone_sales_by_OS_Q3-2023.webp" alt="Android sales reliably constitute 80-85% of worldwide volume." style="padding: 15px; background-color: white;; aspect-ratio: 1200 / 675" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Android sales reliably constitute 80-85% of worldwide volume.</figcaption>      </figure><p></p>
<p></p><figure><a href="https://www.statista.com/statistics/245191/market-share-of-mobile-operating-systems-for-smartphone-sales-in-australia/" alt="Even in rich nations like Australia and the <a href='https://www.statista.com/statistics/262179/market-share-held-by-mobile-operating-systems-in-the-united-kingdom/'>the U.K.</a>, iPhones account for less than half of sales. Predictably, they are over-represented in analytics and logs owing to wealth-related factors including superior network access and performance hysteresis." target="_blank"><picture style="--lqip: 521881" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/au_smartphone_share_by_os.webp" alt="Even in rich nations like Australia and the <a href='https://www.statista.com/statistics/262179/market-share-held-by-mobile-operating-systems-in-the-united-kingdom/'>the U.K.</a>, iPhones account for less than half of sales. Predictably, they are over-represented in analytics and logs owing to wealth-related factors including superior network access and performance hysteresis." style="padding: 15px; background-color: white;; aspect-ratio: 1313 / 658" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Even in rich nations like Australia and the <a href="https://www.statista.com/statistics/262179/market-share-held-by-mobile-operating-systems-in-the-united-kingdom/">the U.K.</a>, iPhones account for less than half of sales. Predictably, they are over-represented in analytics and logs owing to wealth-related factors including superior network access and performance hysteresis.</figcaption>      </figure><p></p>
<p>Smartphone replacement rates have remained roughly in line with previous years, although we should expect higher device longevity in future years. <a href="https://www.sellcell.com/blog/how-often-do-people-upgrade-their-phone-2023-statistics/">Survey reports</a> and market analysts continue to estimate average replacement at 3-4 years, depending on segment. Premium devices last longer, and a higher fraction of devices may be older in wealthy geographies. Combined with <a href="https://www2.deloitte.com/us/en/insights/economy/consumer-pulse/state-of-the-us-consumer.html">discretionary spending pressure</a> and <a href="https://www.ons.gov.uk/economy/inflationandpriceindices/articles/costofliving/latestinsights">inflationary impacts on household budgets</a>, consumer intent to spend on electronics has taken a hit, which will be felt in device lifetime extension until conditions improve. <a href="https://www.counterpointresearch.com/insights/apple-refurbished-smartphone-volumes-grew-16-yoy-globally-in-2022/">Increasing demand for refurbished devices</a> also adds to observable device aging.</p>
<p>The data paints a substantially similar picture to previous years: the web is experienced on devices that are slower and older than those carried by affluent developers and corporate directors whose purchasing decisions are not impacted by transitory inflation.</p>
<p>To serve users effectively, we must do extra work to <a href="https://glazkov.com/2023/07/30/live-as-our-customer/">live as our customers do</a>.</p>
<h4 id="test-device-recommendations" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#test-device-recommendations">Test Device Recommendations</a></h4>
<p>Re-using <a href="https://infrequently.org/2022/12/performance-baseline-2023/#devices-1">last year's P75 device calculus</a>, our estimate is based on a device sold new, unlocked for the mid-2020 to mid-2021 global ASP of ~$350-375.</p>
<p>Representative examples from that time period include the <a href="https://www.gsmarena.com/samsung_galaxy_a51-9963.php">Samsung Galaxy A51</a> and the <a href="https://www.gsmarena.com/google_pixel_4a-10123.php">Pixel 4a</a>. Neither model featured 5G,<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-premium-5g-6" id="fnref-premium-5g-6">6</a></sup> and we cannot expect 5G to play a significant role in worldwide baselines for at least the next several years.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-5g-lumpiness-4" id="fnref-5g-lumpiness-4:1">4:1</a></sup></p>
<p>The A51 featured <a href="https://www.gsmarena.com/samsung_galaxy_a51-9963.php#:~:text=Octa%2Dcore%20(4x2.3%20GHz%20Cortex%2DA73%20%26%204x1.7%20GHz%20Cortex%2DA53)">eight slow cores (4x2.3 GHz Cortex-A73 and 4x1.7 GHz Cortex-A53) on a 10nm process</a>:</p>
<p></p><figure><a href="https://browser.geekbench.com/v6/cpu/compare/350184?baseline=3639070" alt="Geekbench 6 scores for the Galaxy A51 versus today's leading device." target="_blank"><picture style="--lqip: 173539" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/a51_vs_iphone_15_pro.webp" alt="Geekbench 6 scores for the Galaxy A51 versus today's leading device." style="aspect-ratio: 1027 / 534" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Geekbench 6 scores for the Galaxy A51 versus today's leading device.</figcaption>      </figure><p></p>
<p><a href="https://www.gsmarena.com/google_pixel_4a-10123.php#:~:text=Octa%2Dcore%20(2x2.2%20GHz%20Kryo%20470%20Gold%20%26%206x1.8%20GHz%20Kryo%20470%20Silver)">The Pixel 4a's slow, eight-core big.LITTLE configuration was fabricated on an 8nm process</a>:</p>
<p></p><figure><a href="https://browser.geekbench.com/v6/cpu/compare/4295850?baseline=3639070" alt="Google spent more on the SoC for the Pixel 4a and enjoyed a later launch date, boosting performance relative to the A51." target="_blank"><picture style="--lqip: 173539" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/pixel_4a_vs_iphone_15_pro.webp" alt="Google spent more on the SoC for the Pixel 4a and enjoyed a later launch date, boosting performance relative to the A51." style="aspect-ratio: 1027 / 534" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Google spent more on the SoC for the Pixel 4a and enjoyed a later launch date, boosting performance relative to the A51.</figcaption>      </figure><p></p>
<p><a href="https://www.androidpolice.com/why-google-pixel-phones-hardware-do-not-sell/">Pixels have never sold well,</a> and Google's focus on strong &gt;SoC performance per dollar was sadly not replicated across the Android ecosystem, forcing us to use the A51 as our stand-in.</p>
<p>Devices within the envelope of our attention are 15-25% as fast as those carried by programmers and their bosses — even in wealthy markets.</p>
<p>The Galaxy may be <a href="https://browser.geekbench.com/v6/cpu/compare/4301594?baseline=442665">slightly faster</a> than last year's <a href="https://infrequently.org/2022/12/performance-baseline-2023/#:~:text=The%20best%20analogue%20you%20can%20buy%20for%20a%20representative%20P75%20device%20today%20are%20~%24200%20Androids%20from%20the%20last%20year%20or%20two%2C%20such%20as%20the%20Samsung%20Galaxy%20A50%20and%20the%20Nokia%20G11.">recommendation</a> of the <a href="https://www.gsmarena.com/samsung_galaxy_a50-9554.php">Galaxy A50 for testing</a>, but the picture is muddy:</p>
<p></p><figure><a href="https://browser.geekbench.com/v5/cpu/compare/22080983?baseline=22095605" alt="Geekbench 5 shows almost no improvement between the A50 and the A51." target="_blank"><picture style="--lqip: 173795" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb5.webp" alt="Geekbench 5 shows almost no improvement between the A50 and the A51." style="aspect-ratio: 1030 / 514" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Geekbench 5 shows almost no improvement between the A50 and the A51.</figcaption>      </figure><p></p>
<p></p><figure><a href="https://browser.geekbench.com/v6/cpu/compare/4302358?baseline=4260956" alt="Geekbench 6 shows the same story within the margin of error. The low-end is stagnant, and still <a href='https://www.statista.com/statistics/934471/smartphone-shipments-by-price-category-worldwide/' target='_new'>30% of worldwide volume</a>." target="_blank"><picture style="--lqip: 173539" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/a50_vs_a51_gb6.webp" alt="Geekbench 6 shows the same story within the margin of error. The low-end is stagnant, and still <a href='https://www.statista.com/statistics/934471/smartphone-shipments-by-price-category-worldwide/' target='_new'>30% of worldwide volume</a>." style="aspect-ratio: 1035 / 511" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Geekbench 6 shows the same story within the margin of error. The low-end is stagnant, and still <a href="https://www.statista.com/statistics/934471/smartphone-shipments-by-price-category-worldwide/" target="_new">30% of worldwide volume</a>.</figcaption>      </figure><p></p>
<p>If you're building a test lab today, refurbished A51s can be had for ~$150. Even better, the newer <a href="https://browser.geekbench.com/v6/cpu/compare/3826666?baseline=350184">Nokia G100</a> can be had for as little as $100, and it's <a href="https://www.nokia.com/phones/en_us/nokia-g-100?sku=F22CF51022200">faithful</a> to the sluggish original in <a href="https://www.gsmarena.com/compare.php3?idPhone1=9963&amp;idPhone2=12373">nearly every respect</a>.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-samsung-replacement-7" id="fnref-samsung-replacement-7">7</a></sup></p>
<p>If your test bench is based on last year's recommended A50 or <a href="https://www.gsmarena.com/nokia_g11-11358.php">Nokia G11</a>, I do not recommend upgrading in 2024. The absolute gains are so slight that the difference will be hard to feel, and bench stability has a value all its own. Looking forward, we can also predict that our bench performance will be stable until 2025.</p>
<p>Claims about how &quot;performant&quot; modern frontend tools are have to be evaluated in this slow, stagnant context.</p>
<h3 id="desktop" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#desktop">Desktop</a></h3>
<p>It's a bit easier to understand the Desktop situation because the Edge telemetry I have access to provides statistically significant insight into <a href="https://www.statista.com/statistics/576473/united-states-quarterly-pc-shipment-share-apple/">85+% of the market</a>.</p>
<h4 id="device-performance-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#device-performance-1">Device Performance</a></h4>
<p>The TL;DR for desktop performance is that Edge telemetry puts ~45% of devices in a &quot;low-end&quot; bucket, meaning they have &lt;= 4 cores or &lt;= 4GB of RAM.</p>
<table class="summary" style="margin: auto; min-width: 75%;">
  <thead>
    <tr>
      <td>Device Tier</td>
      <td>Fleet %</td>
      <td style="text-align: center;">Definition</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Low-end</td>
      <td>45%</td>
      <td style="width: 50%;">Either:<br />&lt;= 4 cores, or<br />&lt;= 4GB RAM</td>
    </tr>
    <tr>
      <td>Medium</td>
      <td>48%</td>
      <td>HDD (not SSD), or<br />4-16 GB RAM, or<br />4-8 cores</td>
    </tr>
    <tr>
      <td>High</td>
      <td>7%</td>
      <td style="width: 50%;">SSD +<br />&gt; 8 cores +<br />&gt; 16GB RAM</td>
    </tr>
  </tbody>
</table>
<p>20% of users are on HDDs (not SSDs) and nearly all of those users also have low (and slow) cores.</p>
<p>You might be tempted to dismiss this data because it doesn't include Macs, which are faster than the PC cohort. Recall, however, that the snapshot also excludes ChromeOS.</p>
<p>ChromeOS share has veered wildly in recent years, representing 50%-200% of Mac shipments in a given per quarter. In '21 and '22, ChromeOS shipments regularly doubled Mac sales. Despite post-pandemic mean reversion, <a href="https://www.idc.com/getdoc.jsp?containerId=IDC_P36344">according to IDC</a> ChromeOS devices outsold Macs ~5.7M to ~4.7M in 2023 Q2. The trend reversed in Q3, with Macs almost doubling ChromeOS sales, but slow ChromeOS devices aren't going away and, from a population perspective, more than offset Macs today. Analysts also <a href="https://www.idc.com/promo/pcdforecast">predict growth in the low end of the market as educational institutions begin to refresh their past purchases.</a></p>
<h4 id="networks-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#networks-1">Networks</a></h4>
<p>Desktop-attached networks <a href="https://www.fiercetelecom.com/broadband/ookla-global-fixed-download-speeds-nearly-doubled-2022">continue to improve</a>, notably <a href="https://www.allconnect.com/blog/broadband-availability-by-type">in the U.S.</a> Regulatory intervention and subsidies have done much to spur enhancements in access to U.S. fixed broadband, although <a href="https://www.allconnect.com/blog/broadband-availability-by-type#:~:text=Top%20and%20bottom%20states%20for%20speed">disparities in access remain</a> and the gains <a href="https://www.cbsnews.com/news/affordable-internet-service-could-be-lost-fcc-program-to-run-out-of-funds/">may not persist</a>.</p>
<p>This suggests that it's time to also bump our baseline for desktop tests beyond the 5Mbps/1Mbps/28ms configuration that <a href="https://www.webpagetest.org/">WebPageTest.org's &quot;Cable&quot; profile</a> has defaulted to for desktop tests.</p>
<p>How far should we bump it? Publicly available data is unclear, and I've come to find out that Edge's telemetry lacks good network observation statistics (doh!).</p>
<p>But the comedy of omissions doesn't end there: Windows telemetry doesn't capture a proxy for network quality, I no longer have access to Chrome's data, the <a href="https://developer.chrome.com/docs/crux/api#effective_connection_type">population-level telemetry available from CrUX is unhelpful</a>, and <a href="https://www.fcc.gov/reports-research/reports/measuring-broadband-america/measuring-fixed-broadband-twelfth-report#:~:text=Chart%2016.2%3A%20The%20ratio%20of%2070/70%20consistent%20download%20speed%20to%20advertised%20download%20speed.">telcos li</a>...er...sorry, <em>&quot;market their products in accordance with local laws and advertising standards.&quot;</em></p>
<p>All of this makes it difficult to construct an estimate.</p>
<p>One option is to use a population-level assessment of medians from <a href="https://www.speedtest.net/global-index">something like the Speedtest.net data</a> and then construct a histogram from median speeds. This is both time-consuming and error-prone, as population-level data varies widely across the world. Emerging markets with high mobile internet use and dense populations <a href="https://www.fiercewireless.com/wireless/indias-top-2-mobile-carriers-fight-supremacy-fixed-broadband">can feature</a> poor fixed-line broadband penetration <a href="https://www.opensignal.com/2023/11/22/closing-the-gap-fixed-broadbands-role-in-global-progress">compared with Western markets</a>.</p>
<p>Another option is to mathematically hand-wave using the best evidence we can get. This might allow us to reconstruct probable P75 and P90 values if we know something about the historical distribution of connections. From there, we can gut-check using other spot data. To do this, we need to assume some data set is representative, a fraught decision all its own.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fn-moar-dragons-8" id="fnref-moar-dragons-8">8</a></sup> Biting the bullet, we could start from the Speedtest.net global survey data, which currently fails to provide anything but medians (P50):</p>
<p></p><figure><a href="https://www.speedtest.net/global-index" alt="Speedtest.net's global median values are unhelpful on their own, both because they represent users who are testing for speed (and not organic throughput) and because they don't give us a fuller understanding of the distribution." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/global_fixed_speedtest_medians.webp" alt="Speedtest.net's global median values are unhelpful on their own, both because they represent users who are testing for speed (and not organic throughput) and because they don't give us a fuller understanding of the distribution." style="aspect-ratio: 512 / 748" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Speedtest.net's global median values are unhelpful on their own, both because they represent users who are testing for speed (and not organic throughput) and because they don't give us a fuller understanding of the distribution.</figcaption>      </figure><p></p>
<p>After many attempted Stupid Math Tricks with poorly fitting curves (bandwidth seems to be a funky cousin of log-normal), I've decided to wing it and beg for help: instead of trying to be clever, I'm leaning on <a href="https://radar.cloudflare.com/quality/">Cloudflare Radar's P25/P50/P75 distributions</a> for <a href="https://en.wikipedia.org/wiki/List_of_countries_by_number_of_Internet_users">populous, openly-connected countries with &gt;= ~50M internet users</a>. It's cheeky, but a weighted average of the P75 of download speeds (3/4ths of all connections are faster) should get us in the ballpark. We can then use the usual 5:1 downlink:uplink ratio to come up with an uplink estimate. We can also derive a weighted average for the P75 RTT from Cloudflare's data. Because Cloudflare doesn't distinguish mobile from desktop connections, this may be an overly conservative estimate, but it's still be more permissive than what we had been pegged to in years past:</p>
<style>
  #natspeeds {
    & td:not(:first-of-type) { text-align: right; }
  }
</style>
<table class="summary" style="margin: auto;" id="natspeeds">
  <caption>National P75 Downlink and RTT</caption>
  <thead>
    <tr>
      <td>Country</td>
      <td>P75 Downlink (Mbps)</td>
      <td>P75 RTT (ms)</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>India</td>
      <td>4</td>
      <td>114</td>
    </tr>
    <tr>
      <td>USA</td>
      <td>11</td>
      <td>58</td>
    </tr>
    <tr>
      <td>Indonesia</td>
      <td>5</td>
      <td>81</td>
    </tr>
    <tr>
      <td>Brazil</td>
      <td>8</td>
      <td>71</td>
    </tr>
    <tr>
      <td>Nigeria</td>
      <td>3</td>
      <td>201</td>
    </tr>
    <tr>
      <td>Pakistan</td>
      <td>3</td>
      <td>166</td>
    </tr>
    <tr>
      <td>Bangladesh</td>
      <td>5</td>
      <td>114</td>
    </tr>
    <tr>
      <td>Japan</td>
      <td>17</td>
      <td>42</td>
    </tr>
    <tr>
      <td>Mexico</td>
      <td>7</td>
      <td>75</td>
    </tr>
    <tr>
      <td>Egypt</td>
      <td>4</td>
      <td>100</td>
    </tr>
    <tr>
      <td>Germany</td>
      <td>16</td>
      <td>36</td>
    </tr>
    <tr>
      <td>Turkey</td>
      <td>7</td>
      <td>74</td>
    </tr>
    <tr>
      <td>Philippines</td>
      <td>7</td>
      <td>72</td>
    </tr>
    <tr>
      <td>Vietnam</td>
      <td>7</td>
      <td>72</td>
    </tr>
    <tr>
      <td>United Kingdom</td>
      <td>16</td>
      <td>37</td>
    </tr>
    <tr>
      <td>South Korea</td>
      <td>24</td>
      <td>26</td>
    </tr>
    <tr style="font-weight: bold;">
      <td><em>Population Weighted Avg.</em></td>
      <td>7.2</td>
      <td>94</td>
    </tr>
  </tbody>
</table>
<p>We, therefore, update our P75 link estimate <strong>7.2Mbps down, 1.4Mbps up, and 94ms RTT.</strong></p>
<p>This is a mild crime against statistics, not least of all because it averages unlike quantities and fails to sift mobile from desktop, but all the other methods available at time of writing are just as bad. Regardless, this new baseline is half again as much link capacity as last year, showing measurable improvement in networks worldwide.</p>
<p>If you or your company are able to generate a credible worldwide latency estimate in the higher percentiles for next year's update, please <a href="https://infrequently.org/about-me/">get in touch</a>.</p>
<h4 id="market-factors-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#market-factors-1">Market Factors</a></h4>
<p>The forces that shape the PC population have been largely fixed for many years. Since 2010, <a href="https://en.wikipedia.org/wiki/Market_share_of_personal_computer_vendors#Worldwide_(1996%E2%80%932022)">volumes have been on a slow downward glide path</a>, shrinking from ~350MM per year in a decade ago to ~260MM in 2018. The pandemic buying spree of 2021 pushed volumes above 300MM per year for the first time in eight years, with the vast majority of those devices being sold at low-end price points — think ~$300 Chromebooks rather than M1 MacBooks.</p>
<p>Lest we assume low-end means &quot;short-lived&quot;, <a href="https://blog.google/outreach-initiatives/education/automatic-update-extension-chromebook/">recent announcements regarding software support for these devices</a> will considerably extend their impact. This low-end cohort will filter through the device population for years to come, pulling our performance budgets down, even as renewed process improvement is unlocking improved power efficiency and performance at the high end of the first-sale market. This won't be as pronounced as the diffusion of $100 smartphones has been in emerging markets, but the longer life-span of desktops is already a factor in our model.</p>
<h4 id="test-device-recommendations-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#test-device-recommendations-1">Test Device Recommendations</a></h4>
<p>Per our methodology from last year which uses the 5-8 year replacement cycle for a PC, we update our target date to late 2017 or early 2018, but leave the average-selling-price fixed between $600-700. Eventually we'll need to factor in the past couple of years of gyrations in inflation and supply chains into account when making an estimate, but not this year.</p>
<p>So what did $650, give or take, buy in late 2017 or early 2018?</p>
<p>One option was a <a href="https://www.theverge.com/2017/5/30/15698476/dell-inspiron-gaming-desktop-announced">naf looking tower from Dell, optimistically pitched at gamers</a>, with a CPU that scores <a href="https://browser.geekbench.com/v6/cpu/compare/3639070?baseline=253445">poorly versus a modern phone</a>, but blessedly includes 8GB of RAM.</p>
<p>In laptops (the larger segment), ~$650 bought the <a href="https://www.pcmag.com/reviews/lenovo-yoga-720-12-inch">Lenovo Yoga 720 (12&quot;)</a>, with a 2-core (4-thread) <a href="https://ark.intel.com/content/www/us/en/ark/products/95442/intel-core-i3-7100u-processor-3m-cache-2-40-ghz.html">Core i3-7100U</a> and 4GB of RAM. Versions with more RAM and a faster chip were available, but cost considerably more than our budget. This was not a fast box. <a href="https://browser.geekbench.com/v6/cpu/compare/3639070?baseline=4311168">Here's a device with that CPU compared to a modern phone</a>; not pretty:</p>
<p></p><figure><a href="https://browser.geekbench.com/v6/cpu/compare/3639070?baseline=4311168" alt="The phones of wealthy developers absolutely smoke the baseline PC." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/i3-7100U_vs_iphone_15_pro.webp" alt="The phones of wealthy developers absolutely smoke the baseline PC." style="aspect-ratio: 1042 / 531" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>The phones of wealthy developers absolutely smoke the baseline PC.</figcaption>      </figure><p></p>
<p>It's considerably faster than <a href="https://www.bhphotovideo.com/c/product/1704697-REG/hp_6k639ut_aba_probook_fortis_14_n4500.html">some devices still being sold to schools, though</a>.</p>
<p>What does this mean for our target devices? There's wild variation in performance per dollar below $600 which will only increase as inflation-affected cohorts grow to represent a larger fraction of the fleet. Intel's move off of 14nm (finally!) also means that gains are starting to arrive at the low end, but in an uneven way. General advice is therefore hard to issue. That said, we can triangulate based on what we know about the market:</p>
<ul>
<li><a href="https://www.statista.com/forecasts/1246316/revenue-segments-pc-market-united-states">Most PCs are laptops or tablets.</a> This means they're power-limited.</li>
<li>Most devices are more than four years old.</li>
<li>Conservative estimates are future-proof.</li>
</ul>
<p>My recommendation, then, to someone setting up a new lab today is not to spend more than $350 on new a test device. Consider laptops with chips like the <a href="https://www.intel.com/content/www/us/en/products/sku/197309/intel-celeron-processor-n4120-4m-cache-up-to-2-60-ghz/specifications.html">N4120</a>, <a href="https://www.intel.com/content/www/us/en/products/sku/212326/intel-celeron-processor-n4500-4m-cache-up-to-2-80-ghz/specifications.html">N4500</a>, or the <a href="https://www.intel.com/content/www/us/en/products/sku/212328/intel-celeron-processor-n5105-4m-cache-up-to-2-90-ghz/specifications.html">N5105</a>. Test devices should also have no more than 8GB of RAM, and preferably 4GB. The <a href="https://a.co/d/98wiGAl">2021 HP 14</a> is a fine proxy. The <a href="https://www.bhphotovideo.com/c/product/1761467-REG/hp_7f424ua_aba_14_14_ep0010nr_laptop_intel.html">updated ~$375 version</a> will do in a pinch, but try to spend less if you can. <a href="https://www.notebookcheck.net/Mobile-Processors-Benchmark-List.2436.0.html?type=&amp;sort=&amp;search=Intel&amp;itemselect_13189=13189&amp;itemselect_13111=13111&amp;itemselect_11533=11533&amp;itemselect_13079=13079&amp;or=0&amp;itemselect_13189=13189&amp;itemselect_13111=13111&amp;itemselect_11533=11533&amp;itemselect_13079=13079&amp;showCount=1&amp;showBars=1&amp;geekbench5_1_single=1&amp;geekbench5_1_multi=1&amp;geekbench6_2_single=1&amp;geekbench6_2_multi=1&amp;octane2=1&amp;speedometer=1&amp;cpu_fullname=1&amp;codename=1&amp;l2cache=1&amp;l3cache=1&amp;tdp=1&amp;mhz=1&amp;turbo_mhz=1&amp;cores=1&amp;threads=1">Test devices should preferably score no higher than 1,000 in single-core Geekbench 6 tests</a>; a line <a href="https://browser.geekbench.com/v6/cpu/4352217">the HP 14's N4120 easily ducks, clocking in at just over 350</a>.</p>
<h2 id="takeaways" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#takeaways">Takeaways</a></h2>
<p>There's a lot of good news embedded in this year's update. Devices and networks have finally started to get faster (as predicted), pulling budgets upwards.</p>
<p>At the same time, the community remains in denial about the disastrous consequences of an over-reliance on JavaScript. This paints a picture of path dependence — frontend isn't moving on from approaches that hurt users, <a href="https://x.com/FredKSchott/status/1744842592905552227?s=20">even as the costs shift back onto teams that have been degrading life for users at the margins</a>.</p>
<p>We can anticipate continued improvement in devices, while network gains will level out as the uneven deployment of 5G stumbles forward. Regardless, the gap between the digital haves and have-nots continues to grow. Those least able to afford fast devices are suffering regressive taxation from developers high on DX fumes.</p>
<p>It's no mystery why folks in the privilege bubble are not building with empathy or humility when nobody calls them to account. What's mysterious is that anybody pays them to do it.</p>
<p>The PM and EM disciplines have utterly failed, neglecting to put business constraints on the enthusiasms of developers. This burden is falling, instead, on users and their browsers. <a href="https://web.dev/articles/vitals">Browsers have had to step in</a> as the experience guardians of last resort, indicating a market-wide botching of the job in technology management ranks and an industry-scale principal-agent issue amongst developers.</p>
<p>Instead of cabining the FP crowd's proclivities for the benefit of the business, managers meekly repeat bullshit like <em>&quot;you can't hire for fundamentals&quot;</em> while bussing in loads of React bootcampers. It is not too much to ask that managers run bake-offs and hire for skills in platform fundamentals that serve businesses better over time. The alternative is continued failure, even for fellow privilege bubble dwellers.</p>
<p>Case in point: this post was partially drafted on airplane wifi, and I can assure you that wealthy folks also experience RTTs north of 500ms and <a href="https://en.wikipedia.org/wiki/Gogo_Inflight_Internet#Technologies">channel capacity in the single-digit-Mbps</a>.</p>
<p>Even the wealthiest users step into the wider world sometimes. Are these EMs and PMs <em>really</em> happy to lose that business?</p>
<p></p><figure><a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg" alt="<em>Tap for a larger version.</em><br>Wealthy users are going to experience networks with properties that are even worse than the 'bad' networks offered to the Next Billion Users. At an altitude of 40k feet and a ground speed for 580 MPH somewhere over Alberta, CA, your correspondent's bandwidth is scarce, lopsided, and laggy." target="_blank"><picture style="--lqip: 353635" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/performance-inequality-gap-2024/airplane_wifi_speedtest.jpg" alt="<em>Tap for a larger version.</em><br>Wealthy users are going to experience networks with properties that are even worse than the 'bad' networks offered to the Next Billion Users. At an altitude of 40k feet and a ground speed for 580 MPH somewhere over Alberta, CA, your correspondent's bandwidth is scarce, lopsided, and laggy." style="aspect-ratio: 1213 / 744" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Wealthy users are going to experience networks with properties that are even worse than the 'bad' networks offered to the Next Billion Users. At an altitude of 40k feet and a ground speed for 580 MPH somewhere over Alberta, CA, your correspondent's bandwidth is scarce, lopsided, and laggy.</figcaption>      </figure><p></p>
<p>Of course, any trend that can't continue won't, and INP's impact is already being felt. The great JavaScript merry-go-round may grind to a stop, but the momentum of consistently bad choices is formidable. Like passengers on a cruise ship ramming a boardwalk at flank speed, JavaScript regret is dawning far too late. As the good ship Scripting shudders and lists on the remains of the ferris wheel, it's not exactly clear how to get off, but the choices that led us here are becoming visible, if only through their negative consequences.</p>
<h3 id="the-great-branch-mispredict" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#the-great-branch-mispredict">The Great Branch Mispredict</a></h3>
<p>We got to a place where performance has been a constant problem in large part because a tribe of programmers convinced themselves that it <em>wasn't</em> and <em>wouldn't be</em>. The circa '13 narrative asserted that:</p>
<ul>
<li>CPUs would keep getting faster (just like they always had).</li>
<li>Networks would get better, or at least not get worse.</li>
<li>Organisations had all learned the lessons of Google and Facebook's adventures in Ajax.</li>
</ul>
<p>It was all bullshit, <em>and many of us spotted it a mile away</em>.</p>
<p>The problem is now visible and demands a solution, but the answers will be largely social, not technical. User-centered values must contest the airtime previouly taken by failed trickle-down DX mantras. Only when the dominant story changes will better architectures and tools win.</p>
<p>How deep was the branch? And how many cycles will the fault cost us? If CPUs and networks continue to improve at the rate of the past two years, and INP finally forces a reckoning, the answer might be as little as a decade. I fear we will not be so lucky; an entire generation has been trained to ignore reality, to prize tribalism rather than engineering rigor, and to devalue fundamentals. Those folks may not find the next couple of years to their liking.</p>
<p>Frontend's hangover from the JavaScript party is gonna <em>suck</em>.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-why-five-seconds-1" class="footnote-item"><p>The five second first-load target is arbitrary, and has always been higher than I would prefer. Five seconds on a modern computer is an <em>eternity</em>, but in 2016 I was talked down from my preferred three-second target by Googlers that despaired that &quot;nobody&quot; could hit that mark on the devices and networks of that era.</p>
<p>This series continues to report budgets with that target, but keen readers will see that I'm also providing three-second numbers. The <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/chart/index.html">interactive estimation tool</a> was also updated this year to provides the ability to configure the budget target.</p>
<p>If you've got thoughts about how this should be set in future, or how it could be handled better, plesae <a href="https://infrequently.org/about-me/">get in touch.</a> <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-why-five-seconds-1" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-why-five-seconds-1:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-lottery-ticket-engineering-2" class="footnote-item"><p>Frontend developers are cursed to program The Devil's Computer. Web apps execute on slow devices we don't spec or provision, on runtimes we can barely reason about, lashed to disks and OSes taxed by malware and equally invasive security software, over networks with the variability of carrier pigeons.</p>
<p>It's vexing, then, that contemporary web development practice has decided that the way to deliver great experiences is to lean into client CPUs and mobile networks, the most unreliable, unscalable properties of any stack.</p>
<p>And yet, here we are in 2024, with Reactors somehow still anointed to decree how and where code should run, despite a decade of failure to predict the obvious, or even adapt to the world as it has been. <a href="https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/worldwide/#yearly-2009-2024">The mobile web overtook desktop eight years ago</a>, and the best time to call bullshit on JS-first development was <a href="https://youtu.be/4bZvq3nodf4?si=D_S5S9jnff5iMJnB">when we could first see the trends clearly.</a></p>
<p>The second best time is now. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-lottery-ticket-engineering-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-self-preservation-3" class="footnote-item"><p>Engineering is design under constraint, with the goal to develop products that serve users and society.</p>
<p>The opposite of engineering is bullshit; substituting fairy tales for inquiry and evidence.</p>
<p>For the frontend to earn and keep its stripes as an engineering discipline, frontenders need to internalise the envelope of what's possible on <em>most</em> devices. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-self-preservation-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-5g-lumpiness-4" class="footnote-item"><p>For at least a decade to come, 5G will continue to deliver unevenly depending on factors including building materials, tower buildout, supported frequencies, device density, radio processing power, and weather. Yes, <a href="https://arxiv.org/pdf/2111.09418.pdf">weather (PDF)</a>.</p>
<p>Even with all of those caveats, 5G networks aren't the limiting factor in wealthy geographies; devices are. It will take years for the deployed base to be fully replaced with 5G-capable handsets, and we should expect the diffusion to be &quot;lumpy&quot;, with wealthy markets seeing 5G device saturation at nearly all price points well in advance of less affluent countries where <a href="https://www.techtarget.com/whatis/feature/5-Predictions-about-5G-Adoption-in-2021-and-Beyond#:~:text=Regardless%20of%20the,the%205G%20revolution.%22">capital availability for 5G network roll-outs will dominate.</a> <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-5g-lumpiness-4" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-5g-lumpiness-4:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-a-plea-to-ookla-and-opensignal-5" class="footnote-item"><p>Ookla! Opensignal! Cloudflare! Akamai! I beseech thee, hear my plea and take pity, oh mighty data collectors.</p>
<p>Whilst you report medians and averages (sometimes interchangeably, though I cannot speculate why), you've stopped publishing useable histogram information about the global situation, making the reports nearly useless for anything but telco marketing. Opensignal has stopped reporting meaningful 4G data at all, endangering any attempt at making sense.</p>
<p>Please, I beg of you, publish P50, P75, P90, and P95 results for each of your market reports! And about the global situation! Or reach out directly and share what you can in confidence so I can generate better guidance for web developers. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-a-plea-to-ookla-and-opensignal-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-premium-5g-6" class="footnote-item"><p>Both the benchmark A51 and Pixel 4a devices were eventually sold in 5G variants (<a href="https://en.wikipedia.org/wiki/Samsung_Galaxy_A51">A51 5G</a>, <a href="https://en.wikipedia.org/wiki/Pixel_4a">Pixel 4a 5G</a>), but at a price of $500 brand-new, unlocked at launch, making them more than 40% above the price of the base models and well above our 2020-2021 ASP of $350-$375. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-premium-5g-6" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-samsung-replacement-7" class="footnote-item"><p>Samsung's lineup is not uniform worldwide, with many devices being region-specific. The closest modern (Western) Samsung device to the A51 is <a href="https://browser.geekbench.com/v6/cpu/compare/4177625?baseline=350184">the Samsung A23 5G, which scores in the range of the Pixel 4a</a>. As a result of the high CPU score and 5G modem, it's hard to recommend it — or any other current Samsung model — as a lab replacement. Try the <a href="https://www.gsmarena.com/nokia_g100-12373.php">Nokia G100 instead.</a> <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-samsung-replacement-7" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-moar-dragons-8" class="footnote-item"><p>The idea that any of the publicly available data sets is globally representative should set off alarms.</p>
<p>The obvious problems include (but are not limited to):</p>
<ul>
<li>geographic differences in service availability and/or deployed infrastructure,</li>
<li>differences in market penetration of observation platforms (e.g., was a system properly localised? Equally advertised?), and</li>
<li>mandated legal gaps in coverage.</li>
</ul>
<p>Of all the hand-waving we're doing to construct an estimate, this is the biggest leap and one of the hardest to triangulate against. <a href="https://infrequently.org/2024/01/performance-inequality-gap-2024/#fnref-moar-dragons-8" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Why Are Tech Reporters Sleeping On The Biggest App Store Story?</title>
    <link href="https://infrequently.org/2024/01/the-web-is-the-app-store/"/>
    <updated>2024-01-01T00:00:00Z</updated>
    <id>https://infrequently.org/2024/01/the-web-is-the-app-store/</id>
    <content type="html"><![CDATA[
      <p>The tech news is chockablock<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-recent-antitrust-news-1" id="fnref-recent-antitrust-news-1">1</a></sup> with <a href="https://open-web-advocacy.org/blog/owa-2023-review/">antitrust rumblings and slow-motion happenings.</a> Eagle-eyed press coverage, regulatory reports, and legal discovery have comprehensively documented the shady dealings of <a href="https://www.theverge.com/2020/4/3/21206400/apple-tax-amazon-tv-prime-30-percent-developers">Apple</a> and <a href="https://www.theverge.com/2023/11/30/23923533/google-explains-why-some-developers-were-able-to-get-away-with-paying-less-on-play">Google's</a> app stores. Pressure for change has built to an unsustainable level. Something's gotta give.</p>
<p>This is the backdrop to the biggest app store story nobody is writing about: on pain of <a href="https://ec.europa.eu/commission/presscorner/detail/en/qanda_20_2349#:~:text=In%20case%20a,systemic%20non%2Dcompliance.">steep fines,</a> gatekeepers are opening up to competing browsers. This, in turn, will enable competitors to replace app stores with directories of <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">Progressive Web Apps</a>. Capable browsers that <a href="https://patrickbrosset.com/articles/2023-09-26-my-first-tpac-conference/#:~:text=The%20Web%20Applications,was%20also%20reviewed.">expose</a> web app installation and powerful features to developers can kickstart app portability, breaking open the mobile duopoly.</p>
<p>But you'd never know it reading Wired or The Verge.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#the-buried-lede">The Buried Lede</a></li><li><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#disruption-disrupted">Disruption Disrupted</a></li><li><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#green-shoots">Green Shoots</a></li><li><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#a-new-hope">A New Hope</a></li></ul></nav>
<p>With shockingly few <a href="https://www.theregister.com/2023/10/09/apple_app_store/">exceptions,</a> coverage of app store regulation assumes the answer to crummy, extractive native app stores is other native app stores. This unexamined framing shapes hundreds of pieces covering regulatory events, including <a href="https://www.rollingstone.com/culture/culture-commentary/internet-future-about-to-get-weird-1234938403/">by web-friendly authors.</a> The tech press almost universally fails to mention the web as a <a href="https://en.wikipedia.org/wiki/Substitute_good">substitute</a> for native apps and fail to inform readers of its potential to disrupt app stores.</p>
<p>As <a href="https://doctorow.medium.com/the-open-web-is-good-actually-9683c692df84#:~:text=%E2%80%9CAn%20app%20is%20just%20a%20web%2Dpage%20wrapped%20in%20enough%20IP%20to%20make%20it%20a%20crime%20to%20defend%20yourself%20against%20corporate%20predation%E2%80%9D">Cory Doctorow observed</a>:</p>
<blockquote>
<p>&quot;An app is just a web-page wrapped in enough IP to make it a crime to defend yourself against corporate predation.&quot;</p>
</blockquote>
<p>The implication is clear: browsers unchained can do to mobile what the web did to desktop, where more than 70% of daily &quot;jobs to be done&quot; happen on the web.</p>
<p>Replacing mobile app stores will look different than the web's path to desktop centrality, but the enablers are waiting in the wings. It has gone largely unreported that <a href="https://web.dev/explore/progressive-web-apps">Progressive Web Apps (PWAs)</a> have been held back by Apple and Google denying competing browsers access to essential APIs.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-convergent-agendas-2" id="fnref-convergent-agendas-2">2</a></sup></p>
<p>Thankfully, regulators haven't been waiting on the press to explain the situation. Recent interventions into mobile ecosystems include requirements to repair browser choice, and the analysis backing those regulations takes into account the web's role as a potential competitor (e.g., <a href="https://www.jftc.go.jp/file/230327EN_Summary.pdf">Japan's JFTC (pdf)</a>).</p>
<p>Regulators seem to understand that:</p>
<ul>
<li>App stores protect proprietary ecosystems through preferential discovery and capabilities.</li>
<li>Stores then extract rents from developers dependent on commodity capabilities duopolists provide only through proprietary APIs.</li>
<li>App portability threatens the proprietary agenda of app stores.</li>
<li>The web can interrupt this model by bringing portability to apps and over-the-top discovery through search. This has yet to happen because...</li>
<li>The duopolists, in different ways, have kneecapped competing browsers along with their own, keeping the web from contesting the role of app stores.</li>
</ul>
<p>Apple and Google saw what the web did to desktop, and they've laid roadblocks to the competitive forces that would let history repeat on smartphones.</p>
<h2 id="the-buried-lede" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/the-web-is-the-app-store/#the-buried-lede">The Buried Lede</a></h2>
<p>The web's potential to disrupt mobile is evident to regulators, <a href="https://open-web-advocacy.org/">advocates</a>, and developers. So why does the tech news fail to explain the situation?</p>
<p>Consider <a href="https://www.techmeme.com/231226/p14#a231226p14">just one</a> of the many antitrust events of recent months. It was covered by <a href="https://www.theverge.com/2023/12/28/24017565/japan-plans-to-crack-down-on-apple-and-google-app-stores">The Verge</a>, <a href="https://www.macrumors.com/2023/12/27/japan-preparing-eu-style-law/">Mac Rumors</a>, <a href="https://appleinsider.com/articles/23/12/26/japan-plans-to-fine-apple-over-app-stores-and-antitrust-issues">Apple Insider</a>, and <a href="https://news.ycombinator.com/item?id=38773429">more.</a></p>
<p>None of the linked articles note browser competition's potential to upend app stores. Browsers unshackled have the potential to free businesses from build-it-twice proprietary ecosystems, end rapacious app store taxes, pave the way for new OS entrants — all without the valid security concerns side-loading introduces.</p>
<p>Lest you think this an isolated incident, <a href="https://www.techmeme.com/230820/p8#a230820p8">this article on the impact of the EU's DMA</a> lacks any hint of the web's potential to unseat app stores. You can repeat this trick with <a href="https://www.techmeme.com/search/query?q=EU+DMA&amp;wm=false"><em>any</em> DMA story from the past year</a>. Or spot-check <a href="https://www.techmeme.com/230201/p11#a230201p11">coverage</a> of the <a href="https://www.ntia.gov/report/2023/competition-mobile-app-ecosystem">NTIA's February report.</a></p>
<p>Reporters are &quot;covering&quot; these stories in the lightest sense of the word. Barrels of virtual ink has been spilt documenting unfair app store terms, conditions, and competition. And yet.</p>
<h2 id="disruption-disrupted" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/the-web-is-the-app-store/#disruption-disrupted">Disruption Disrupted</a></h2>
<p>In an industry obsessed with &quot;disruption,&quot; why is this David vs. Goliath story going untold? Some theories, in no particular order.</p>
<p>First, Mozilla <a href="https://infrequently.org/2020/06/platform-adjacency-theory/#the-committee-to-cast-the-web-in-amber">isn't advocating for a web that can challenge native apps,</a> and none of the other major browser vendors are telling the story either. Apple and Google have no interest in seeing their lucrative proprietary platforms supplanted, and Microsoft (your narrator's employer) <a href="https://www.theverge.com/2023/10/24/23930478/microsoft-ceo-satya-nadella-mobile-windows-phone">famously lacks sustained mobile focus.</a></p>
<p>Next, it's hard to overlook that tech reporters live like wealthy people, iPhones and all. From that vantage point, it's often news that the web is <a href="https://fugu-tracker.web.app/">significantly more capable</a> on other OSes (never mind that they spend much of every day working in a desktop browser). It's hard to report on the potential of something you can't see for yourself.</p>
<p>Also, this might all be Greek. Reporters and editors aren't software engineers, so the potential of browser competition can remain understandably opaque. Stories that include mention of &quot;alternative app stores&quot; generally fail to mention that these stores may not be as safe, or that OS restrictions on features won't disappear just because of a different distribution mechanism, or that the security track records of the <em>existing</em> duopolist app stores are sketchy at best. Under these conditions, it's asking a lot to expect details-based discussion of alternatives, given the many technical wrinkles. Hopefully, <a href="https://open-web-advocacy.org/">someone can walk them through it.</a></p>
<p>Further, <a href="https://en.wikipedia.org/wiki/Contestable_market">market contestability theory</a> has only recently become a big part of the tech news beat. Regulators have been writing reports to convey their understanding of the market, and to shape effective legislation that will unchain the web, but smart folks unversed in both antitrust and browser minutiae might need help to pick up what regulators are putting down.</p>
<p>Lastly, it hasn't happened yet. Yes, <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">Progressive Web Apps</a> have been around for a few years, but they haven't had an impact on the iPhones that reporters and their circles almost universally carry. It's much easier to get folks to cover stories that directly affect them, and this is one that, so far, largely hasn't.</p>
<h2 id="green-shoots" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/the-web-is-the-app-store/#green-shoots">Green Shoots</a></h2>
<p>The seeds of web-based app store dislocation have already been sown, but the chicken-and-egg question at the heart of platform competition looms.</p>
<p>On the technology side, Apple has been <a href="https://infrequently.org/2021/04/progress-delayed/">enormously successful at denying essential capabilities to the web</a> through a strategy of compelled monoculture combined with strategic foot-dragging.</p>
<p></p><figure><a href="https://mastodon.social/@bobpony/111602947135060878" alt="undefined" target="_blank"><picture style="--lqip: -175509" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/every_browser_toot.webp&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/the-web-is-the-app-store/every_browser_toot.webp" alt="Missing alt text" style="aspect-ratio: 682 / 841" class="preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption></figcaption>      </figure><p></p>
<p>As an example, the <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/">eight-year delay</a> in implementing Push Notifications for the web<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-checkbox-compliance-3" id="fnref-checkbox-compliance-3">3</a></sup> kept many businesses from giving the web a second thought. If they couldn't re-engage users at the same rates as native apps, the web might as well not exist on phones. This logic has played out on a loop over the last decade, category-by-category, with gatekeepers preventing competing browsers from bringing capabilities to web apps that would let them supplant app stores<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-convergent-agendas-2" id="fnref-convergent-agendas-2:1">2:1</a></sup> while simultaneously keeping them from being discovered through existing stores.</p>
<p>Proper browser choice could upend this situation, finally allowing the web to provide &quot;table stakes&quot; features in a compelling way. For the first time, developers could bring the modern web's full power to wealthy mobile users, enabling the &quot;write once, test everywhere&quot; vision, and cut out the app store middleman — all without sacrificing essential app features or undermining security.</p>
<p>Sunsetting the 30% tax requires a compelling alternative, and Apple's simultaneous underfunding of Safari and compelled adoption of its underpowered engine have interlocked to keep the web out of the game. No wonder Apple is massively funding lobbyists, lawyers, and <a href="https://www.bloomberg.com/news/articles/2022-09-19/apple-flexes-muscle-as-quiet-power-behind-app-developer-group">astroturf groups</a> to keep engine diversity at bay while belatedly <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/">battening the hatches</a>.</p>
<p>On the business side, managers think about &quot;mobile&quot; as a category. Rather than digging into the texture of iOS, Android, and the differing web features available on each, businesses tend to bulk accept or reject the app store model. One sub-segment of &quot;mobile&quot; growing the ability to route around highway robbery Ts &amp; Cs is tantalising, but not enough to change the game; the web, like other metaplatforms, is only a disruptive force when pervasive and capable.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-self-censorship-4" id="fnref-self-censorship-4">4</a></sup></p>
<p>A prohibition on store discovery for web apps has buttressed Apple's denial of essential features to browsers:</p>
<p></p><figure><a href="https://developer.apple.com/app-store/review/guidelines/#2.4" alt="Even if developers overcome the ridiculous hurdles that Apple's shoddy browser engine throws up, they're still <a href='https://developer.apple.com/app-store/review/guidelines/#2.4'>prevented by Apple policy</a> from making interoperable web apps discoverable where users look for them." target="_blank"><picture style="--lqip: 174818" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2024/01/the-web-is-the-app-store/apple_4.2._highlight_minimum-functionality.png" alt="Even if developers overcome the ridiculous hurdles that Apple's shoddy browser engine throws up, they're still <a href='https://developer.apple.com/app-store/review/guidelines/#2.4'>prevented by Apple policy</a> from making interoperable web apps discoverable where users look for them." style="aspect-ratio: 626 / 136" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>Even if developers overcome the ridiculous hurdles that Apple's shoddy browser engine throws up, they're still <a href="https://developer.apple.com/app-store/review/guidelines/#2.4">prevented by Apple policy</a> from making interoperable web apps discoverable where users look for them.</figcaption>      </figure><p></p>
<p><a href="https://developer.chrome.com/docs/android/trusted-web-activity">Google's answer to web apps in Play is a dog's breakfast</a>, but it <em>does</em> at least exist for developers willing to put in the effort, or for teams savvy enough to reach for <a href="https://www.pwabuilder.com/">PWA Builder.</a></p>
<p>Recent developments also point to a competitive future for capable web apps.</p>
<p>First, browser engine choice should become a reality on iOS in the EU in 2024, thanks to the plain language of the DMA. Apple will, of course, attempt to delay the entry of competing browsers through as-yet-unknown strategies, but the clock is ticking. Once browsers can enable capable web apps with easier distribution, the logic of the app store loses a bit of its lustre.</p>
<p>Work is also underway to give competing browsers a <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/WebInstall/explainer_cross_domain.md">chance to facilitate PWAs that can install other PWAs.</a> Web App Stores would then become a real possibility through browsers that support them, and we should expect that regulatory and legislative interventions will facilitate this in the near future. Removed from the need to police security (browsers have that covered) and handle distribution (websites update themselves), PWA app stores like <a href="https://store.app/">store.app</a> can become honest-to-goodness app management surfaces that can safely facilitate discovery and sync.</p>
<figure class="row">
<figure class="two">
<img src="https://infrequently.org/2024/01/the-web-is-the-app-store/appsco.pe.webp" style="aspect-ratio: 1420 / 2862;" decoding="async" loading="lazy" />
<img src="https://infrequently.org/2024/01/the-web-is-the-app-store/store.app.webp" style="aspect-ratio: 1420 / 2862;" decoding="async" loading="lazy" />
</figure>
<figcaption>
  PWA app stores like <a href="https://appsco.pe/" target="_new">Appscope</a> and <a href="https://store.app/">store.app</a> exist, but they're hobbled by gatekeepers that have denied competing browsers access to APIs that could turn PWA directories into real contenders.
<figcaption>
</figcaption></figcaption></figure>
<p>It's no surprise that Apple and Google have kept private the APIs needed to make this better future possible. They built the necessary infrastructure for the web to disrupt native, then kept it to themselves. This potential has remained locked away within organisations politically hamstrung by native app store agendas. But all of that is about to change.</p>
<p>This begs the question: where's the coverage? This is the most exciting moment in more than 15 years for the web vs. native story, but the tech press is whiffing it.</p>
<h2 id="a-new-hope" tabindex="-1"><a class="permalink" href="https://infrequently.org/2024/01/the-web-is-the-app-store/#a-new-hope">A New Hope</a></h2>
<p>2024 will be packed to the gills with app store and browser news, from implementation of the DMA, to the UK's renewed push into mobile browsers and cloud gaming, to new legislation arriving in many jurisdictions, to the first attempts at shipping iOS ports of Blink and Gecko browsers. Each event is a chance to inform the public about the already-raging battle for the future of the phone.</p>
<p>It's still possible to reframe these events and provide better context. We need a fuller discussion about what it will mean for mobile OSes to have competing native app stores when the underlying OSes are foundationally insecure. There are also existing examples of ecosystems with this sort of choice (e.g., China), and more needs to be written about the implications for users and developers. Instead of nirvana, the insecure status quo of today's mobile OSes, combined with (even more) absentee app store purveyors, turns side-loading into an alternative form of lock-in, with a kicker of added insecurity for users. With such a foundation, the tech-buying public could understand why a browser's superior sandboxing, web search's better discovery, and frictionless links are better than dodgy curation side-deals and <a href="https://www.theverge.com/c/22611236/epic-v-apple-emails-project-liberty-app-store-schiller-sweeney-cook-jobs#:~:text=%E2%80%9CRegarding%20review%20processes,we%20can%20detect%3F%E2%80%99%E2%80%9D"><em>&quot;beware of dog&quot;</em> sign security.</a></p>
<p>The more that folks understand the stakes, the more likely tech will genuinely change for the better. And isn't that what public interest journalism is <em>for</em>?</p>
<div style="font-size: 1rem;">
<p><em>Thanks to Charlie, <a href="https://www.kryogenix.org/days/">Stuart Langride</a>, and <a href="https://fberriman.com/blog/">Frances Berriman</a> for feedback on drafts of this post.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-recent-antitrust-news-1" class="footnote-item"><p><a href="https://www.theverge.com/antitrust">Antitrust is now a significant tech beat</a>, and recent events frequently include browser choice angles because regulators keep writing regulations that will enhance it. This beat is only getting more intense, giving the tech press ample column inches to explain the status quo more deeply and and educate around the most important issues.</p>
<p>In just the last two months:</p>
<ul>
<li>
<p>Google lost to Epic in a <a href="https://www.theverge.com/23994174/epic-google-trial-jury-verdict-monopoly-google-play">jury trial that determined Google's Play Store is an illegal monopoly.</a></p>
</li>
<li>
<p>Google <a href="https://www.theverge.com/23945184/epic-v-google-fortnite-play-store-antitrust-trial-updates/archives/3#stream-entry-d3f7f1e3-0891-475e-95f8-0b0a4320e371">lost all assumption of good faith</a> as evidence from the Epic trial <a href="https://www.theverge.com/2023/11/13/23959570/samsung-knew-the-project-banyan-deal-was-anticompetitive">showed the Play team to be scoundrels</a>, <a href="https://www.theverge.com/2023/11/15/23962589/i-dont-know-if-ensuring-fairness-was-part-of-my-job-i-never-thought-of-it-that-way">two-timers</a>, and <a href="https://www.theverge.com/2023/11/9/23954111/google-boasted-it-got-riot-games-not-to-launch-its-own-app-store-by-offering-10m">cretins</a> who were willing to set <a href="https://www.theverge.com/2023/11/20/23969690/google-spotify-android-billing-commission-secret-deal">shockingly unfair terms</a> for <a href="https://www.theverge.com/23954852/google-netflix-app-store-deal-play-10-percent-revshare">anyone</a> with enough market power to embarrass them. And that's before we get to the <a href="https://gizmodo.com/google-denies-its-project-hug-bribed-20-developers-1851009202">light attempted bribery.</a></p>
</li>
<li>
<p>Google's <a href="https://arstechnica.com/gadgets/2023/11/googles-36-search-revenue-share-with-apple-is-3x-what-android-oems-get/">witness also blurted out a statistic that is both anodyne and damning: 36%.</a> That's what Google pays Apple in search rev-share for default search placement in Safari. Normally, this would be a detail of a boring business deal. In context, however, it highlights Apple's decade-long suppression of iOS browser competition — combined with <a href="https://wpt.fyi/results/?label=experimental&amp;label=master&amp;aligned">poverty-level funding of WebKit</a> — which has <a href="https://www.theverge.com/2023/11/14/23960819/pichai-admits-google-pays-apple-a-36-percent-revenue-share-for-search-results">skimmed tens of billions in profit <em>per year</em> from the web</a> while starving browser development. This has deprived users, businesses, and web developers of safe (but critical) capabilities. It wasn't just Play that buggered the mobile web; Google was happy to outsource the dirty deed too.</p>
</li>
<li>
<p>Apple <a href="https://caselaw.nationalarchives.gov.uk/ewca/civ/2023/1445">lost on an appeal</a> to keep the UK's Competition and Market Authority (CMA) <a href="https://www.gov.uk/cma-cases/mobile-browsers-and-cloud-gaming">investigation into browsers and cloud gaming</a> on ice.<sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-mir-icing-5" id="fnref-mir-icing-5">5</a></sup></p>
</li>
<li>
<p>In December, Apple <a href="https://open-web-advocacy.org/blog/cma-reopens-investigation-into-apple/">declined to appeal to the UK's Supreme Court</a> for reasons that remain opaque.</p>
<p>Perhaps Apple didn't appeal because, in November, the UK unexpectedly brought forward the <a href="https://bills.parliament.uk/bills/3453">Digital Markets, Competition and Consumers Bill.</a> It looks set to become law early in the new year, standing up a regulator with real teeth who, one presumes, will not be predisposed to think well of Apple's delay of its predecessor's investigations.</p>
</li>
<li>
<p>Meanwhile, in the EU, Apple attempted to wriggle out of regulations that might bring about proper browser choice by <a href="https://www.theregister.com/2023/11/02/apple_safari_browser/">arguing that Safari is actually <em>three</em> under-performing browsers.</a> in <a href="https://brucelawson.co.uk/2023/apples-eu-legal-shenanigans/">a marketing trenchcoat</a><sup class="footnote-ref"><a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fn-hair-splitting-6" id="fnref-hair-splitting-6">6</a></sup>.</p>
</li>
<li>
<p>On the other side of the planet, <a href="https://asia.nikkei.com/Business/Technology/Japan-to-crack-down-on-Apple-and-Google-app-store-monopolies">news just broke that Japan will bring forward legislation</a> to target app store shenanigans. Given the JFTC's earlier findings about how interlocking layers of control have kept browsers from contesting app store prominence, we can expect some spicy legislative language around browsers.</p>
</li>
<li>
<p>Australia has also <a href="https://open-web-advocacy.org/blog/new-digital-competition-laws-for-australia/">just agreed (in principle) to do the same</a>, including language that acknowledges the role suppressing browser choice has had in preventing the web from competing with mobile native app ecosystems.</p>
</li>
</ul>
<p>All but one of the 19 links above are from just the last 60 days, a period which includes a holiday break in the US and Europe. With the EU's DMA coming into force in March and the CMA back on the job, browser antitrust enforcement is only accelerating. It sure would be great if reporters could occasionally connect these dots. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-recent-antitrust-news-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-convergent-agendas-2" class="footnote-item"><p>The stories of how Apple and Google have kept browsers from becoming real app stores differ greatly in their details, but the effects have been nearly identical: only their browsers could offer installation of web apps, and those browsers have done shockingly little to support web developers who want to depend on the browser as the platform.</p>
<p>The ways that Apple has undermined browser-based stores is relatively well known: no equivalent to PWA install or <a href="https://bugs.webkit.org/show_bug.cgi?id=255858">&quot;Smart Banners&quot; for the web</a>, no way for sites to <a href="https://bugs.webkit.org/show_bug.cgi?id=259490">suppress promotion of native apps</a>, no ability for competing browsers to trigger homescreen installation until just this year, etc. etc. The decade-long build of Apple's many and varied attacks on the web as a platform is a story that's both tired and under-told.</p>
<p>Google's malfeasance has gotten substantially less airtime, even among web developers – nevermind the tech press.</p>
<p>The story picks up in 2017, two years after the <a href="https://blog.chromium.org/2015/03/chrome-42-beta-push-notifications_12.html">release of PWAs and Push Notifications in Chrome.</a> At the time, the PWA install flow was something of a poorly practised parlour trick: installation used an unreliable homescreen shortcut API that failed on many devices with OEM-customised launchers. The shortcut API also came laden with baggage that prevented effective uninstall and cross-device sync.</p>
<p>To improve this situation, <a href="https://web.dev/articles/webapks">&quot;WebAPKs&quot; were developed.</a> This new method of installation allows for deep integration with the OS, similar to the Application Identity Proxy feature that Windows lets browsers to provide for PWAs, with one notable exception: on Android, only Chrome gets to use the WebAPK system.</p>
<p>Without getting into the weeds, suffice to say many non-Chrome browsers requested access. Only Google could meaningfully provide this essential capability across the Android ecosystem. So important were WebAPKs that Samsung gave up begging and <a href="https://medium.com/samsung-internet-dev/new-year-new-samsung-internet-b74f282e4429">reverse engineered it for their browser</a> on Samsung devices. This only worked on Samsung phones where Suwon's engineers could count on device services and system keys not available elsewhere. That hasn't helped other browsers, and it certainly isn't an answer to an ecosystem-level challenge.</p>
<p>Without WebAPK API access, competing browsers can't innovate on PWA install UI and can't meaningfully offer PWA app stores. Instead, the ecosystem has been left to limp along at the excruciating pace of Chrome's PWA UI development.</p>
<p>Sure, Chrome's PWA support has been a damn sight better than Safari's, but that's just damning with faith praise. Both Apple and Google have done their part to quietly engineer a decade of unchallenged native app dominance. Neither can be trusted as exclusive stewards of web competitiveness. Breaking the lock on the doors holding back real PWA installation competition will be a litmus test for the effectiveness of regulation now in-flight. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-convergent-agendas-2" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-convergent-agendas-2:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-checkbox-compliance-3" class="footnote-item"><p>Push Notifications were, without exaggeration, the single most requested mobile Safari feature in the eight years between Chromium browsers shipping and <a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/">Apple's 2023 capitulation.</a></p>
<p>It's unedifying to recount all of the ways Apple prevented competing iOS browsers from implementing Push while publicly gaslighting developers who requested this business-critical feature. Over and over and over again. It's also unhelpful to fixate on the runarounds that Apple privately gave companies with enough clout to somehow find an Apple rep to harangue directly. So, let's call it water under the bridge. Apple <a href="https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_web_apps_and_browsers">shipped</a>, so we're good, right?</p>
<p>Right?</p>
<p>I regret to inform you, dear reader, that it is not, in fact, &quot;good&quot;.</p>
<p>Despite most of a decade to study up on the problem space, and nearly <a href="https://en.wikipedia.org/wiki/Apple_Push_Notification_service">15 years of of experience</a> with Push, Apple's implementation is anything but complete.</p>
<p>The first few releases exposed APIs that hinted at important functionality that was broken or missing. Features as core as closing notifications, or updating text when new data comes in. The implementation of Push that Apple shipped could not allow a chat app to show only the latest message, or a summary. Instead, Apple's broken system leaves a stream of notifications in the tray for every message.</p>
<p>Many important features didn't work. <a href="https://bugs.webkit.org/show_bug.cgi?id=258922">Some still don't.</a>. And the pathetic set of customisations provided for notifications are a sick, sad joke.</p>
<p>Web developers have once again been left to dig through the wreckage to understand just how badly Apple's <em>cough</em> &quot;minimalist&quot; <em>cough</em> implementation is compromised. And boy howdy, is it bad.</p>
<p>Apple's implementation might have <a href="https://wpt.fyi/results/notifications?label=experimental&amp;label=master&amp;aligned">passed surface-level tests</a> (gotta drive up that score!), but it's unusable for serious products. It's possible to draw many possible conclusions from this terrible showing, but even the relative charity of Hanlon's Razor is damning.</p>
<p>Nothing about this would be worse than any other under-funded, trailing-edge browser over the past three decades (which is to say, a bloody huge problem), except for Apple's well-funded, aggressive, belligerent ongoing protest to every regulatory attempt to allow true browser choice for iPhone owners.</p>
<p>In the year 2024, you can have any iOS browser you like. You can even set them as default. They <em>might</em> even have APIs that look like they'll solve important product needs, but as long as they're forced to rely on Apple's shit-show implementation, the web can't ever be a competitive platform.</p>
<p>When Apple gets to define the web's potential, the winner will always be native, and through it, Apple's bottom line. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-checkbox-compliance-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-self-censorship-4" class="footnote-item"><p>The muting effect of Apple's abuse of monopoly over wealthy users to kneecap the web's capabilities is aided by the self-censorship of web developers. The values of the web are a mirror world to native, where developers are feted for adopting bleeding-edge APIs. On the web, features aren't &quot;available&quot; until 90+% of all users have access to them. Because <a href="https://analytics.wikimedia.org/dashboards/browsers/#all-sites-by-os-and-browser">iOS is at least 20%</a> of <a href="https://gs.statcounter.com/browser-market-share/">the pie</a>), web developers don't go near features Apple fails to support. Which is a <em>lot</em>.</p>
<figure>
  <picture>
    <img src="https://infrequently.org/2024/01/the-web-is-the-app-store/caniuse_browser_scores.webp" decoding="async" loading="lazy" style="aspect-ratio: 544 / 440;" />
  </picture>
  <figcaption>
    caniuse.com's <a href="https://caniuse.com/#:~:text=See%20full%20list-,Browser%20scores,-Current%20version">"Browser Score"</a> is one way to understand the scale of the gap in features that Apple has forced on all iOS browsers.
  </figcaption>
</figure>
<figure>
  <picture>
    <img src="https://infrequently.org/2024/01/the-web-is-the-app-store/wpt_browser_specific_failures.webp" decoding="async" loading="lazy" style="aspect-ratio: 1264 / 591;" />
  </picture>
  <figcaption>
    The <a href="https://wpt.fyi/">Web Platform Tests dashboard</a> highlights 'Browser Specific Failures', which only measure failures <em>in tests for features the browser claims to support</em>. Not only are iOS browsers held back by Apple's shockingly poor feature support, but the features that _are_ available are broken so often that many businesses feel no option but to retreat to native APIs that Apple doesn't break on a whim, forcing the logic of the app store on them if they want to reach valuable users.
  </figcaption>
</figure>
<p>Apple's pocket veto over the web is no accident, and its abuse of that power is no bug.</p>
<p>Native app stores can only take an outsized cut if the web remains weak and developers stay dependent on proprietary APIs to access commodity capabilities. A prohibition on capable engines prevents feature parity, suppressing competition. A feature-poor, unreliable open web is essential to prevent the dam from breaking.</p>
<p>Why, then, have competing browser makers played along? Why aren't Google, Mozilla, Microsoft, and Opera on the ramparts, waving the flag of engine choice? Why do they silently lend their brands to Apple's campaign against the web? Why don't they rename their iOS browsers to &quot;Chrome Lite&quot; or &quot;Firefox Lite&quot; until genuine choice is possible? Why don't they ask users to write their representatives or sign petitions for effective browser choice? It's not like they shrink from it for <a href="https://blog.mozilla.org/en/mozilla/news/mozilla-joins-net-neutrality-blackout-for-break-the-internet-day/">other worthy causes.</a></p>
<p>I'm shocked by not surprised by the tardiness of browser bosses to seize the initiative. Instead of standing up to unfair terms, they've rolled over time and time again. It makes a perverse sort of sense.</p>
<p>More than 30 years have passed since we last saw <a href="https://en.wikipedia.org/wiki/History_of_Unix#:~:text=In%201983%2C%20the%20U.S.%20Department,System%20V%20into%20the%20market.">effective tech regulation.</a> The careers of those at the top have been forged under the unforgiving terms of late-stage, might-makes-right capitalism, rather than the logic of open markets and standards. Today's bosses didn't rise by sticking their necks above the parapets to argue virtue and principle. At best, they kept the open web dream alive by quietly nurturing the potential of open technology, hoping the situation would change.</p>
<p>Now it has, and yet they cower.</p>
<p>Organisations that value conflict aversion and <em>&quot;the web's lane is desktop&quot;</em> thinking get as much of it as they care to afford. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-self-censorship-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-mir-icing-5" class="footnote-item"><p>Recall that Apple <a href="https://www.reuters.com/technology/apple-wins-appeal-against-uks-decision-investigate-its-mobile-browser-2023-03-31/">won an upset victory in March</a> after litigating the meaning of the word &quot;may&quot; and arguing that the CMA wasn't wrong to find after multiple years of investigations that Apple were (to paraphrase) inveterate shitheels, but rather that the CMA waited <em>too long</em> (six months) to bring an action which might have had teeth.</p>
<p>Yes, you're reading that right; Apple's <em>actual</em> argument to the Competition Appeal Tribunal amounted to a mashup of rugged, free-market fundamentalist <em>&quot; but mah regulatory certainty!&quot;</em>, performative fainting into strategically placed couches, and feigned ignorance about issues it knows it'll have to address in other jurisdictions.</p>
<p>Thankfully, the Court of Appeals was not to be taken for fools. Given the <a href="https://caselaw.nationalarchives.gov.uk/ewca/civ/2023/1445#:~:text=In%20my%20judgement%2C%20the%20CAT%20lost%20sight%20of%20this%20consideration.%20There%20is%20no%20overarching%20principle%20that%20an%20undertaking%20is%20entitled%20to%20be%20investigated%20once%2C%20and%20once%20only.">harsh (in British) language</a> of the reversal, we can hope a chastened Competition Appeal Tribunal will roll over less readily in future. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-mir-icing-5" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-hair-splitting-6" class="footnote-item"><p>If you're getting the sense that legalistic hair-splitting is what Apple spends its <a href="https://venturebeat.com/mobile/apples-former-top-lawyer-1-billion-budget-enabled-high-risk-strategies/">billion-dollar-per-year legal budget</a> on because it has neither the facts nor real benefits to society on its side, <a href="http://www.fosspatents.com/2023/02/japans-competition-authority-jftc.html">wait 'till you hear about some of the stuff it filed with Japan's Fair Trade Commission!</a></p>
<p>A clear strategy is being deployed. Apple:</p>
<ul>
<li>First claims there's <a href="https://www.congress.gov/116/meeting/house/110883/witnesses/HHRG-116-JU05-Wstate-CookT-20200729.pdf">no there there (pdf).</a> When that fails...</li>
<li>Claims competitors that it has expressly ham-strung are credible substitutes. When that fails...</li>
<li>Claims security would suffer if reasonable competition were allowed. Rending of garments is performed while prophets of doom recycle the script that the sky will fall if competing browsers are allowed (which would, in turn, expand the web's capabilities). Many treatments of this script fill the inboxes of regulators worldwide. When those bodies investigate, e.g. the history of iOS's forced-web-monoculture insecurity, and inevitably reject these farcical arguments, Apple...</li>
<li>Uses any and every procedural hurdle to prevent intervention in the market it has broken.</li>
</ul>
<p>The modern administrative state indulges firms with <em>&quot;as much due process as money can buy&quot;</em>, and Apple knows it, viciously contesting microscopic points. When bluster fails, <a href="https://infrequently.org/2022/02/minimum-standards/">huffingly implemented, legalistic, hair-splitting &quot;fixes&quot; are deployed</a> on the slowest possible time scale. This strategy buys years of delay, and it's everywhere: browser and mail app defaults, payment alternatives, engine choice, and right-to-repair. Even charging cable standardisation took years longer than it should have thanks to stall tactics. This maximalist, joined-up legal and lobbying strategy works to exhaust regulators and bamboozle legislators. Delay favours the monopolist.</p>
<p>A firm that can <a href="https://www.youtube.com/watch?v=17p3ThgMQYo">transform the economy of an entire nation</a> just by paying a bit of the tax it owes won't even notice a line item for lawyers to argue the most outlandish things at every opportunity. Apple (correctly) calculates that regulators are gun-shy about punishing them for delay tactics, so engagement with process is a is a win by default. Compelling $1600/hr white-shoe associates to make ludicrous, unsupportable claims is a <em>de facto</em> win when delay brings in billions. Regulators are too politically cowed and legally ham-strung to do more, and Apple plays process like a fiddle. <a href="https://infrequently.org/2024/01/the-web-is-the-app-store/#fnref-hair-splitting-6" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Safari 16.4 Is An Admission</title>
    <link href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/"/>
    <updated>2023-02-22T00:00:00Z</updated>
    <id>https://infrequently.org/2023/02/safari-16-4-is-an-admission/</id>
    <content type="html"><![CDATA[
      <p>If you're a web developer not living under a rock, you probably saw last week's <a href="https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes">big Safari 16.4 reveal</a>. There's much to cheer, but we need to talk about why this mega-release is happening now, and what it means for the future.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#webkit's-roaring-twenties">WebKit's Roaring Twenties</a></li><li><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#good-things-come-in-sixes">Good Things Come In Sixes</a></li><li><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#what-changed%3F">What Changed?</a></li><li><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#headcount-is-destiny">Headcount Is Destiny</a></li><li><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#early-innings">Early Innings</a></li></ul></nav>
<p>But first, the list!</p>
<h2 id="webkit's-roaring-twenties" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#webkit's-roaring-twenties">WebKit's Roaring Twenties</a></h2>
<p>Apple's summary combines dozens of minor fixes with several big-ticket items. Here's an overview of the most notable features, prefixed with the year they shipped in Chromium:</p>
<ul>
<li><a href="https://developer.chrome.com/blog/push-notifications-on-the-open-web/"><time datetime="2015-02">2015</time></a>: Web Push for iOS (<a href="https://webventures.rejh.nl/blog/2023/ios-web-push-requires-install/">but only for installed PWAs</a>)</li>
<li><a href="https://developer.chrome.com/en/articles/badging-api/"><time datetime="2020-04">2020</time></a>: PWA Badging API (for unread counts) and <code>id</code> support (making updates smoother)</li>
<li><a href="https://dev.opera.com/blog/installable-web-apps/"><time datetime="2015-06">2015</time></a>: PWA installation for third-party browsers (but not to parity with <a href="https://developer.apple.com/documentation/webkit/promoting_apps_with_smart_app_banners">&quot;Smart Banners&quot;</a>)</li>
<li>A bevy of Web Components features, many of which Apple had held up in standards bodies for <em>years</em><sup class="footnote-ref"><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-u-turns-1" id="fnref-u-turns-1">1</a></sup>, including:
<ul>
<li><a href="https://web.dev/constructable-stylesheets/"><time datetime="2019-03">2019</time></a>: Constructable Stylesheets (important for performance)</li>
<li><a href="https://web.dev/more-capable-form-controls/"><time datetime="2019-09">2019</time></a>: <a href="https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/">Form participation and default ARIA role</a></li>
<li><a href="https://developer.chrome.com/articles/declarative-shadow-dom/"><time datetime="2021-04">2021</time></a>: <a href="https://webkit.org/blog/13851/declarative-shadow-dom/">Declarative Shadow DOM</a> for &quot;SSR&quot;</li>
</ul>
</li>
<li>Myriad small CSS improvements and animation fixes, but also:
<ul>
<li><a href="https://developer.chrome.com/blog/cssom/"><time datetime="2018-04">2018</time></a>: CSS Typed OM for faster styling from JavaScript</li>
<li><a href="https://css-tricks.com/exploring-property-and-its-animating-powers/"><time datetime="2020-08">2020</time></a>: CSS Custom Properties can now be animated</li>
</ul>
</li>
<li><a href="https://developer.chrome.com/blog/new-in-chrome-77/#lazy-loading"><time datetime="2019-09">2019</time></a>: <code>&lt;iframe&gt;</code> lazy loading</li>
<li><a href="https://developer.chrome.com/docs/workbox/remove-buggy-service-workers/#set-a-clear-site-data-header"><time datetime="2017-09">2017</time></a>: <code>Clear-Site-Data</code> for Service Worker use at scale</li>
<li><a href="https://developer.chrome.com/blog/new-in-chrome-94/#webcodecs"><time datetime="2021-09">2021</time></a>: Web Codecs for video (but not audio)</li>
<li><a href="https://developer.chrome.com/blog/new-in-chrome-91/#more"><time datetime="2021-05">2021</time></a>: WASM SIMD for better ML and games</li>
<li><a href="https://developer.chrome.com/blog/compression-streams-api/"><time datetime="2020-03">2020</time></a>: Compression Streams</li>
<li><a href="https://developer.chrome.com/articles/reporting-api/"><time datetime="2018-09">2018</time></a>: Reporting API (for learning about crashes and metrics reporting)</li>
<li><a href="https://developer.chrome.com/en/articles/wake-lock/"><time datetime="2020-07">2020</time></a>: Screen Orientation &amp; Screen Wake Lock APIs (critical for games)</li>
<li><a href="https://developer.chrome.com/blog/offscreen-canvas/"><time datetime="2018-09">2018</time></a>: Offscreen Canvas (but only 2D, which isn't what folks really need)</li>
<li>Critical usability and quality fixes for WebRTC</li>
</ul>
<p>A number of improvements look promising, but remain exclusive to macOS and iPadOS:</p>
<ul>
<li>Fullscreen API fixes</li>
<li>AVIF and AV1 support</li>
</ul>
<p>The lack of iOS support for Fullscreen API on <code>&lt;canvas&gt;</code> elements continues to harm game makers; likewise, the lack of AVIF and AV1 holds back media and streaming businesses.</p>
<p>Regardless, Safari 16.4 is astonishingly dense with delayed features, inadvertantly emphasising just how far behind WebKit has remained for many years and how effective the <a href="https://www.chromium.org/blink/launching-features/">Blink Launch Process</a> has been in allowing Chromium to ship responsibly while consensus was witheld in standards by Apple.</p>
<p><a href="https://www.youtube.com/watch?v=1Z83L6xa1tw">The requirements of that process</a> accelerated Apple's catch-up implementations by mandating proof of developer enthusiasm for features, extensive test suites, and accurate specifications. This collateral put the catch-up process on rails for Apple.</p>
<p>The intentional, responsible leadership of Blink was no accident, but to see it rewarded so definitively is gratifying.</p>
<p>The size of the release was expected in some corners, owing to the torrent of WebKit blog posts over the last few weeks:</p>
<ul>
<li><time datetime="2023-01-31">Jan. 31st</time>: <a href="https://webkit.org/blog/13708/allowing-web-share-on-third-party-sites/">Web Share changes</a></li>
<li><time datetime="2023-02-06">Feb. 6th</time>: <a href="https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/">Form participation for Web Components</a></li>
<li><time datetime="2023-02-08">Feb. 8th</time>: <a href="https://webkit.org/blog/13813/try-css-nesting-today-in-safari-technology-preview/">CSS Nesting</a> (not enabled for Beta)</li>
<li><time datetime="2023-02-13">Feb. 13th</time>: <a href="https://webkit.org/blog/13851/declarative-shadow-dom/">Declarative Shadow DOM</a></li>
<li><time datetime="2023-02-15">Feb. 15th</time>: <a href="https://webkit.org/blog/13862/the-user-activation-api/">User Activation API changes</a></li>
<li><time datetime="2023-02-16">Feb. 16th, 2023</time>: <a href="https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/">Web Push API for iOS</a></li>
</ul>
<p>This is a <em>lot</em>, particularly considering that Apple has <a href="https://en.wikipedia.org/wiki/Safari_version_history">upped the pace of new releases to once every eight weeks (or thereabouts)</a> over the past year and a half.</p>
<h2 id="good-things-come-in-sixes" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#good-things-come-in-sixes">Good Things Come In Sixes</a></h2>
<p>Leading browsers moved to 6-week update cadence <a href="https://blog.mozilla.org/futurereleases/2011/07/19/every-six-weeks/">by 2011 at the latest</a>, routinely delivering fixes at a quick clip. It took another decade for Apple to finally adopt modern browser engineering and deployment practices.</p>
<p>Starting in <a href="https://en.wikipedia.org/wiki/Safari_version_history#Safari_15">September 2021</a>, Safari moved to an eight-week cadence. This is a sea change all its own.</p>
<p>Before Safari 15, Apple only delivered two substantial releases per year, a pattern that had been stable since 2016:</p>
<ul>
<li>New features were teased at WWDC in the early summer</li>
<li>They landed in the Fall alongside a new iOS version</li>
<li>A second set of small features trickled out the next Spring</li>
</ul>
<p>For a decade, two releases per year meant that progress on WebKit bugs was a roulette that developers lost by default.</p>
<p>In even leaner years (2012-2015), a single Fall release was all we could expect. This excruciating cadence affected Safari along with every other iOS browser <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/">forced to put its badge on Apple's sub-par product</a>.</p>
<p>Contrast Apple's manufactured scarcity around bug fix information with the open bug tracking and reliable candecne of delivery from leading browsers. Cupertino manages the <em>actual</em> work of Safari engineers through an Apple-internal system (<a href="https://apple.fandom.com/wiki/Radar">&quot;Radar&quot;</a>), making public bug reports a sort of parallel track. Once an issue is imported to a private Radar bug it's more likely to get developer attention, but this also obscures progress from view.</p>
<p>This lack of transparency is by design.</p>
<p>It provides Apple deniability while simultaneously setting low expectations, which are easier to meet. Developers facing showstopping bugs end up in a bind. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/">Without competitive recourse</a>, they can't even recommend a different browser because every iOS browser is forced to use WebKit, meaning every iOS browser is at <em>least</em> as broken as Safari.</p>
<!-- Features had lower odds of being cherry-picked into the private branch if they didn't make the pre-WWDC stabilisation branch cut. This dragged timelines for anticipated improvements past nine months in many cases. -->
<p>Given the <a href="https://infrequently.org/2021/04/progress-delayed/">dire state of WebKit</a>, and the <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#apple's-open-source-claim">challenges contributors face helping to plug the gaps</a>, these heartbreaks have induced a learned helplessness in much of the web community. So little improved, for so long, that some assumed it never would.</p>
<p>But here we are, with six releases a year and WebKit accelerating the pace at which it's closing the (large) gap.</p>
<h2 id="what-changed%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#what-changed%3F">What Changed?</a></h2>
<p>Many big-ticket items are missing from this release — iOS fullscreen API for <code>&lt;canvas&gt;</code>, Paint Worklets, true PWA installation APIs for competing browsers, Offscreen Canvas for WebGL, <a href="https://fugu-tracker.web.app/">Device APIs</a> (if only for installed web apps), etc. — but the pace is now blistering.</p>
<p>This is the power of just the <em>threat</em> of competition.</p>
<p>Apple's laywers have <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#apple's-arguments">offered claims in court</a> and in regulatory filings defending App Store rapaciousness because, in their telling, iOS browsers provide an alternative. If developers don't like the <em>generous</em> offer to take only 30% of revenue, there's always Cupertino's <em>highly</em> capable browser to fall back on.</p>
<p>The only problem is that regulators ask follow-up questions like <em>&quot;is it?&quot;</em> and <em>&quot;what do developers think?&quot;</em></p>
<p>Which they did.</p>
<p>TL;DR: it wasn't, and developers had <a href="https://open-web-advocacy.org/walled-gardens-report/"><em>lots</em></a> to say.</p>
<p>This is, as they say, a bad look.</p>
<p>And so Apple hedged, slowly at first, but ever faster as 2021 bled into 2022 and the momentum of additional staffing began to pay dividends.</p>
<h2 id="headcount-is-destiny" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#headcount-is-destiny">Headcount Is Destiny</a></h2>
<p>Apple <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#webkit-is-no-charity">had the resources needed to build a world-beating browser for more than a decade</a>. The choice to ship a slower, less secure, less capable engine was precisely that: <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#choices%2C-choices">a choice</a>.</p>
<p>Starting in 2021, Apple made a different choice, opening up dozens of Safari team positions. From 2023 perspective of pervasive tech layoffs, this might look like the same exuberant hiring Apple's competitors recently engaged in, but recall Cupertino had maintained <em>extreme</em> discipline about Safari staffing for nearly two decades. Feast or famine, Safari wouldn't grow, and Apple wouldn't put significant new resourcing into WebKit, no matter how far it fell behind.</p>
<p>The decision to hire aggressively, including some &quot;big gets&quot; in standards-land, indicates more is afoot, and the reason isn't that Tim lost his cool. No, this is a strategy shift. New problems needed new (old) solutions.</p>
<p>Apple undoubtedly hopes that a less egregiously incompetent Safari will blunt the intensity of arguments for iOS engine choice. Combined with (previously winning) <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#apple's-security-argument">security scaremongering</a>, reduced developer pressure might allow Cupertino to wriggle out of needing to compete worldwide, allowing it to ring-fence progress to markets too small to justify browser development resources (e.g., just the EU).</p>
<p>Increased investment also does double duty in the uncertain near future. In scenarios where Safari <em>is</em> exposed to real competition, a more capable engine provides fewer reasons for web developers to recommend other browsers. It takes time to board up the windows before a storm, and if competition is truly coming, this burst of energy looks like a belated attempt to batten the hatches.</p>
<p>It's critical to Apple that narrative discipline with both developers and regulators is maintained. Dilatory attempts at catch-up only work if developers tell each other that these changes are an inevitable outcome of Apple's long-standing commitment to the web (remember the first iPhone!?!). An easily distracted tech press will help spread the idea that this was always part of the plan; nobody is making Cupertino do anything it doesn't want to do, nevermind the <a href="https://www.gamesindustry.biz/apple-cma-remedies-for-cloud-gaming-on-ios-are-plainly-inappropriate-and-unreasonable">frantic regulatory filings and legal briefings</a>.</p>
<p>But what if developers see behind the veil? What if they begin to reflect and internalise Apple's abandonment of web apps after iOS 1.0 as an exercise of market power that held the web back for more than a decade?</p>
<p>That might lead developers to demand competition. Apple might not be able to ring-fence browser choice to a few geographies. The web might threaten Cupertino's ability to extract rents in precisely the way Apple represented in court that it already does.</p>
<h2 id="early-innings" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#early-innings">Early Innings</a></h2>
<p><a href="https://www.theregister.com/2023/02/07/mozilla_google_apple_webkit/">Rumours of engine ports are afoot</a>. The plain language of the EU's DMA is set to allow true browser choice on iOS. But the regulatory landscape is not at all settled. Apple might still prevent progress from spreading. It might yet sue its way to curtailing the potential size and scope of the market that will allow for the web to actually compete, and if it succeeds in that, no amount of fast catch-up in the next few quarters will pose a true threat to native.</p>
<p>Consider the omissions:</p>
<ul>
<li>PWA installation prompting</li>
<li>Fullscreen for <code>&lt;canvas&gt;</code></li>
<li>Real Offscreen Canvas</li>
<li>Improved codecs</li>
<li>Web Transport</li>
<li>WebGPU</li>
<li>Device APIs</li>
</ul>
<p>Depending on the class of app, any of these can be a deal-breaker, and if Apple isn't facing ongoing, effective competition it can just reassign headcount to other, &quot;more critical&quot; projects when the threat blows over. It wouldn't be the first time.</p>
<p>So, this isn't done. Not by a long shot.</p>
<p>Safari 16.4 is an admission that competition is effective and that Apple is spooked, but it isn't an answer. Only genuine browser choice will ensure the taps stay open.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-u-turns-1" class="footnote-item"><p>Apple's standards engineers have a long and inglorious history of stalling tactics in standards bodies to delay progress on important APIs, like <a href="https://web.dev/declarative-shadow-dom/">Declarative Shadow DOM</a> (<abbr>DSD</abbr>).</p>
<p>The idea behind DSD <a href="https://github.com/WICG/webcomponents/issues/71">was not new</a>, and the intensity of developer demand had only increased since Dimitri's 2015 sketch. A <a href="https://github.com/whatwg/dom/issues/510">2017 attempt to revive it</a> was <a href="https://github.com/whatwg/dom/issues/510#issuecomment-370980398">shot down in 2018 by Apple engineers without evidence or data</a>.</p>
<p>Throughout this period, Apple would engage sparsely in conversations, sometimes only weighing in at biannual face-to-face meetings. It was gobsmacking to watch them argue that features were unnecessary directly to the developers in the room who were personally telling them otherwise. This was disheartening because a key goal of any proposal was to gain support from iOS. In a world where nobody else could ship-and-let-live, and where Mozilla could not muster an opinion (it <a href="https://hacks.mozilla.org/2018/11/the-power-of-web-components/">did not ship Web Components until late 2018</a>), any whiff of disinterest from Apple was sufficient to kill progress.</p>
<p>The phrase &quot;stop-energy&quot; is often misused, but the dampening effect of Apple on the progress of Web Components after 2015-2016's <a href="https://web.dev/webcomponents-org/">burst of <abbr title="Version 1">V1</abbr> design energy</a> was palpable. After that, the only Web Components features that launched in leading-edge browsers were those that an engineer and <abbr>PM</abbr> were willing to accept could only reach part of the developer base.</p>
<p>I cannot stress enough how effectively this slowed progress on Web Components. The pantomime of regular face-to-face meetings continued, but Apple just stopped shipping. What had been a grudging willingness to engage on new features became a stalemate.</p>
<p>But needs must.</p>
<p>In early 2020, after months of background conversations and research, Mason Freed <a href="https://github.com/mfreed7/declarative-shadow-dom/commit/7117d860752452ba4dde112bbb9c3c63afb3aeef">posted</a> a <a href="https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md">new set of design alternatives</a>, which included extensive performance research. The conclusion was overwhelming: not only was Declarative Shadow DOM now in heavy demand by the community, but it would also make websites much faster.</p>
<p>The proposal looked shockingly like those sketched in years past. In a world where <code>&lt;template&gt;</code> existed and Shadow DOM V1 had shipped, the design space for Declarative Shadow DOM alternatives was not large; we just needed to pick one.</p>
<p>An updated proposal was presented to the Web Components Community Group in March 2020; Apple objected on spurious grounds, offering no constructive counter.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-counter-or-gtfo-2" id="fnref-counter-or-gtfo-2">2</a></sup></p>
<p>Residual questions revolved around security implications of changing parser behaviour, but these were also straightforward. The first draft of Mason's Explainer even <a href="https://github.com/mfreed7/declarative-shadow-dom/commit/7117d860752452ba4dde112bbb9c3c63afb3aeef#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R430">calls out why the proposal is less invasive than a whole new element</a>.</p>
<p>Recall that Web Components and the <code>&lt;template&gt;</code> element <em>themselves</em> were large parser behaviour changes; the semantics for <code>&lt;template&gt;</code> even required changes to the long-settled grammar of XML (long story, don't ask). A drumbeat of (and proposals for) new elements and attributes post-HTML5 also represent identical security risks, and yet we barrel forward with them. These have notably included <code>&lt;picture&gt;</code>, <code>&lt;portal&gt;</code> (<a href="https://web.dev/hands-on-portals/">proposed</a>), <code>&lt;fencedframe&gt;</code> (<a href="https://developer.chrome.com/en/docs/privacy-sandbox/fenced-frame/">proposed</a>), <code>&lt;dialog&gt;</code>, <code>&lt;selectmenu&gt;</code> (<a href="https://css-tricks.com/the-selectmenu-element/">proposed</a>), and <code>&lt;img srcset&gt;</code>.</p>
<p>The addition of <code>&lt;template shadowroot=&quot;open&quot;&gt;</code> would, indeed,  change parser behaviour, but not in ways that were unknowably large or unprecedented. Chromium's <a href="https://chromestatus.com/metrics/feature/popularity">usage data</a>, along with the <a href="https://httparchive.org/faq">HTTP Archive crawl HAR file corpus</a>, provided ample evidence about the prevalence of patterns that might cause issues. None were detected.</p>
<p>And yet, at TPAC 2020, Apple's representatives continued to press the line that large security issues remained. This was all <a href="https://youtu.be/xY2rpHsaGlI?t=906">considered at length</a>. Google's security teams audited the colossal volume of user-generated content Google hosts for problems and did not find significant concerns. And yet, Apple continued to apply stop-energy.</p>
<p>The feature eventually <a href="https://chromestatus.com/feature/5191745052606464">shipped with heavy developer backing as part of Chromium 90 in April 2021</a> but without consensus. Apple persistently repeated objections that had already been answered with patient explication and evidence.</p>
<p>Cupertino is now implementing this same design, and Safari will support DSD soon.</p>
<p>This has not been the worst case of Apple's deflection and delay — looking at you, Push Notifications — but serves as an exemplar. Problem solvers have been forced into a series of high-stakes gambits to solve developer problems by Apple (and, to a lesser extent, Mozilla) over Cupertino's dozen years of engine disinvestment.</p>
<p><em>Even in Chromium</em>, DSD was delayed by several quarters. Because of the Apple Browser Ban, cross-OS availability was postponed by two years. The fact that Apple will ship DSD without changes and without counterproposals across the long arc of obstruction implies claims of caution were, at best, overstated.</p>
<p>The only folks to bring data to the party were Googlers and web developers. No new thing was learned through groundless objection. No new understanding was derived from the delay. Apple did no research about the supposed risks. It has yet to argue why it's safe <em>now</em>, but wasn't then.</p>
<p>So let's call it what it was: concern trolling.</p>
<p>Uncritical acceptance of the high-quality design it had long delayed is an admission, of sorts. It demonstrates Apple's ennui about developer and user needs (until pressed), paired with great skill at deflection.</p>
<p>The playbook is simple:</p>
<ul>
<li>Use opaque standards processes to make it look like occasional attendance at a <abbr title="face-to-face">F2F</abbr> meeting is the same thing as good-faith co-engineering.</li>
<li><em>&quot;Just ask questions&quot;</em> when overstretched or uninterested in the problem.</li>
<li>Spread <abbr title="fear, uncertainty, and doubt">FUD</abbr> about the security or privacy of a meticulously-vetted design.</li>
<li>When all else fails, say you will formally object and then claim that others are <em>&quot;shipping whatever they want&quot;</em> and <em>&quot;not following standards&quot;</em> when they carefully launch a specced and tested design you were long consulted about, but withheld good faith engagement to improve.</li>
</ul>
<p>The last step works because only insiders can distinguish between legitimate critiques and standards process jockeying. Hanging the first-mover risk around the neck of those working to solve problems is nearly cost-free when you can <em>also</em> prevent designs from moving forward in standards, paired with a market veto (thaks to <a href="https://open-web-advocacy.org/walled-gardens-report/">anti-competitive shenanigans</a>).</p>
<p>Play this dynamic out over dozens of features across a decade, and you'll better understand why Chromium participants get exercised about the responsibility theatre various Apple engineers put on to avoid engaging substantively, while simultaneously blocking all forward movement. Understood in context, it decodes as delay and deflection; a way to avoid using standards bodies to help <em>actually</em> solve problems.</p>
<p>Cupertino has paid no price for deploying these smoke screens, thanks to the Apple Browser Ban and a lack of curiosity in the press. Without those shields, Apple engineers would have had to offer convincing arguments from data for why their positions were correct. Instead, they have whatabouted for over three years, only to suddenly implement proposals they recently opposed when the piercing gaze of regulators finally fell on WebKit.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fn-if-it-aint-broke-3" id="fnref-if-it-aint-broke-3">3</a></sup> <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fnref-u-turns-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-counter-or-gtfo-2" class="footnote-item"><p>The presence or absence of a counterproposal when objecting to a design is a primary indicator of seriousness within a standards discussion. All parties will have been able to examine proposals before any meeting, and in groups that operate by consensus, blocking objections are understood to be used sparingly by serious parties.</p>
<p>It's normal for disagreements to surface over proposed designs, but engaged and collaborative counter-parties will offer soft concerns – <em>&quot;we won't block on this, but we think it could be improved...&quot;</em> – or through the offer to bring a counterproposal. The benefits of a concrete counter are large. It demonstrates good faith in working to solve the problem and signals a willingness to ship the offered design. Threats to veto, or never implement a specific proposal, are just <em>not done</em> in the genteel world of web standards.</p>
<p>Over the past decade, making veto threats while offering neither data nor a counterproposal have become a hallmark of Apple's web standards footprint. It's a bad look, but it continues because nobody in those rooms wants to risk pissing off Cupertino. Your narrator considered a <a href="https://infrequently.org/2021/04/progress-delayed/">direct accounting of just the <em>consequences</em> of these tactics</a> a potentially career-ending move; that's how serious the stakes are.</p>
<p>The true power of a monopoly in standards is silence — the ability to get away with things others blanch at because they fear you'll hold an even larger group of hostages next time. <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fnref-counter-or-gtfo-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-if-it-aint-broke-3" class="footnote-item"><p>Apple has rolled out the same playbook in dozens of areas over the last decade, and we can learn a few things from this experience.</p>
<p>First, Apple corporate does not care about the web, no matter how much the individuals that work on WebKit (deeply) care. Cupertino's artificial bandwidth constraints on WebKit engineering ensured that it implements only when pressured.</p>
<p>That means that external pressure must be maintained. Cupertino must fear losing their market share for doing a lousy job. That's a feeling that hasn't been felt near the intersection of I-280 and CA Route 85 in a few years. For the web to deliver for users, gatekeepers must sleep poorly.</p>
<p>Lastly, Apple had the capacity and resources to deliver a richer web for a decade but simply declined. This was a choice — a question of will, not of design correctness or security or privacy.</p>
<p>Safari 16.4 is evidence, an admission that better was possible, and the delaying tactics were a sort of gaslighting. Apple disrespects the legitimate needs of web developers when allowed, so it must not be.</p>
<p>Lack of competition was the primary reason Apple feared no consequence for failing to deliver. Apple's protectionism towards Safari's participation-prize under-achievement hasn't withstood even the faintest whiff of future challengers, which should be an enduring lesson: no vendor must ever be allowed to deny true and effective browser competition. <a href="https://infrequently.org/2023/02/safari-16-4-is-an-admission/#fnref-if-it-aint-broke-3" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>The Market for Lemons</title>
    <link href="https://infrequently.org/2023/02/the-market-for-lemons/"/>
    <updated>2023-02-04T00:00:00Z</updated>
    <id>https://infrequently.org/2023/02/the-market-for-lemons/</id>
    <content type="html"><![CDATA[
      <p>For most of the past decade, I have spent a considerable fraction of my professional life consulting with teams building on the web.</p>
<p>It is not going well.</p>
<p>Not only are new services being built to a self-defeatingly low UX and performance standard, existing experiences are pervasively re-developed on unspeakably slow, JS-taxed stacks. At a business level, this is a disaster, raising the question: <em>&quot;why are new teams buying into stacks that have failed so often before?&quot;</em></p>
<p>In other words, <em>&quot;why is this market so inefficient?&quot;</em></p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2023/02/the-market-for-lemons/#what-did-they-know-and-when-did-they-know-it%3F">What Did They Know and When Did They Know It?</a></li><li><a href="https://infrequently.org/2023/02/the-market-for-lemons/#sandy-foundations">Sandy Foundations</a></li><li><a href="https://infrequently.org/2023/02/the-market-for-lemons/#denouement">Denouement</a></li><li><a href="https://infrequently.org/2023/02/the-market-for-lemons/#shrinkage">Shrinkage</a></li></ul></nav>
<p>George Akerlof's most famous paper introduced economists to the idea that <em>information asymmetries</em> distort markets and reduce the quality of goods because sellers with more information can pass off low-quality products as more valuable than informed buyers appraise them to be. (<a href="https://www.sfu.ca/~wainwrig/Econ400/akerlof.pdf">PDF</a>, <a href="https://en.wikipedia.org/wiki/The_Market_for_Lemons">summary</a>)</p>
<p>Customers that can't assess the quality of products pay too much for poor quality goods, creating a disincentive for high-quality products to emerge while working against their success when they do. For many years, this effect has dominated the frontend technology market. Partisans for slow, complex frameworks have successfully marketed lemons as the hot new thing, despite the pervasive failures in their wake, crowding out higher-quality options in the process.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/the-market-for-lemons/#fn-alex-approved-1" id="fnref-alex-approved-1">1</a></sup></p>
<p>These technologies were initially pitched on the back of <em>&quot;better user experiences&quot;</em>, but have <a href="https://dev.to/tigt/making-the-worlds-fastest-website-and-other-mistakes-56na">utterly failed</a> to deliver on that promise outside of the <a href="https://infrequently.org/2022/05/performance-management-maturity/">high-management-maturity organisations</a> in which they were born.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/the-market-for-lemons/#fn-everything-in-moderation-2" id="fnref-everything-in-moderation-2">2</a></sup> Transplanted into the wider web, these new stacks have proven to be <a href="https://infrequently.org/2022/12/performance-baseline-2023/">expensive duds</a>.</p>
<p>The complexity merchants knew their environments weren't typical, but sold their highly specialised tools to folks shopping for general purpose solutions anyway. They understood most sites lack latency budgeting, dedicated performance teams, hawkish management reviews, ship gates to prevent regressions, and end-to-end measurements of critical user journeys. They grasped that massive investment in controlling complexity is the only way to scale JS-driven frontends, but warned none of their customers.</p>
<p>They also knew that their choices were hard to replicate. Few can afford to build and maintain 3+ versions of a site (&quot;desktop&quot;, &quot;mobile&quot;, and &quot;lite&quot;), and vanishingly few web experiences feature long sessions and login-gated content.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/the-market-for-lemons/#fn-amortised-interaction-costs-3" id="fnref-amortised-interaction-costs-3">3</a></sup></p>
<p>Armed with this knowledge, they kept the caveats to themselves.</p>
<h2 id="what-did-they-know-and-when-did-they-know-it%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/the-market-for-lemons/#what-did-they-know-and-when-did-they-know-it%3F">What Did They Know and When Did They Know It?</a></h2>
<p>This information asymmetry persists; the worst actors still haven't levelled with their communities about what it takes to operate complex JS stacks at scale. They did not signpost the delicate balance of engineering constraints that allowed their products to adopt this new, slow, and complicated tech. Why? For the same reason used car dealers don't talk up average monthly repair costs.</p>
<p>The market for lemons depends on customers having less information than those selling shoddy products. Some who hyped these stacks early on were earnestly ignorant, which is forgivable when recognition of error leads to changes in behaviour. But that's not what the most popular frameworks of the last decade did.</p>
<p>As time passed, and the results continued to underwhelm, an initial lack of clarity was revealed to be intentional omission. These omissions have been material to both users and developers. Extensive evidence of these failures was provided directly to their marketeers, often by me. At some point (certainly by 2017) the omissions veered into intentional prevarication.</p>
<p>Faced with the dawning realisation that this tech mostly made things worse, not better, the JS-industrial-complex <a href="https://www.scientificamerican.com/article/exxon-knew-about-climate-change-almost-40-years-ago/">pulled an Exxon</a>.</p>
<p>They <em>could</em> have copped to an honest error, admitted that these technologies require vast infrastructure to operate; that they are unscalable in the hands of all but the most sophisticated teams. They did the opposite, doubling down, <a href="https://techcrunch.com/2017/04/18/facebook-announces-react-fiber-a-rewrite-of-its-react-framework/">breathlessly announcing vapourware year</a> after <a href="https://www.youtube.com/watch?v=NZoRlVi3MjQ">year</a> to forestall critical thinking about fundamental design flaws. They also worked behind the scenes to marginalise those who pointed out the disturbing results and extraordinary costs.</p>
<p>Credit where it's due, the complexity merchants have been incredibly effective in one regard: top-shelf marketing discipline.</p>
<p>Over the last ten years, they have worked overtime to make frontend an evidence-free zone. The hucksters knew that discussions about performance trade-offs would not end with teams investing more in their technology, so boosterism and misdirection were aggressively substituted for evidence and debate. Like a curtain of Halon descending to put out the fire of engineering dialogue, they blanketed the discourse with toxic positivity. Those who dared speak up were branded &quot;negative&quot; and &quot;haters&quot;, no matter how much data they lugged in tow.</p>
<h2 id="sandy-foundations" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/the-market-for-lemons/#sandy-foundations">Sandy Foundations</a></h2>
<p><a href="https://ericwbailey.website/published/modern-health-frameworks-performance-and-harm/">It was, of course, bullshit.</a></p>
<p>Astonishingly, gobsmackingly effective bullshit, but nonsense nonetheless. There was a point to it, though. Playing for time allowed the bullshitters to punt introspection of the always-wrong assumptions they'd built their entire technical ediface on:</p>
<ul>
<li>CPUs get faster every year (<em><a href="https://infrequently.org/2022/12/performance-baseline-2023/">they do not</a></em>)</li>
<li>Organisations can manage these complex stacks (<em><a href="https://infrequently.org/2022/05/performance-management-maturity/">they cannot</a></em>)</li>
</ul>
<p>In time, these misapprehensions would become cursed articles of faith.</p>
<p>All of this was <a href="https://www.youtube.com/watch?v=4bZvq3nodf4">falsified by 2016</a>, but nobody wanted to turn on the house lights while the JS party was in full swing. Not the developers being showered with shiny tools and boffo praise for replacing &quot;legacy&quot; HTML and CSS that performed fine. Not the scoundrels peddling foul JavaScript elixirs and potions. Not the managers that craved a check to cut and a rewrite to take credit for in lieu of critical thinking about user needs and market research.</p>
<p>Consider the narrative <a href="https://en.wikipedia.org/wiki/Baffles_(submarine)">Crazy Ivans</a> that led to this point.</p>
<p></p><figure><a href="https://youtu.be/Ar9R-CX217o?t=231" alt="By 2013 the trashfuture was here, just not evenly distributed yet. Undeterred, the complexity merchants spent a decade selling <a href='/2022/12/performance-baseline-2023/'>inequality-exascerbating technology</a> as a cure-all tonic." target="_blank"><picture style="--lqip: -358173" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/a-decade-of-error.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2023/02/the-market-for-lemons/a-decade-of-error.png" alt="By 2013 the trashfuture was here, just not evenly distributed yet. Undeterred, the complexity merchants spent a decade selling <a href='/2022/12/performance-baseline-2023/'>inequality-exascerbating technology</a> as a cure-all tonic." style="aspect-ratio: 1919 / 1080" class="preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>By 2013 the trashfuture was here, just not evenly distributed yet. Undeterred, the complexity merchants spent a decade selling <a href="https://infrequently.org/2022/12/performance-baseline-2023/">inequality-exascerbating technology</a> as a cure-all tonic.</figcaption>      </figure><p></p>
<!--

-->
<p>It's challenging to summarise a vast discourse over the span of a decade, particularly one as dense with jargon and acronyms as that which led to today's <em>status quo</em> of overpriced failure. These are not quotes, but vignettes of distinct epochs in our tortured journey:</p>
<ul>
<li>
<p><em>&quot;Progressive Enhancement has failed! Multiple pages are slow and clunky!</em></p>
<p><em>SPAs are a better user experience, and managing state is a big problem on the client side. You'll need a tool to help structure that complexity when rendering on the client side, and our framework works at scale&quot;</em></p>
<p>[  <a href="https://reactjs.org/blog/2014/02/15/community-roundup-16.html">illustrative example</a>  ]</p>
</li>
<li>
<p><em>&quot;Instead of waiting on the JavaScript that will absolutely deliver a superior SPA experience...someday...why not render on the server as well, so that there's something for the user to look at while they wait for our awesome and <em>totally</em> scalable JavaScript to collect its thoughts?&quot;</em></p>
<p>[  <a href="https://webbylab.com/blog/isomorphic-react/">an intro to &quot;isomorphic javascript&quot;, a.k.a. &quot;Server-Side Rendering&quot;, a.k.a. &quot;SSR&quot;</a>  ]</p>
</li>
<li>
<p><em>&quot;SPAs are a better experience, but everyone knows you'll need to do all the work twice because SSR makes that better experience minimally usable. But even with SSR, you might be sending so much JS that things feel bad. So give us credit for a promise of vapourware for delay-loading parts of your JS.&quot;</em></p>
<p>[  <a href="https://reactjs.org/blog/2018/11/13/react-conf-recap.html">impressive stage management</a>  ]</p>
</li>
<li>
<p><em>&quot;SPAs are a better experience. SSR is vital because SPAs take a long time to start up, and you aren't using our vapourware to split your code effectively. As a result, the main thread is often locked up, which could be bad?</em>&quot;</p>
<p><em>Anyway, this is totally your fault and not the predictable result of us failing to advise you about the controls and budgets we found necessary to scale JS in our environment. Regardless, we see that you lock up main threads for seconds when using our slow system, so in a few years we'll create a parallel scheduler that will break up the work transparently&quot;</em></p>
<p>[  <a href="https://www.youtube.com/watch?v=ZCuYPiUIONs">2017's beautiful overview of a fated errand</a> and <a href="https://www.youtube.com/watch?v=ByBPyMBTzM0">2018's breathless re-brand</a>  ]</p>
</li>
<li>
<p><em>&quot;The scheduler isn't ready, but thanks for your patience; here's a new way to spell your component that introduces new timing issues but doesn't address the fact that our system is incredibly slow, built for browsers you no longer support, and that CPUs are not getting faster&quot;</em></p>
<p>[  <a href="https://www.youtube.com/watch?v=wXLf18DsV-I">representative pitch</a>  ]</p>
</li>
<li>
<p><em>&quot;Now that you're 'SSR'ing your SPA and have re-spelt all of your components, and given that the scheduler hasn't fixed things and CPUs haven't gotten faster, why not skip SPAs and settle for progressive enhancement of sections of a document?&quot;</em></p>
<p>[  <a href="https://www.patterns.dev/posts/islands-architecture/">&quot;islands&quot;</a>, <a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html">&quot;server components&quot;</a>, etc.  ]</p>
</li>
</ul>
<p>It's the <a href="https://simpsons.fandom.com/wiki/Steamed_Hams">Steamed Hams</a> of technology pitches.</p>
<p>Like Chalmers, teams and managers often acquiesce to the contradictions embedded in the stacked rationalisations. Together, the community invented dozens of reasons to look the other way, from the theoretically plausible to the fully imaginary.</p>
<p>But even as the complexity merchant's well-intentioned victims meekly recite the koans of trickle-down UX — <em>it can work this time, if only we try it hard enough!</em> — the evidence mounts that &quot;modern&quot; web development is, in the main, an expensive failure.</p>
<p>The baroque and insular terminology of the in-group is a clue. It's functional purpose (outside of signalling) is to obscure furious plate spinning. The tech isn't working, but admitting as much would shrink the market for lemons.</p>
<p>You'd be forgiven for thinking the verbiage was designed to obfuscate. Little comfort, then, that folks selling new approaches must now <a href="https://dev.to/tigt/making-the-worlds-fastest-website-and-other-mistakes-56na">wade through</a> waist-deep jargon excrement <a href="https://www.epicweb.dev/the-webs-next-transition">to argue for the <em>next</em> increment of complexity.</a></p>
<p>The most recent turn is as predictable as it is bilious. Today's most successful complexity merchants have never backed down, never apologised, and never come clean about what they knew about the level of expense involved in keeping SPA-oriented technologies in check. But they expect you'll follow them down the <em>next</em> dark alley anyway:</p>
<p></p><figure><a href="https://twitter.com/rauchg/status/1619492334961569792" alt="An admission against interest." target="_blank"><picture style="--lqip: 174627" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/lemony_snicker.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2023/02/the-market-for-lemons/lemony_snicker.png" alt="An admission against interest." style="aspect-ratio: 1080 / 449" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption>An admission against interest.</figcaption>      </figure><p></p>
<p>And why not? The industry has been down to clown for so long it's hard to get in the door if you aren't wearing a red nose.</p>
<p>The substitution of heroic developer narratives for user success happened imperceptibly. Admitting it was a mistake would embarrass the good and the great alike. Once the lemon sellers embed the data-light idea that improved &quot;Developer Experience&quot; (&quot;DX&quot;) leads to better user outcomes, improving &quot;DX&quot; became and end unto itself. Many who knew better felt forced to play along.</p>
<p>The long lead time for falsifying trickle-down UX was a feature, not a bug; they don't need you to succeed, only to keep buying.</p>
<p>As marketing goes, the &quot;DX&quot; <a href="https://infrequently.org/2018/09/the-developer-experience-bait-and-switch/">bait-and-switch</a> is brilliant, but the tech isn't delivering for anyone <em>but</em> developers.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/the-market-for-lemons/#fn-sunk-costs-4" id="fnref-sunk-costs-4">4</a></sup> The highest goal of the complexity merchants is to put brands on showcase microsites and to make acqui-hiring failing startups easier. Performance and success of the resulting products is merely a nice-to-have.</p>
<h2 id="denouement" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/the-market-for-lemons/#denouement">Denouement</a></h2>
<p>You'd think there would be data, that we would be awash in case studies and blog posts attributing product success to adoption of SPAs and heavy frameworks in an incontrovertable way.</p>
<p>And yet, after more than a decade of JS hot air, the framework-centric pitch is still phrased in speculative terms because there's no there there. The complexity merchants can't cop to the fact that <a href="https://infrequently.org/2022/05/performance-management-maturity/">management competence and <em>lower</em> complexity</a> — not baroque technology — are determinative of product and end-user success.</p>
<p>The simmering, widespread failure of SPA-premised approaches has belatedly forced the JS colporteurs to adapt their pitches. In each iteration, they must accept a smaller rhetorical lane to explain why this stack is still the future.</p>
<p>The excuses are running out.</p>
<p>At long last, the journey has culminated with the rollout of <a href="https://web.dev/vitals/">Core Web Vitals</a>. It finally provides an objective quality measurement that prospective customers can use to assess frontend architectures.</p>
<p>It's no coincidence the final turn away from the SPA justification has happened just as buyers can see a linkage between the stacks they've bought and the monetary outcomes they already value; namely SEO. The objective buyer, circa 2023, will understand heavy JS stacks as a regrettable legacy, one that teams who have hollowed out their HTML and CSS skill bases will pay for dearly in years to come.</p>
<p>No doubt, many folks who know their JS-first stacks are slow will do as Akerlof predicts, and obfuscate for as long as possible. The market for lemons is, indeed, mostly a <em>resale</em> market, and the excesses of our lost decade will not be flushed from the ecosystem quickly. Beware tools pitching <em>&quot;100 on Lighthouse&quot;</em> without checking the real-world <a href="https://treo.sh/sitespeed">Core Web Vitals results</a>.</p>
<h2 id="shrinkage" tabindex="-1"><a class="permalink" href="https://infrequently.org/2023/02/the-market-for-lemons/#shrinkage">Shrinkage</a></h2>
<p>A subtle aspect of Akerlof's theory is that markets in which lemons dominate eventually shrink. I've <a href="https://infrequently.org/series/performance-inequality/">warned for years</a> that the mobile web is under threat from within, and <a href="https://vimeo.com/364402896">the depressing data I've cited about users moving to apps</a> and away from terrible web experiences aligns with that theory.</p>
<p>When websites feel like categorically worse experiences to the folks who write the checks, why should anyone expect them to spend a lot on them? And when websites stop being where accurate information and useful services are, will anyone still believe there's a future in web development?</p>
<p>The lost decade we've suffered at the hands of lemon purveyors isn't just a local product travesty; it's also an ecosystem-level risk. Forget AI putting web developers out of jobs; JS-heavy web stacks have been shrinking the future market for your services <em>for years</em>.</p>
<p>As <a href="https://www.theguardian.com/education/2002/dec/20/highereducation.uk1#:~:text=Adam%20Smith's%20invisible%20hand%20%2D%20the,because%20it%20is%20not%20there.">Stigliz memorably quipped</a>:</p>
<blockquote>
<p>Adam Smith's invisible hand — the idea that free markets lead to efficiency as if guided by unseen forces — is invisible, at least in part, because it is not there.</p>
</blockquote>
<p>But dreams die hard.</p>
<p>I'm already hearing laments from folks who have been responsible citizens of framework-landia lo these many years. Oppressed as they were by the lemon vendors, they worry about babies being throw out with the bathwater, and I empathise. But for the sake of users, and for the new opportunities for the web that will open up when experiences finally improve, I say <em>&quot;chuck those tubs&quot;</em>.</p>
<p>Chuck 'em hard, and post the photos of the unrepentant bastards that tried to palm off this nonsense behind the cash register.</p>
<p><picture style="--lqip: -109908" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2023/02/the-market-for-lemons/anti-js-js-club-lighter-small.jpg" alt="Anti JavaScript JavaScript Club" style="aspect-ratio: 1000 / 710" class="preview" decoding="async" loading="lazy" />      </picture></p>
<p>We lost a decade to smooth talkers and hollow marketeering; folks who failed the most basic test of intellectual honesty: signposting known unknowns. Instead of engaging honestly with the emerging evidence, they sold lemons and shrunk the market for better solutions. Furiously playing catch-up to stay one step ahead of market rejection, frontend's anguished, belated return to quality has been hindered at every step by those who would stand to lose if their <a href="https://joshcollinsworth.com/blog/self-fulfilling-prophecy-of-react">false premises and hollow promises</a> were to be fully re-evaluated.</p>
<p>Toxic mimicry and recalcitrant ignorance must not be rewarded.</p>
<p>Vendor's random walk through frontend choices may eventually lead them to be right twice a day, but that's not a reason to keep following their lead. No, we need to move our attention back to the folks that have been right all along. The people who never gave up on semantic markup, CSS, and progressive enhancement for <em>most</em> sites. The people who, when slinging JS, have treated it as special occasion food. The tools and communities whose culture puts the user ahead of the developer and hold evidence of doing better for users in the highest regard.<sup class="footnote-ref"><a href="https://infrequently.org/2023/02/the-market-for-lemons/#fn-alex-approved-1" id="fnref-alex-approved-1:1">1:1</a></sup></p>
<p>It's not healing, and it won't be enough to nurse the web back to health, but tossing the Vercels and the Facebooks out of polite conversation is, at least, a start.</p>
<div style="font-size: 1rem;">
<p><em>Deepest thanks to <a href="https://brucelawson.co.uk/">Bruce Lawson</a>, <a href="https://heydonworks.com/">Heydon Pickering</a>, <a href="https://fberriman.com/">Frances Berriman</a>, and <a href="https://ti.gt/">Taylor Hunt</a> for their thoughtful feedback on drafts of this post.</em></p>
</div>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-alex-approved-1" class="footnote-item"><p>You wouldn't know it from today's frontend discourse, but the modern era has never been without high-quality alternatives to React, Angular, Ember, and other legacy desktop-era frameworks.</p>
<p>In a bazaar dominated by lemon vendors, many tools and communities have been respectful of today's mostly-mobile users at the expense of their own marketability. These are today's honest brokers and they deserve your attention far more than whatever solution to a problem created by React that the React community is on about this week.</p>
<p>This has included JS frameworks with an emphasis on speed and low overhead vs. cadillac comfort of first-class IE8 support:</p>
<ul>
<li><a href="https://stenciljs.com/">Stencil</a></li>
<li><a href="https://lit.dev/">Lit</a> and <a href="https://polymer-library.polymer-project.org/3.0/docs/devguide/feature-overview">Polymer</a></li>
<li><a href="https://svelte.dev/">Svelte</a></li>
<li><a href="https://preactjs.com/">Preact</a></li>
<li><a href="https://www.solidjs.com/">Solid</a></li>
<li><a href="https://markojs.com/">Marko</a></li>
<li><a href="https://www.infernojs.org/">Inferno</a></li>
<li><a href="https://github.com/WebReflection/hyperHTML">Hyper</a></li>
<li><a href="https://www.fast.design/">FAST</a></li>
<li><a href="https://vuejs.org/">Vue</a></li>
<li><a href="https://qwik.builder.io/">Qwik</a></li>
</ul>
<p>It's possible to make slow sites with any of these tools, but the <em>ethos</em> of these communities is that what's good for users is essential while developer luxuries are nice-to-have — even as they compete furiously for developer attention. This uncompromising focus on <em>real</em> quality is what has been muffled under the blanket complexity merchants have thrown over today's frontend discourse.</p>
<p>Similarly, the SPA orthodoxy that precipitated the market for frontend lemons has been challenged both by the continued success of &quot;legacy&quot; tools like WordPress, as well as a new crop of HTML-first systems that provide JS-friendly authoring but output that's largely HTML and CSS:</p>
<ul>
<li><a href="https://www.11ty.dev/">Eleventy</a></li>
<li><a href="https://astro.build/">Astro</a></li>
<li><a href="https://enhance.dev/docs/">Enhance</a></li>
<li><a href="https://kit.svelte.dev/">SvelteKit</a></li>
<li><a href="https://fresh.deno.dev/">Fresh</a></li>
<li>...and many others.</li>
</ul>
<p>The essential thing about tools that succeed more often than not is <em>starting with simple output</em>. The difficulty in managing what you've explicitly added based on incremental need, vs. what you've been bequeathed by an inscrutable Rube Goldberg-esque metaframework, is an order of magnitude in cost and usability. Teams that adopt tools with simpler default output start with simpler problems that tend to have better-understood solutions. <a href="https://infrequently.org/2023/02/the-market-for-lemons/#fnref-alex-approved-1" class="footnote-backref">⇐</a> <a href="https://infrequently.org/2023/02/the-market-for-lemons/#fnref-alex-approved-1:1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-everything-in-moderation-2" class="footnote-item"><p>Organisations that manage their systems (not the other way around) can succeed with <em>any</em> set of tools. They might pick some elegant ones and some awkward ones, but the <em>sine qua non</em> of their success isn't what they pick up, it's how they hold it.</p>
<p>Recall that Facebook became a multi-billion dollar, globe-striding colossus using PHP and C++.</p>
<p>The differences between FB and your applications are likely legion. This is why it's fundamentally lazy and wrong for TLs and PMs to accept any sort of argument along the lines of <em>&quot;X scales, FB uses it&quot;</em>.</p>
<p>Pigs <em>can</em> fly; it's only matter of how much force you apply — but if you aren't willing to fund creation of a large enough trebuchet, it's unlikley that porcine UI will take wing in your organisation. <a href="https://infrequently.org/2023/02/the-market-for-lemons/#fnref-everything-in-moderation-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-amortised-interaction-costs-3" class="footnote-item"><p>I <a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/#a-battle-between-two-teams">hinted last year</a> at and under-developed model for how we can evolve our discussion around web performance to take account of the larger factors that distinguish different <em>kinds</em> of sites.</p>
<p>While it doesn't account for many corner-cases, and is insufficient on its own to describe multi-modal experiences like WordPress (a content-producing editor for a small fraction of important users vs. shallow content-consumption reader experience for most), I wind up thinking about the total latency incurred in a user's session <em>divided by</em> the number of interactions. This raises a follow-on question: what's an interaction? Elsewhere, I've defined it as <a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/#a-battle-between-two-teams:~:text=These%20steps%20inform%20a%20general%20description%20of%20the%20interaction%20loop%3A"><em>&quot;turns through the interaction loop&quot;</em></a>, but can be more easily described as <em>&quot;taps or clicks that involve your code doing work&quot;</em>. This helpfully excludes scrolling, but includes navigations.</p>
<p><em>ANYWAY</em>, all of this nets out a session-depth weighted intuition about when and where heavyweight frameworks make sense to load up-front:</p>
<figure class="full_wide">
  <picture>
    <img src="https://infrequently.org/2023/02/the-market-for-lemons/depth-and-frequency-small.png" alt="Sites with shorter average sessions can afford less JS up-front." decoding="async" loading="lazy" style="aspect-ratio: 3528 / 1478;" />
  </picture>
  <figcaption>
    Sites with shorter average sessions can afford less JS up-front.
  </figcaption>
</figure>
<p>Social media sites that gate content behind a login (and can use the login process to pre-load bundles), and which have tons of data about session depth — not to mention ML-based per-user bundling, staffed performance teams, ship gates to prevent regressions, and the funding to build and maintain at least 3 different versions of the site — can afford to make fundamentally different choices about how much to load up-front and for which users.</p>
<p>The rest of us, trying to serve all users from a single codebase, need to prefer conservative choices that <a href="https://infrequently.org/2022/05/performance-management-maturity/">align with our <em>management</em> capacity to keep complexity in check</a>. <a href="https://infrequently.org/2023/02/the-market-for-lemons/#fnref-amortised-interaction-costs-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-sunk-costs-4" class="footnote-item"><p>The &quot;DX&quot; fixation hasn't even worked for developers, if we're being honest. Teams I work with suffer eye-watering build times, shockingly poor code velocity, mysterious performance cliffs, and some poor sod stuck in a broom closet that nobody bothers, lest the webs stop packing.</p>
<p>And yet, these same teams are happy to tell me they couldn't live without the new ball-and-chain.</p>
<p>One group, after weeks of debugging a particularly gnarly set of issues brought on by their preposterously inefficient &quot;CSS-in-JS&quot; solution, combined with React's penchant for terrible data flow management, actually said to me that they were so glad they'd moved everything to hooks because it was <em>&quot;so much cleaner&quot;</em> and that &quot;CSS-in-JS&quot; was great because <em>&quot;now they could reason about it&quot;</em>; nevermind the weeks they'd <em>just</em> lost to the combination of dirtier callstacks and harder to reason about runtime implications of heisenbug styling.</p>
<p>Nothing about the lived experience of web development has meaningfully improved, except perhaps for TypeScript adding structure to large codebases. And yet, here we are. Celebrating failure as success while parroting narratives about developer productivity that have no data to back them up.</p>
<p><a href="https://en.wikipedia.org/wiki/Sunk_cost">Sunk-cost fallacy</a> rules all we survey. <a href="https://infrequently.org/2023/02/the-market-for-lemons/#fnref-sunk-costs-4" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>The Performance Inequality Gap, 2023</title>
    <link href="https://infrequently.org/2022/12/performance-baseline-2023/"/>
    <updated>2022-12-19T00:00:00Z</updated>
    <id>https://infrequently.org/2022/12/performance-baseline-2023/</id>
    <content type="html"><![CDATA[
      <aside class="tldr">
<p><strong><abbr title="&quot;Too long; didn't read&quot;; a summary of a post">TL;DR</abbr>:</strong> To serve users at the 75<sup>th</sup> percentile (<abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr>) of devices and networks, we can now afford ~150KiB of <abbr title="HyperText Markup Language">HTML</abbr>/<abbr title="Cascading Style Sheets">CSS</abbr>/fonts and ~300-350KiB of JavaScript (gzipped). This is a slight improvement on <a href="https://infrequently.org/2021/03/the-performance-inequality-gap/">last year's budgets</a>, thanks to device and network improvements. Meanwhile, sites <a href="https://httparchive.org/reports/state-of-javascript">continue to send more script than is reasonable</a> for <a href="https://www.idc.com/promo/smartphone-market-share/os">80+% of the world's users</a>, widening the gap between the haves and the have-nots. This is an ethical crisis for frontend.</p>
</aside>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#2023-content-targets">2023 Content Targets</a></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#desktop">Desktop</a><ul><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#devices">Devices</a></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#networks">Networks</a></li></ul></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#mobile">Mobile</a><ul><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#devices-1">Devices</a></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#networks-1">Networks</a></li></ul></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#developing-your-own-targets">Developing Your Own Targets</a></li><li><a href="https://infrequently.org/2022/12/performance-baseline-2023/#the-performance-inequality-gap-is-growing">The Performance Inequality Gap is Growing</a></li></ul></nav>
<p>Last month, I had the honour of joining what seemed like the entire web performance community at <a href="https://perfnow.nl/">performance.now() in Amsterdam</a>.</p>
<p>The <a href="https://www.youtube.com/channel/UCuZeHD5SGecQomz2pVDHGzg">talks are up on YouTube</a> behind a paywall, but <a href="https://docs.google.com/presentation/d/16MSBIgPiNwROlVOCrndVjb0d9K4u5gLA/edit?usp=sharing&amp;ouid=113757927151929258451&amp;rtpof=true&amp;sd=true">my slides are mirrored here</a><sup class="footnote-ref"><a href="https://infrequently.org/2022/12/performance-baseline-2023/#fn-speaker-notes-1" id="fnref-speaker-notes-1">1</a></sup>:</p>
<p><lite-youtube videoid="BmiVevOUvho" videotitle="performance.now(): The Global Baseline" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=BmiVevOUvho">performance.now(): The Global Baseline</a>              </lite-youtube></p>
<p>The talk, like this post, is an update on network and <abbr title="Central Processing Unit">CPU</abbr> realities this series has <a href="https://infrequently.org/series/performance-inequality">documented since 2017</a>. More importantly, it is also a look at what the latest data means for our collective performance budgets.</p>
<h2 id="2023-content-targets" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#2023-content-targets">2023 Content Targets</a></h2>
<p>In the interest of brevity, here's what we should be aiming to send over the wire per page in 2023 to reach interactivity in less than 5 seconds on first load:<sup class="footnote-ref"><a href="https://infrequently.org/2022/12/performance-baseline-2023/#fn-pages-vs-interactions-2" id="fnref-pages-vs-interactions-2">2</a></sup><sup class="footnote-ref"><a href="https://infrequently.org/2022/12/performance-baseline-2023/#fn-five-seconds-3" id="fnref-five-seconds-3">3</a></sup></p>
<ul>
<li>~150KiB of <abbr title="HyperText Markup Language">HTML</abbr>, <abbr title="Cascading Style Sheets">CSS</abbr>, images, and render-blocking font resources</li>
<li>No more than ~300-350KiB of JavaScript</li>
</ul>
<p>This implies a heavy <abbr title="JavaScript">JS</abbr> payload, which most new sites suffer from for reasons both bad and beyond the scope of this post. With a more classic content profile — mostly <abbr title="HyperText Markup Language">HTML</abbr> and <abbr title="Cascading Style Sheets">CSS</abbr> — <a href="https://infrequently.org/2022/12/performance-baseline-2023/chart/index.html">we can afford much more in terms of total data</a>, because JavaScript is still the costliest way to do things and CPUs at the global <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> <em>are not fast</em>.</p>
<p>These estimates also assume some serving discipline, including:</p>
<ul>
<li>No more than two HTTP connections, implying <a href="https://hpbn.co/http2/">HTTP/2</a></li>
<li><a href="https://hpbn.co/http1x/#:~:text=the%20last%20update.-,Gzip%20assets,-All%20text%2Dbased">Compressing</a> text resources</li>
<li>Reasonable <a href="https://developer.chrome.com/en/docs/lighthouse/performance/render-blocking-resources/">content structure</a></li>
</ul>
<p>These targets are anchored to global estimates for networks and devices <a href="https://support.speedcurve.com/docs/performance-for-product-managers#75th-percentile">at the 75<sup>th</sup> percentile</a><sup class="footnote-ref"><a href="https://infrequently.org/2022/12/performance-baseline-2023/#fn-P75-is-for-suckers-4" id="fnref-P75-is-for-suckers-4">4</a></sup>.</p>
<p>More on how those estimates are constructed in a moment, but suffice to say, it's messy. Where the data is weak, we should always prefer conservative estimates.</p>
<p>Based on trends and historical precedent, there's little reason for optimism that things are better than they seem. Indeed, misplaced optimism about disk, network, and <abbr title="Central Processing Unit">CPU</abbr> resources is the background music to frontend's lost decade.</p>
<br style="display: none;" />
<figure class="full_wide">
<img src="https://infrequently.org/2022/12/performance-baseline-2023/INP-performance-by-device.svg" alt="Interaction-to-Next Paint measures page responsivness, and shows a large gap between desktop and mobile today" style="aspect-ratio: 619 / 384; width: 100%; display: block;" decoding="async" />
<figcaption>
  Per the <a href="https://almanac.httparchive.org/en/2022/">2022 Web Almanac</a>, which pulls data from real-world devices via <a href="https://developer.chrome.com/docs/crux/">the CrUX dataset</a>, today's web offers poor performance for the majority of users who are on mobile devices.
</figcaption>
</figure>
<p>It is not an exaggeration to say that modern frontend is so <a href="https://infrequently.org/2022/03/cache-and-prizes/">enamoured of post-scarcity fairy tales</a> that it is mortgaging the web's future for another night drinking at the JavaScript party.</p>
<p>We're burning our inheritance and polluting the ecosystem on shockingly thin, perniciously marketed claims of &quot;speed&quot; and &quot;agility&quot; and &quot;better <abbr title="User Experience">UX</abbr>&quot; that have not panned out <em>at all</em>. Instead, each additional layer of JavaScript cruft has dragged us further from living within the limits of what we can truly afford.</p>
<p></p><figure class="full_wide"><a href="https://httparchive.org/reports/state-of-javascript" alt="No amount of framework vendor happy talk can hide the reality that we are sending an escalating and unaffordable amount of JavaScript." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/timeseries-of-javascript.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/12/performance-baseline-2023/timeseries-of-javascript.png" alt="No amount of framework vendor happy talk can hide the reality that we are sending an escalating and unaffordable amount of JavaScript." style="aspect-ratio: 1200 / 800" class="full_wide preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>No amount of framework vendor happy talk can hide the reality that we are sending an escalating and unaffordable amount of JavaScript.</figcaption>      </figure><p></p>
<p>This isn't working for users or for businesses that hire developers hopped up Facebook's latest JavaScript hopium. A correction is due.</p>
<h2 id="desktop" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#desktop">Desktop</a></h2>
<p>In years past, I haven't paid as much attention to the situation on desktops. But researching this year's update has turned up sobering facts that should colour our collective understanding.</p>
<h3 id="devices" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#devices">Devices</a></h3>
<p>From Edge's telemetry, we see that nearly half of devices fall into our &quot;low-end&quot; designation, which means that they have:</p>
<ul>
<li><abbr title="Hard Drives">HDDs</abbr> (not <abbr title="Solid-State Drives">SSDs</abbr>)</li>
<li>2-4 <abbr title="Central Processing Unit">CPU</abbr> cores</li>
<li>4GB <abbr title="Random Access Memory">RAM</abbr> or less</li>
</ul>
<p>Add to this the fact that desktop devices have a lifespan between five and eight years, on average. This means the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device was sold in <em>2016</em>.</p>
<p>As this series has emphasised in years past, Average Selling Price (<abbr title="Average Selling Price">ASP</abbr>) is performance destiny. To understand our <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device, we must imagine what the <abbr title="Average Selling Price">ASP</abbr> device was at the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> age.<sup class="footnote-ref"><a href="https://infrequently.org/2022/12/performance-baseline-2023/#fn-p75-other-attacks-5" id="fnref-p75-other-attacks-5">5</a></sup> That is, what was the average device in 2016? It sure wasn't a $2,000 M1 MacBook Pro, that's for sure.</p>
<p>No, it was a <a href="https://www.statista.com/statistics/722992/worldwide-personal-computers-average-selling-price/">$600-$700 device</a>. Think (best-case) <a href="https://ark.intel.com/content/www/us/en/ark/products/90729/intel-core-i36100-processor-3m-cache-3-70-ghz.html">2-core, 4-thread</a> married to slow, spinning rust.</p>
<h3 id="networks" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#networks">Networks</a></h3>
<p>Desktop-attached networks are hugely variable worldwide, including in the U.S., where <a href="https://themarkup.org/still-loading/2022/10/19/dollars-to-megabits-you-may-be-paying-400-times-as-much-as-your-neighbor-for-internet-service#2022-broadband_kansas_city_redlining">the shocking effects of digital red-lining continue this day</a>. And that's on top of <a href="https://www.newamerica.org/oti/reports/cost-connectivity-2020/global-findings/">globally uncompetitive service</a>, thanks to shockingly lax regulation and legalised corruption.</p>
<p>As a result, we are sticking to our conservative estimates for bandwidth in line with <a href="https://www.webpagetest.org/">WebPageTest's</a> throttled Cable profile of 5Mbps bandwidth and ~25ms <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr>.</p>
<p>Speeds will be <a href="https://pcrd.purdue.edu/the-real-digital-divide-advertised-vs-actual-internet-speeds/">much slower than advertised in many areas</a>, particularly for rural users.</p>
<h2 id="mobile" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#mobile">Mobile</a></h2>
<p>We've been tracking the mobile device landscape more carefully over the years and, as with desktop, <abbr title="Average Selling Prices">ASPs</abbr> today are tomorrow's performance destiny. Thankfully, device turnover is faster, with the average handset surviving only three to four years.</p>
<h3 id="devices-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#devices-1">Devices</a></h3>
<p>Without beating around the bush, our <abbr title="Average Selling Price">ASP</abbr> 2019 device was an Android that cost between $300-$350, new and unlocked. It featured poor single and multi-core performance, and the high-end experience has continued to pull away from it since:</p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2022/12/performance-baseline-2023/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Updated Geekbench five single-core scores for each mobile price point. TL;DR: your iPhone isn't real life." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/single_core_scores.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/12/performance-baseline-2023/single_core_scores.png" alt="<em>Tap for a larger version.</em><br>Updated Geekbench five single-core scores for each mobile price point. TL;DR: your iPhone isn't real life." style="border: 8px solid white;; aspect-ratio: 1343 / 623" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Updated Geekbench five single-core scores for each mobile price point. <abbr title="&quot;Too long; didn't read&quot;; a summary of a post">TL;DR</abbr>: your iPhone isn't real life.</figcaption>      </figure><p></p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2022/12/performance-baseline-2023/multi_core_scores.png" alt="<em>Tap for a larger version.</em><br>Android ecosystem <abbr title='system-on-chip'>SoC</abbr>s fare slightly better on multi-core performance, but the Performance Inequality Gap is growing there, too." target="_blank"><picture style="--lqip: 524186" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/multi_core_scores.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/12/performance-baseline-2023/multi_core_scores.png" alt="<em>Tap for a larger version.</em><br>Android ecosystem <abbr title='system-on-chip'>SoC</abbr>s fare slightly better on multi-core performance, but the Performance Inequality Gap is growing there, too." style="border: 8px solid white;; aspect-ratio: 1343 / 623" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap for a larger version.</em><br />Android ecosystem <abbr title="system-on-chip"><abbr title="System-on-a-Chip">SoC</abbr></abbr>s fare slightly better on multi-core performance, but the Performance Inequality Gap is growing there, too.</figcaption>      </figure><p></p>
<p>As you can see, the gap is widening, in part because the high end has risen dramatically in price.</p>
<p>The best analogue you can buy for a representative <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device today are ~$200 Androids from the last year or two, such as the <a href="https://www.gsmarena.com/samsung_galaxy_a50-9554.php">Samsung Galaxy A50</a> and the <a href="https://www.gsmarena.com/nokia_g11-11358.php">Nokia G11</a>.</p>
<p>These devices feature:</p>
<ul>
<li>Eight slow, big.LITTLE ARM cores (A75+A55, or A73+A53) built on last-generation processes with very little cache</li>
<li>4GiB of <abbr title="Random Access Memory">RAM</abbr></li>
<li>4G radios</li>
</ul>
<p>These are depressingly similar specs to devices <a href="https://calibreapp.com/blog/beyond-the-bubble">I recommended for testing <em>in 2017</em></a>. Qualcomm has some 'splainin to do.</p>
<p>5G is still in its early diffusion phase, and the inclusion of a 5G radio is hugely randomising for device specs at today's mid-market price-point. It'll take a couple of years for that to settle.</p>
<h3 id="networks-1" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#networks-1">Networks</a></h3>
<p>Trustworthy mobile network data is challenging to acquire. Geographic differences create huge effects that we can see as variability in <a href="https://www.speedtest.net/global-index">various global indexes</a>. This variance forces us towards the bottom of the range when estimating our baseline, as mobile networks are highly contextual.</p>
<p>Triangulating from both <a href="https://www.speedtest.net/global-index">speedtest.net</a> and <a href="https://www.opensignal.com/market-insights">OpenSignal</a> data (which has declined markedly in usefuleness), we're also going to maintain our global network baseline from last year:</p>
<ul>
<li>9Mbps bandwidth</li>
<li>170ms <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr></li>
</ul>
<p>This is a higher bandwidth estimate than might be reasonable, but also a higher <abbr title="Round-Trip Time, the number of milliseconds to send a packet and receive a reply">RTT</abbr> to cover the effects of high network behaviour variance. I'm cautiously optimistic that we'll be able to bump one or both of these numbers in a positive direction next year. But they stay put for now.</p>
<h2 id="developing-your-own-targets" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#developing-your-own-targets">Developing Your Own Targets</a></h2>
<p>You don't have to take my word for it. If your product behavior or your own team's data or market research suggests different tradeoffs, then it's only right to set your own per-product baseline.</p>
<p>For example, let's say you send more <abbr title="HyperText Markup Language">HTML</abbr> and less JavaScript, or your serving game is on lock and all critical assets load over a single H/2 link. How should your estimates change?</p>
<p>Per usual, I've also updated the rinky-dink live model that you can use to select different combinations of device, network, and content type.</p>
<p></p><figure class="full_wide"><a href="https://infrequently.org/2022/12/performance-baseline-2023/chart/index.html" alt="<em>Tap to try the interactive version.</em>" target="_blank"><picture style="--lqip: 170714" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/12/performance-baseline-2023/chart.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/12/performance-baseline-2023/chart.png" alt="<em>Tap to try the interactive version.</em>" style="aspect-ratio: 1224 / 642" class="full_wide preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><em>Tap to try the interactive version.</em></figcaption>      </figure><p></p>
<h2 id="the-performance-inequality-gap-is-growing" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/12/performance-baseline-2023/#the-performance-inequality-gap-is-growing">The Performance Inequality Gap is Growing</a></h2>
<p>Essential public services are now delivered <em>primarily</em> through digital channels in many countries. This means what the frontend community celebrates and promotes has a stochastic effect on the provision of those services — which leads to an uncomfortable conversation because, taken as a whole, it isn't working.</p>
<p>Pervasively poor results are part of why responsible public sector organisations <a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement">are forced to develop <abbr title="HyperText Markup Language">HTML</abbr>-first, progressive enhancement guidance in stark opposition to the &quot;frontend consensus&quot;</a>.</p>
<p>This is an indictment: modern frontend's fascination with towering piles of JavasScript complexity is not delivering better experiences for most users.</p>
<p>For a genuinely raw example, consider California, the state where I live. In early November, it was brought to my attention that <a href="https://ca.gov/">CA.gov</a> <em>&quot;felt slow</em>&quot;, so I gave it a look. It was bad on my local development box, so I put it under the WebPageTest microscope. The results were, to be blunt, <a href="https://www.webpagetest.org/video/compare.php?tests=221108_AiDcC6_GEK-r%3A1-c%3A0&amp;thumbSize=200&amp;ival=100&amp;end=full">a travesty</a>.</p>
<p>How did this happen? Well, per the new usual, overly optimistic assumptions about the state of the world accreted until folks at the margins were excluded.</p>
<p>In the case of CA.gov, it was an <em>official</em> Twitter embed that, for some cursed reason, had been built using React, Next.js, and the full parade of modern horrors. Removing the embed, along with code optimistically built in a pre-<abbr title="JavaScript">JS</abbr>-bloat era that blocked rendering until all resources were loaded, resulted <a href="https://www.webpagetest.org/video/compare.php?tests=221108_AiDcC6_GEK,221205_AiDc1Y_AW4&amp;thumbSize=200&amp;ival=100&amp;end=full#">in a dramatic improvement</a>:</p>
<br style="display: none;" />
<figure class="full_wide">
<video src="https://infrequently.org/2022/12/performance-baseline-2023/ca.gov-before-and-after.mp4" poster="https://infrequently.org/2022/12/performance-baseline-2023/ca.gov-before-and-after.poster.jpg" style="aspect-ratio: 904 / 680; width: 100%; display: block;" controls="" playsinline="" loading="lazy">
</video>
<figcaption>
  Thanks to some quick work by the CA.gov team, the experience of the site radically improved between early November and mid-December, giving Californians easier access to critical information.
</figcaption>
</figure>
<p>This is not an isolated incident. These sorts of disasters have been arriving on my desk with shocking frequency for <em>years</em>.</p>
<p>Nor is this improvement a success story, but rather a cautionary tale about the assumptions and preferences of those who live inside the privilege bubble. When they are allowed to set the agenda, folks who are less well-off get hurt.</p>
<p>It wasn't the embed engineer getting paid hundreds of thousands of dollars a year to sling JavaScript who was marginalised by this gross misapplication of overly complex technology. No, it was Californians who could least afford fast devices and networks who were excluded. Likewise, it hasn't been those same well-to-do folks who have remediate the resulting disasters. They don't even clean up their own messes.</p>
<p>Frontend's failure to deliver in today's mostly-mobile, mostly-Android world is shocking, if only for the durability of the myths that sustain the indefensible. We can't keep doing this.</p>
<p>As they say, any trend that can't continue won't.</p>
<!-- General -->
<!-- Media Types -->
<!-- Units -->
<!-- Performance -->

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-speaker-notes-1" class="footnote-item"><p>Apologies for the lack of speaker notes in this deck. If there's sufficient demand, I can go back through and add key points. Let me know if that would help you or your team <a href="https://toot.cafe/@slightlyoff">over on Mastodon</a>. <a href="https://infrequently.org/2022/12/performance-baseline-2023/#fnref-speaker-notes-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-pages-vs-interactions-2" class="footnote-item"><p>Since at least 2017, I've grown increasingly frustrated at the way we collectively think about the tradeoffs in frontend metrics. Per this year's post on <a href="https://infrequently.org/2022/03/a-unified-theory-of-web-performance/">a unified theory of web performance</a>, it's entirely possible to model nearly every interaction in terms of a full page load (and <em>vice versa</em>).</p>
<p>What does this tell us? Well, briefly, it tells us that the interaction loop for each interaction is only part of the story. Recall the loop's phases:</p>
<ol>
<li>Interactive (ready to handle input)</li>
<li>Receiving input</li>
<li>Acknowledging input, beginning work</li>
<li>Updating status</li>
<li>Work ends, output displayed</li>
<li>GOTO 1</li>
</ol>
<p>Now imagine we collect all the interactions a user performs in a session (ignoring scrolling, which is nearly always handled by the browser unless you screw up), and then we divide the total set of costs incurred by the number of turns through the loop.</p>
<p>Since our goal is to ensure users complete each turn through the loop with <em>low latency</em> and <em>low variance</em>, we can see the colourable claim for <abbr title="Single Page App">SPA</abbr> architectures take shape: by trading off some initial latency, we can reduce total latency and variance. But this also gives rise to the critique: OK, but does it work?</p>
<p>The answer, shockingly, seems to be &quot;no&quot; — at least not as practised by most sites adopting this technology over the past decade.</p>
<p>The web performance community should eventually come to a more session-depth-weighted understanding of metrics and goals. Still, until we pull into that station, per-page-load metrics are useful. They model the better style of app construction and represent the most actionable advice for developers. <a href="https://infrequently.org/2022/12/performance-baseline-2023/#fnref-pages-vs-interactions-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-five-seconds-3" class="footnote-item"><p>The target that this series has used consistently has been reaching a consistently interactive (&quot;<abbr title="Time-to-Interactive; the moment when a page becomes consistently usable with low input delay">TTI</abbr>&quot;) state in less than 5 seconds on the chosen device and network baseline.</p>
<p>This isn't an ideal target.</p>
<p>First, even with today's the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> network and device, we can aim higher (lower?) and get compelling experiences loaded and main-thread clean in much less than 5 seconds.</p>
<p>Second, this target was set in covnersation back in 2016 in preparation for a Google I/O talk, based on what was then possible. At the time, this was still not ambitious enough, but the impact of an additional connection shrunk the set of origins that could accomplish the feat significantly.</p>
<p>Lastly, <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> is not where mature teams and developers spend their effort. Instead, they're looking up the percentiles and focusing on P90+, and so for mature teams looking to really make their experiences sing, I'd happily recommend that you target 5 second <abbr title="Time-to-Interactive; the moment when a page becomes consistently usable with low input delay">TTI</abbr> at P90 instead. It's possible, and on a good stack with a good team and strong management, a goal you can be proud to hit. <a href="https://infrequently.org/2022/12/performance-baseline-2023/#fnref-five-seconds-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-P75-is-for-suckers-4" class="footnote-item"><p>Looking at the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> networks and devices may strike <a href="https://infrequently.org/2022/05/performance-management-maturity/">mature teams and managers</a> as a sandbagged goal and, honestly, I struggle with this.</p>
<p>On the one hand, yes, we should be looking into the higher percentiles. But weaker goals aren't within reach for most teams today. If we moved the ecosystem to a place where it could reliably hit these limits and hold them in place for a few years, the web would stand a <a href="https://vimeo.com/364402896">significantly higher chance of remaining relevant</a>.</p>
<p>On the other hand, these difficulties stack. Additive error means that targeting the combination <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> network <em>and</em> <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> device likely puts you north of P90 in the experiential distribution, but it's hard to know. <a href="https://infrequently.org/2022/12/performance-baseline-2023/#fnref-P75-is-for-suckers-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-p75-other-attacks-5" class="footnote-item"><p>Data-minded folks will be keenly aware that simply extrapolating from average selling price over time can lead to some very bad conclusions. For example, what if device volumes fluctuate significantly? What if, in more recent years, <abbr title="Average Selling Prices">ASPs</abbr> fluctuate significantly? Or what if divergence in underlying data makes comparison across years otherwise unreliable.</p>
<p>These are <a href="https://en.wikipedia.org/wiki/Anscombe%27s_quartet">classic questions</a> in data analysis, and thankfully the PC market has been relatively stable in volumes, prices, and segmentation, even through the pandemic.</p>
<p>As covered later in this post, mobile is showing signs of heavy divergence in properties by segment, with the high-end pulling away in both capability and price. This is happening even as global <abbr title="Average Selling Prices">ASPs</abbr> remain relatively fixed, due to the increases in low-end volume over the past decade. Both desktop and mobile are staying within a narrow Average Selling Price band, but in both markets (though for different reasons), the <abbr title="75th percentile; a quarter of all values in the distribution are slower">P75</abbr> is not where folks looking only at today's new devices might expect it to be.</p>
<p>In this way, we can think of the Performance Inequality Gap as being an expression of <a href="http://www.thefunctionalart.com/2016/08/download-datasaurus-never-trust-summary.html">Alberto Cairo's visual data lessons</a>: things may look <a href="https://www.autodesk.com/research/publications/same-stats-different-graphs">descriptively similar</a> at the level of movement of averages between desktop and mobile, but the underlying data tells a very different story. <a href="https://infrequently.org/2022/12/performance-baseline-2023/#fnref-p75-other-attacks-5" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
  <entry>
    <title>Apple Is Not Defending Browser Engine Choice</title>
    <link href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/"/>
    <updated>2022-06-23T00:00:00Z</updated>
    <id>https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/</id>
    <content type="html"><![CDATA[
      <p>Gentle reader, I made a terrible mistake. Yes, that's right: I read the comments on <a href="https://www.macrumors.com/2022/06/10/uk-to-target-apple-gaming-and-browser-restrictions/">a MacRumors article</a>. At my age, one knows better. And yet.</p>
<p>As penance for this error, and <a href="https://twitter.com/slightlylate/status/1534223987261157376?s=20&amp;t=Fb70BlpfllEZ6WeQrI16rQ">for being short with Miguel</a>, I must deconstruct the ways Apple has undermined browser engine diversity. Contrary to claims of Apple partisans, iOS engine restrictions are not preventing a &quot;takeover&quot; by Chromium — at least that's not the primary effect. Apple uses its power over browsers to strip-mine and sabotage the web, hurting all engine projects and draining the web of future potential.</p>
<p>As we will see, both the present and future of browser engine choice are squarely within Cupertino's control.</p>
<nav class="table-of-contents"><h4>Contents</h4><ul><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#apple's-long-standing-policies-are-anti-diversity">Apple's Long-Standing Policies Are Anti-Diversity</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#%22webkit-couldn't-compete-if-it-had-to.%22">&quot;WebKit couldn't compete if it had to.&quot;</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#browsers-are-big-business">Browsers Are Big Business</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#webkit-is-no-charity">WebKit Is No Charity</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#choices%2C-choices">Choices, Choices</a><ul><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#recent-developments">Recent Developments</a></li></ul></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#how-apple-gutted-mozilla's-chances">How Apple Gutted Mozilla's Chances</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#back-of-the-napkin">Back Of The Napkin</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#the-best-kind-of-correct">The Best Kind Of Correct</a></li><li><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#what-now%3F">What Now?</a></li></ul></nav>
<h2 id="apple's-long-standing-policies-are-anti-diversity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#apple's-long-standing-policies-are-anti-diversity">Apple's Long-Standing Policies Are Anti-Diversity</a></h2>
<p>A refresher on Apple's iOS browser policies:</p>
<ul>
<li>From <a href="https://en.wikipedia.org/wiki/IPhone_OS_2">iOS 2.0 in '08</a> to <a href="https://en.wikipedia.org/wiki/IOS_14#:~:text=The%20default%20mail%20and%20web%20browser%20apps%20can%20now%20be%20changed">iOS 14 in late '20</a>, Apple would not allow any browser but Safari to be the default.</li>
<li>For 14 years and counting, Apple has prevented competing browsers from bringing their own engines, forcing vendors to build skins over Apple's WebKit binary, which has historically been slower, <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#apple's-security-argument">less secure</a>, and <a href="https://infrequently.org/2021/04/progress-delayed/">lacking in features</a>.</li>
<li>Apple will not even allow competing browsers to provide different <a href="https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Settings.yaml">runtime flags</a> to WebKit. Instead, Fruit Co. publishes <a href="https://developer.apple.com/documentation/webkit/wkwebviewconfiguration">a paltry set</a> of options that carry an unmistakable odour of first-party app requirements.</li>
<li>Apple continues to self-preference through exclusive <abbr>API</abbr> access for Safari; e.g., the ability to install <abbr title="Progressive Web App">PWA</abbr>s to the home screen, implement media codecs, and much else.</li>
</ul>
<p>Defenders of Apple's monopoly offer hard-to-test claims, but many boil down to the idea that Apple's product is inferior by necessity. This line is frankly insulting to the good people that work on WebKit. They're excellent engineers; some of the best, pound for pound, but there aren't enough of them. And that's a choice.</p>
<h2 id="%22webkit-couldn't-compete-if-it-had-to.%22" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#%22webkit-couldn't-compete-if-it-had-to.%22"><em>&quot;WebKit couldn't compete if it had to.&quot;</em></a></h2>
<p>Nobody frames it precisely this way; instead they'll say, <q>if WebKit weren't mandated, Chromium would take over,</q> or <q>Google would dominate the web if not for the WebKit restriction.</q> That potential future requires mechanisms of action — something to cause Safari users to switch. What are those mechanisms? And why are some commenters so sure the end is nigh for WebKit?</p>
<p>Recall the status quo: websites can <em>already</em> ask iOS users to download alternative browsers. Thanks to <a href="https://infrequently.org/2021/04/progress-delayed/">(belated) questioning by Congress</a>, they can even be set as the user's default, ensuring a higher probability to generate search traffic and derive associated revenue. None of that hinges on browser engine choice; it's just marketing. At the level of commerce, Apple's capitulation on default browser choice is a big deal, but it falls short of true differentiation.</p>
<p>So, websites can already put up banners asking users to get different browsers, If WebKit is doomed, its failure must lie in other stars; e.g., that Safari's WebKit is inferior to Gecko and Blink.</p>
<p>But the quality and completeness of WebKit is entirely within Apple's control.</p>
<p>Past swings away from <abbr title="operating system">OS</abbr> default browsers happened because alternatives offered <a href="https://www.computerworld.com/article/2567205/mozilla-launches-firefox-1-0-browser.html">new features</a>, <a href="https://www.infoq.com/news/2008/09/google-chrome-perspectives/">better performance</a>, <a href="https://web.dev/browser-sandbox/">improved security</a>, and good site compatibility. These are properties intrinsic to the engine, not just the badge on the bonnet. Marketing and distribution have a role, but in recent browser battles, better engines have powered market shifts.</p>
<p>To truly differentiate and win, competitors must be able to bring their own engines. The leads of <abbr>OS</abbr> incumbents are not insurmountable because browsers are commodities with relatively low switching costs. Better products tend to win, if allowed, and Apple knows it.</p>
<p></p><figure><a href="https://gs.statcounter.com/browser-market-share/desktop/worldwide/#yearly-2009-2022" alt="Destkop <abbr>OS</abbr>es have long created a vibrant market for browser choice, enabling competitors not tied to OS defaults to flourish over the years." target="_blank"><picture style="--lqip: 174819" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/StatCounter-browser-ww-yearly-2009-2022.png" alt="Destkop <abbr>OS</abbr>es have long created a vibrant market for browser choice, enabling competitors not tied to OS defaults to flourish over the years." style="aspect-ratio: 1280 / 720" class="preview" decoding="async" fetchpriority="high" />      </picture>          </a>        <figcaption>Destkop <abbr>OS</abbr>es have long created a vibrant market for browser choice, enabling competitors not tied to OS defaults to flourish over the years.</figcaption>      </figure><p></p>
<p>Apple's <a href="https://developer.apple.com/app-store/review/guidelines/#2.5.6">prohibition on iOS browser engine competition</a> has drained the potential of browser choice to deliver improvements. Without the ability to differentiate on features, security, performance, privacy, and compatibility, what's to sell? A slightly different <abbr title="user interface">UI</abbr>? That's meaningful, but identically feeble web features cap the potential of every iOS browser. Nobody can pull ahead, and no product can offer future-looking capabilities that might make the web a more attractive platform.</p>
<p>This is working as intended:</p>
<p></p><figure><a href="https://developer.apple.com/app-store/review/guidelines/#2.5.6" alt="<a href='https://developer.apple.com/app-store/review/guidelines/#2.5.6'>Apple's policies</a> explicitly prevent meaningful competition between browsers on iOS. In 2022, you can have any default you like, as long as it's as buggy as Safari." target="_blank"><picture style="--lqip: 174306" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/apple_2.5.6_highlight.png" alt="<a href='https://developer.apple.com/app-store/review/guidelines/#2.5.6'>Apple's policies</a> explicitly prevent meaningful competition between browsers on iOS. In 2022, you can have any default you like, as long as it's as buggy as Safari." style="aspect-ratio: 717 / 232" class="preview" decoding="async" loading="lazy" />      </picture>          </a>        <figcaption><a href="https://developer.apple.com/app-store/review/guidelines/#2.5.6">Apple's policies</a> explicitly prevent meaningful competition between browsers on iOS. In 2022, you can have any default you like, as long as it's as buggy as Safari.</figcaption>      </figure><p></p>
<p>On <abbr>OS</abbr>es with proper browser competition, sites can recommend browsers with engines that cost less to support or unlock crucial capabilities. Major sites asking users to switch can be incredibly effective in aggregate.  Standards support is sometimes offered as a solution, but it's best to think of it as a trailing indicator.<sup class="footnote-ref"><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fn-the-role-of-standards-in-compatibility-1" id="fnref-the-role-of-standards-in-compatibility-1">1</a></sup> Critical capabilities often arrive in just one engine to start with, and developers that need these features may have incentive to prompt users to switch.</p>
<p>Developers are reluctanct to do this, however; turning away users isn't a winning growth strategy, and prompting visitors to switch <a href="https://www.reddit.com/r/webdev/comments/38o43q/psa_if_your_site_uses_the_phrase_this_site_best/">is passé</a>.</p>
<p>Still, <em>in extremis</em>, <a href="https://infrequently.org/2021/04/progress-delayed/">missing features</a> and the <a href="https://www.theregister.com/2021/06/16/apple_safari_indexeddb_bug/">parade of showstopping bugs</a> render some services impossible to deliver. In these cases, suggesting an alternative beats losing users entirely.</p>
<p>But what if there's no better alternative? This is the situation that Apple has engineered on iOS. <em>Cui bono?</em> — who benefits?</p>
<p>All iOS browsers present as Safari to developers. There's no point in recommending a better browser because none is available. The combined mass of all iOS browsing pegged to the trailing edge means that folks <em>must</em> support WebKit or decamp for Apple's App Store, where it hands out capabilities like candy, but at a <a href="https://www.consumercompetitionclaims.com/collective-actions">shocking price</a>.</p>
<p>iOS's mandated inadequacy has convinced some that when engine choice is possible, users will stampede of away from Safari. This would, in turn, cause developers to skimp on testing for Apple's engine, making it inevitable that browsers based on WebKit and other minority engines could not compete. Or so the theory goes.</p>
<p>But is it predestined?</p>
<p>Perhaps some users will switch, but browser market changes take a great deal of time, and Apple enjoys numerous defences.</p>
<p>To the extent that Apple wants to win developers and avoid losing users, it has plenty of time.</p>
<p>It took over five years for Chrome to earn majority share on Windows with a superior product, and there's no reason to think iOS browser share will move faster. Then there's the countervailing evidence from macOS, where Safari manages to do just fine.</p>
<p>Regulatory mandates about engine choice will also take more than a year to come into force, giving Apple plenty of time to respond and improve the competitiveness of its engine. And that's the lower bound.</p>
<p>Apple's <a href="https://infrequently.org/2022/02/minimum-standards/">pattern of malaicious compliance</a> will likely postpone true choice even futher. As Apple fights tooth-and-nail to prevent alternative browser engines, it will try to create ambiguity about vendor's ability to ship their best products worldwide, potentially delaying high-cost investment in ports with uncertain market reach.</p>
<p>Cupertino may also try to create arduous processes that force vendors to individually challenge the lack of each API, one geography at a time. In the best case, time will still be lost to this sort of brinksmanship. This is time that Apple can use to improve WebKit and Safari to be properly competitive.</p>
<p>Why would developers recommend alternatives if Safari adds features, improves security, prioritises performance, and fumigates for showstopping bugs? Remember: developers don't <em>want</em> to prompt users to switch; they only do it under duress. The features and quality of Safari are squarely in Apple's control.</p>
<p>So, given that Apple has plenty of time to catch up, is it a rational business decision to invest enough to compete?</p>
<h2 id="browsers-are-big-business" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#browsers-are-big-business">Browsers Are Big Business</a></h2>
<p>Browsers are both big business and industrial-scale engineering projects. Hundreds of folks are needed to implement and maintain a competitive browser with specialisations in nearly every area of computing. World-class experts in graphics, networking, cryptography, databases, language design, <abbr title="virtual machine">VM</abbr> implementation, security, usability (particularly usable security), power management, compilers, fonts, high-performance layout, codecs, real-time media, audio and video pipelines, and per-<abbr>OS</abbr> specialisation are required. And then you need infrastructure; lots of it.</p>
<p>How much does all of this cost? A reasonable floor comes from Mozilla's annual reports. The <a href="https://assets.mozilla.net/annualreport/2020/mozilla-fdn-2020-short-form-0926.pdf">latest consolidated financials (PDF) are from 2020</a> and show that, without marketing expenses, Mozilla spends between $380 and $430 million <abbr>US</abbr> per year on software development. Salaries are the largest category of these costs (~$180-210 million), and Mozilla economises by hiring remote employees paid local market rates, without large bonuses or stock-based compensation.</p>
<p>From this data, we can assume a baseline cost to build and maintain a competitive, cross-platform browser at $450 million per year.</p>
<p>Browser vendors fund their industrial-scale software engineering projects through integrations. Search engines pay browser makers for default placement within their products. They, in turn, make a lot of money because browsers send them <a href="https://www.semrush.com/blog/how-to-use-search-intent-for-your-business/">transactional and commercial intent searches</a> as part of the query stream.</p>
<p>Advertisers bid huge sums to place ads against keywords in these categories. This market, in turn, funds all the <abbr title="research and development">R&amp;D</abbr> and operational costs of search engines, including &quot;traffic acquisition costs&quot; like browser search default deals.<sup class="footnote-ref"><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fn-ex-tac-2" id="fnref-ex-tac-2">2</a></sup></p>
<p>How much money are we talking about? Mozilla's $450 million in annual revenue comes from <a href="https://gs.statcounter.com/browser-market-share/desktop/worldwide">approximately 8% of the desktop market</a> and negligible mobile share. Browsers are big, big business.</p>
<h2 id="webkit-is-no-charity" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#webkit-is-no-charity">WebKit Is No Charity</a></h2>
<p>Despite being largely open source, browsers and their engines are not loss leaders.</p>
<p>Safari, in particular, is <em>wildly</em> profitable. <a href="https://www.nytimes.com/2020/10/25/technology/apple-google-search-antitrust.html">The New York Times reported in late 2020</a> that Google now pays Apple between $8-12 billion <em>per year</em> to remain Safari's default search engine, up from $1 billion in 2014. Other estimates put the current payments in the <a href="https://9to5mac.com/2021/08/25/analysts-google-to-pay-apple-15-billion-to-remain-default-safari-search-engine-in-2021/">$15 billion range</a>. What does this almighty torrent of cash buy Google? Searches, preferably of the commercial intent sort.</p>
<p>Mobile <a href="https://www.perficient.com/insights/research-hub/mobile-vs-desktop-usage">accounts for two-thirds of web traffic</a> (or <a href="https://gs.statcounter.com/platform-market-share#monthly-202105-202205">thereabouts</a>), making <a href="https://www.marketingdive.com/news/survey-iphone-owners-spend-more-have-higher-incomes-than-android-users/541008/">outsized iOS adoption among wealthy users</a> particularly salient to publishers and advertisers. Google's payments to Apple are largely driven by the iPhone rather than <a href="https://en.wikipedia.org/wiki/Usage_share_of_operating_systems#Desktop_and_laptop_computers">its niche desktop products</a> where effective browser competition has reduced the influence of Apple's defaults.</p>
<p></p><figure><picture style="--lqip: 393140" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/macOS_share_us_govt_sites.png" alt="Against considerable competition, Safari was used by 52% of visitors to <abbr>US</abbr> Government websites from macOS devices from <time datetime='2022-03-06'>March 6<sup>th</sup></time> to <time datetime='2022-04-04'>April 4<sup>th</sup>, 2022</time>" style="aspect-ratio: 600 / 380" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>Against considerable competition, Safari was used by 52% of visitors to <abbr>US</abbr> Government websites from macOS devices from <time datetime="2022-03-06">March 6<sup>th</sup></time> to <time datetime="2022-04-04">April 4<sup>th</sup>, 2022</time></figcaption>      </figure><p></p>
<br />
<p></p><figure><picture style="--lqip: 393121" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/iOS_share_us_govt_sites.png" alt="The influence of a dozen years of suppressed browser choice is evident on iOS, where Safari is used 90% of the time. Apple's policies caused Mozilla to delay producing an iOS browser for seven years, and its de minimus iOS share (versus 3.6% on macOS) is a predictable result." style="aspect-ratio: 600 / 380" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>The influence of a dozen years of suppressed browser choice is evident on iOS, where Safari is used 90% of the time. Apple's policies caused Mozilla to delay producing an iOS browser for seven years, and its de minimus iOS share (versus 3.6% on macOS) is a predictable result.</figcaption>      </figure><p></p>
<br />
<p></p><figure><picture style="--lqip: 524212" class="preview">        <source sizes="(max-width: 1200px) 70vw, 600px" srcset="https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=3600 2400w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=2400 1600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=1800 1200w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=1200 800w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=900 600w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=750 500w, https://infrequently.org/.netlify/images?url=/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png&fm=avif&w=600 400w" />      <img src="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/visits_by_apple_os_us_govt_sites.png" alt="iOS represents 75% of all visits to <abbr>US</abbr> Government websites from Apple <abbr>OS</abbr>es" style="aspect-ratio: 600 / 371" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>iOS represents 75% of all visits to <abbr>US</abbr> Government websites from Apple <abbr>OS</abbr>es</figcaption>      </figure><p></p>
<p>Even with Apple's somewhat higher salaries per engineer, the skeleton staffing of WebKit, combined with the easier task of supporting fewer platforms, suggests that Apple is unlikely to spend considerably more than Mozilla does on browser development. In 2014, Apple would have enjoyed a profit margin of 50% if it had spent half a billion on browser engineering. Today, that margin would be 94-97%, depending on which figure you believe for Google's payments.</p>
<p>In absolute terms, that's more profit than Apple makes selling Macs.</p>
<p>Compare Cupertino's 3-6% search revenue reinvestment in the web with Mozilla's near 100% commitment, then recall that Mozilla has consistently delivered a superior engine to more platforms. I don't know what's more embarrassing: that some folks argue with a straight face that Apple is trying hard to build a good browser, or that it is consistently overmatched in performance, security, and compatibility by a plucky non-profit foundation that makes just ~5% of Apple's web revenue.</p>
<h2 id="choices%2C-choices" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#choices%2C-choices">Choices, Choices</a></h2>
<p>Steve Jobs launched Safari for Windows in the same <abbr>WWDC</abbr> keynote that unveiled the iPhone.</p>
<p><lite-youtube videoid="eyuvlr9OPfI" videotitle="WWDC 2007 - One More Thing: Safari for Windows" posterloading="lazy">        <a href="https://www.youtube.com/watch?v=eyuvlr9OPfI">WWDC 2007 - One More Thing: Safari for Windows</a>              </lite-youtube></p>
<p>Commenters often fixate on the iPhone's original <a href="https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html">web-based pitch</a>, but don't give Apple stick for reducing engine diversity by abandoning Windows <a href="https://en.wikipedia.org/wiki/Safari_version_history#Windows">three versions later</a>.</p>
<p>Today, Apple doesn't compete outside its home turf, and when it has agency, it prevents others from doing so. These are not the actions of a firm that is consciously attempting to promote engine diversity. If Apple is an ally in that cause, it is only by accident.</p>
<p>Theories that postulate a takeover by Chromium dismiss Apple's power over a situation it created and recommits to annually through its budgeting process.</p>
<p>This is not a question of resources. Recall that Apple spends <a href="https://www.cnbc.com/2022/01/03/apples-3-trillion-market-cap-shows-value-of-share-buybacks-dividend.html">$85 billion <em>per year</em> on stock buybacks</a><sup class="footnote-ref"><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fn-buybacks-3" id="fnref-buybacks-3">3</a></sup>, <a href="https://www.investopedia.com/articles/markets-economy/091816/aapl-apple-dividend-analysis.asp">$15 billion on dividends</a>, <a href="https://www.macrotrends.net/stocks/charts/AAPL/apple/free-cash-flow">enjoys free cash flow</a> larger than <a href="https://en.wikipedia.org/wiki/List_of_countries_by_government_budget">the annual budgets of 47 nations</a>, and <a href="https://www.macrotrends.net/stocks/charts/AAPL/apple/cash-on-hand">retain tens of billions of dollars of cash on hand</a>.<sup class="footnote-ref"><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fn-apples-cash-drawdown-4" id="fnref-apples-cash-drawdown-4">4</a></sup> And that's to say nothing of Apple's $100+ billion in non-business-related long-term investments.</p>
<p>Even if Safari were a loss leader, Apple would be able to avoid producing a <a href="https://9to5google.com/2022/06/06/chrome-mac-speedometer/">slower</a>, <a href="https://infrequently.org/2021/04/progress-delayed/">stifled</a>, <a href="https://googleprojectzero.blogspot.com/2022/02/a-walk-through-project-zero-metrics.html#h.4ajnbffcm6lj">less secure</a>, <a href="https://www.theregister.com/2021/06/16/apple_safari_indexeddb_bug/">famously buggy</a> engine without breaking the bank.</p>
<p>Apple needs fewer staff to deliver equivalent features because Safari supports fewer <abbr>OS</abbr>es. The necessary investments are also <abbr>R&amp;D</abbr> expenses that receive <a href="https://www.bdo.com/insights/tax/r-d-tax/r-d-tax-credit-faqs-for-large-and-small-businesses">heavy tax advantages</a>. Apple enjoys enviable discounts to produce a credible browser, but <a href="https://httptoolkit.tech/blog/safari-is-killing-the-web/">refuses to do so</a>.</p>
<p>Unlike Microsoft's late and underpowered efforts with <abbr title="Internet Explorer">IE</abbr> 7-11, Safari enjoys tolerable web compatibility, more than 90% share on a popular <abbr>OS<abbr>, and an unheard-of war chest with which to finance a defence. The postulated apocalypse seems far away and entirely within Apple's power to forestall.</abbr></abbr></p>
<h3 id="recent-developments" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#recent-developments">Recent Developments</a></h3>
<p>One way to understand the voluntary nature of Safari's poor competitiveness is to put <a href="https://developer.apple.com/documentation/safari-release-notes">Cupertino's recent burst of effort</a> in context.</p>
<p>When regulators and legislators <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#apple's-arguments">began asking questions</a> in 2019, a response was required. Following Congress' query about default browser choice, Apple quietly allowed it through iOS 14 (<a href="https://www.theverge.com/2020/9/24/21454861/apple-ios14-iphone-ipad-fix-default-mail-browser">however ham-fistedly</a>) the following year. This underscores Apple's gatekeeper status and the tiny scale of investment required to enable large changes.</p>
<p>In the past six months, the Safari team has gone on a <a href="https://jobs.apple.com/en-us/search?search=webkit&amp;sort=newest">veritable hiring spree</a>. This month's <a href="https://developer.apple.com/videos/play/wwdc2022/10048/"><abbr>WWDC</abbr> announcements</a> showcased returns on that investment. By spending more in response to regulatory pressure, Apple has eviscerated notions that it could not have delivered a safer, more capable, and competitive browser many years earlier.</p>
<p>Safari's incremental headcount allocation has been large compared to the previous size of the Safari team, but in terms of Apple's <abbr title="purchase and loss">P&amp;L</abbr>, it's loose change. Predictably, hiring talent to catch up has come at <a href="https://www.macrotrends.net/stocks/charts/AAPL/apple/gross-profit">no appreciable loss to profitability</a>.</p>
<p>The competitive potential of any browser hinges on headcount, and Apple is not limited in its ability to hire engineering talent. Recent efforts demonstrate that Apple has been able to build a better browser all along and, year after year, chose not to.</p>
<h2 id="how-apple-gutted-mozilla's-chances" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#how-apple-gutted-mozilla's-chances">How Apple Gutted Mozilla's Chances</a></h2>
<p>For over a dozen years, setting any browser other than Safari as the iOS default was impossible. This spotted Safari a massive market share head-start. Meanwhile, restrictions on engine choice continue to hamstring competitors, removing arguments for why users should switch. But don't take my word for it; here's the recent <a href="https://www.gov.uk/cma-cases/mobile-ecosystems-market-study#final-report">&quot;UK CMA Final Report on Mobile Ecosystems&quot;</a> summarising submissions by Mozilla and others (pages 154-155):</p>
<blockquote>
<p><strong>5.48</strong>
The WebKit restriction also means that browser vendors that want to use Blink or Gecko on other operating systems have to build their browser on two different browser engines. Several browser vendors submitted that needing to code their browser for both WebKit and the browser engine they use on Android results in higher costs and features being deployed more slowly.</p>
<p><strong>5.49</strong>
Two browser vendors submitted that they do not offer a mobile browser for iOS due to the lack of differentiation and the extra costs, while Mozilla told us that the WebKit restriction delayed its entrance into iOS by around seven years</p>
</blockquote>
<p>That's seven years of marketing, feature iteration, and brand loyalty that Mozilla sacrificed on the principle that if they could not bring their core differentiator, there was no point.</p>
<p>It would have been better if Mozilla had made a ruckus, rather than hoping the world would notice its stoic virtue, but thankfully <a href="https://blog.mozilla.org/en/mozilla/calling-for-antitrust-reform/">the T-rex has roused from its slumber</a>.</p>
<p>Given the <a href="https://www.wired.com/story/firefox-mozilla-2022/">hard times the Mozilla Foundation has found itself in</a>, it seems worth trying to quantify the costs.</p>
<p>To start, Mozilla must fund a <em>separate</em> team to re-develop features atop a less-capable runtime. Every feature that interacts with web content must be rebuilt in an ad-hoc way <a href="https://infrequently.org/2021/08/webkit-ios-deep-dive/#introducing-apple-to-developer.apple.com">using inferior tools</a>. Everything from form autofill to password management to content blocking requires extra resources to build for iOS. Not only does this tax development of the iOS product, it makes coordinated feature launches more costly across <em>all</em> ports.</p>
<p>Most substantially, iOS policies against default browser choice — <a href="https://infrequently.org/2021/07/hobsons-browser/">combined with &quot;in-app-browser&quot; and search entry point shenanigans</a> — have delayed and devalued browser choice.</p>
<p>Until late 2020, users needed to explicitly tap the Firefox icon on the home screen to get back to their browser. Naïvely tapping links would, instead, load content in Safari. This split experience causes a sort of pervasive forgetfulness, making the web less useful.</p>
<p>Continuous partial amnesia about browser-managed information is bad for users, but it hurts browser makers too. On OSes with functional competition, convincing a user to download a new browser has a chance of converting nearly all of their browsing to that product. iOS (along with <a href="https://infrequently.org/2021/07/hobsons-browser/">Android and Facebook's mobile apps</a>) undermine this by constantly splitting browsing, ignoring the user's default. When users don't end up in their browser, searches occur through it less often, affecting revenue. Web developers also experience this as a reduction in visible share of browsing from competing products, reducing incentives to support alternative engines.</p>
<p>A foregetful web also hurts publishers. Ad bid rates are suppressed, and users struggle to access pay-walled content when browsing is split. The conspicuious <a href="https://infrequently.org/2021/04/progress-delayed/">lack of re-engagement features like Push Notifications</a> are the rotten cherry on top, forcing sites to push users to the App Store where Apple doesn't randomly log users out, or deprive publishers of key features.</p>
<p>Users, browser makers, web developers, and web businesses all lose. The hat-trick of value destruction.</p>
<h2 id="back-of-the-napkin" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#back-of-the-napkin">Back Of The Napkin</a></h2>
<p>The pantomime of browser choice on iOS has created an anaemic, amnesiac web. Tapping links is more slogging than surfing when autofill fails, passwords are lost, and login state is forgotten. Browsers become less valuable as the web stops being a reliable way to complete tasks.</p>
<p>Can we quantify these losses?</p>
<p>Estimating lost business from user frustration and ad rate depression is challenging. But we can extrapolate what a dozen years of choice might have meant for Mozilla from what we know about how Apple monetises the web.</p>
<p>For the purposes of argument, let's assume Mozilla would be paid for web traffic at the same rate as Apple; $8-15 billion per year for ~75% share of traffic from Apple <abbr>OS</abbr>es.</p>
<p>If the traffic numbers to <abbr>US</abbr> government websites are reasonable proxies for the iOS/macOS traffic mix (big &quot;if&quot;s), then equal share for Firefox on iOS to macOS would be worth $215-400 million <em>per year</em>.<sup class="footnote-ref"><a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fn-mo-money-5" id="fnref-mo-money-5">5</a></sup> Put differently; there's reason to think that Mozilla would not have suffered layoffs if Apple were an ally of engine choice.</p>
<p>Apple's policies have made the web a less compelling ecosystem, its anti-competitive behaviours drive up competitor's costs, and it simultaneously starves them of revenue by undermining browser choice.</p>
<p>If Apple is a friend of engine diversity, who needs enemies?</p>
<h2 id="the-best-kind-of-correct" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#the-best-kind-of-correct">The Best Kind Of Correct</a></h2>
<p>There is a narrow, fetid sense in which Apple's influence is nominally pro-diversity. Having anchored a significant fraction of web traffic at the trailing edge, businesses that do not decamp for the App Store may feel obliged to support WebKit.</p>
<p>This is a malignant form of diversity, not unlike other lagging engines through the years that harmed users and web-based businesses by externalizing costs. But on OSes with true browser choice, alternatives were meaningful.</p>
<p>Consider the loathed memory of <abbr>IE<abbr> 6, a browser that overstayed its welcome by nearly a decade. For as bad as it was, folks could recommend alternatives. <a href="https://en.wikipedia.org/wiki/Google_Chrome_Frame">Plugins also allowed us to transparently upgrade the platform</a>.</abbr></abbr></p>
<p>Before the rise of open-source engines, the end of one browser lineage may have been a deep loss to ecosystem diversity, but in the past 15 years, the primary way new engines emerge has been through forking and remixing.</p>
<p>But the fact of an engine being different does not make that difference valuable, and WebKit's differences are incremental. Sure, Blink now has a faster layout engine, better security, more features, and fewer bugs, but like WebKit, it is also derived from <a href="https://en.wikipedia.org/wiki/KHTML">KHTML</a>. Both engines are forks and owe many present-day traits to their ancestors.</p>
<p></p><figure><picture style="--lqip: 27107" class="preview">      <img src="https://infrequently.org/2021/08/webkit-ios-deep-dive/Timeline_of_web_browsers.svg" alt="The history of browsers includes many forks and remixes. It's naïve to think that will end if iOS becomes hospitable to browser competition. After all, it has been competition that spurred engine improvements and forks." style="aspect-ratio: 3605 / 2840" class="preview" decoding="async" loading="lazy" />      </picture>                  <figcaption>The history of browsers includes many forks and remixes. It's naïve to think that will end if iOS becomes hospitable to browser competition. After all, it has been competition that spurred engine improvements and forks.</figcaption>      </figure><p></p>
<p>Today's KHTML descendants are not the end of the story. Future forks are possible. New codebases can be built from parts. Indeed, there's already valuable cross-pollination in code between Gecko, WebKit, and Chromium. Unlike the '90s and early 2000s, diversity can arrive in valuable increments through forking and recombination.</p>
<p>What's necessary for <em>leading edge</em> diversity, however, is funding.</p>
<p>By simultaneously taking a massive pot of cash for browser-building off the table, returning the least it can to engine development, and preventing others from filling the gap, Apple has foundationally imperilled the web ecosystem by destroying the utility of a diverse population of browsers and engines.</p>
<p>Apple has agency. It is not a victim, and it is not defending engine diversity.</p>
<h2 id="what-now%3F" tabindex="-1"><a class="permalink" href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#what-now%3F">What Now?</a></h2>
<p>A better, brighter future for the web is possible, and thanks to belated movement by regulators, increasingly likely. The good folks over at <a href="https://open-web-advocacy.org/">Open Web Advocacy</a> are leading the way, clearly explaining to anyone who will listen both what's at stake and what it will take to improve the situation.</p>
<p>Investigations are now underway worldwide, so if you think Apple shouldn't be afraid of a bit of competition if it will help the web thrive, consider getting involved. And if you're in the UK or do business there, <a href="https://www.kryogenix.org/days/2022/06/17/help-the-cma-help-the-web/">consider helping the CMA help the web before July 22nd, 2022.</a> The future isn't written yet, and we can change it for the better.</p>

<h2 class="footnotes-sep">FOOTNOTES</h2>
<section class="footnotes">
  <ol class="footnotes-list"><li id="fn-the-role-of-standards-in-compatibility-1" class="footnote-item"><p>Many commenters come to debates about compatibility and standards compliance with a mistaken view of <a href="https://infrequently.org/series/effective-standards-work/">how standards are made</a>. As a result, they perceive vendors with better standards conformance (rather than content compatibility) to occupy a sort of moral high ground. They do not. Instead, it usually represents a broken standards-setting process.</p>
<p>This can happen for several reasons. Sometimes standards bodies shutter, and the state of the art moves forward without them. This presents some risk for vendors that forge ahead without the cover of an <abbr title="standards developing organisation">SDO</abbr>'s protective <abbr>IP</abbr> umbrella, but that risk is often temporary and measured. <abbr>SDO</abbr>s aren't hard to come by; if new features are valuable, they can be standardised in a new venue. Alternatively, vendors can renovate the old one if others are interested in the work.</p>
<p>More often, working groups move at the speed of their most obstinate participants, uncomfortably prolonging technical debates already settled in the market and preventing definitive documentation of the winning design. In other cases, a vendor may play games with intellectual property claims to delay standardisation or lure competitors into a patent minefield (as Apple did with Touch Events).</p>
<p>At the leading edge, vendors need space to try new ideas without the need for the <em>a priori</em> consensus represented by a standard. However, compatibility concerns expressed by developers take on a different tinge over time.</p>
<p>When the specific <abbr>API</abbr> details and capabilities of ageing features do not converge, a continual tax is placed on folks trying to build sites using features from that set. When developers stress the need for compatibility, it is often in this respect.</p>
<p>Disingenuous actors sometimes try to misrepresent this interest and claim that all features must become standards <em>before</em> they are introduced in any engine. This interpretation runs against the <a href="https://www.ietf.org/about/participate/tao/#:~:text=We%20believe%20in%20rough%20consensus%20and%20running%20code">long practice of internet standards development</a> and almost always hides an ulterior motive.</p>
<p>The role of standards is to consolidate gains introduced at the leading edge through <a href="https://www.youtube.com/watch?v=hgEyQsy1D7w">responsible</a> competition. Vendors that fail to participate constructively in this process earn scorn. They bring ignominy upon their houses by failing to bring implementations in line with the rough (documented and tested) consensus or by playing the heel in <abbr>SDO</abbr>s to forestall progress they find inconvenient.</p>
<p>Vendors like Apple. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fnref-the-role-of-standards-in-compatibility-1" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-ex-tac-2" class="footnote-item"><p>In the financial reports of internet businesses, you will see the costs to acquire business through channels reported as &quot;Traffic Acquisition Costs&quot; or &quot;<abbr>TACM</abbr>&quot;. Many startups report their revenue &quot;excluding <abbr>TAC</abbr>&quot; or &quot;ex-<abbr>TAC</abbr>&quot;. These are all ways of saying, &quot;we paid for lead generation&quot;, and search engines are no different. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fnref-ex-tac-2" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-buybacks-3" class="footnote-item"><p><em>This is money Apple believes it cannot figure out a way to invest in its products.</em> That's literally what share buybacks indicate. <a href="https://www.investopedia.com/articles/02/041702.asp#toc-the-motives">They're an admission that a company is not smart enough to invest the money in something productive.</a> Buybacks are attractive to managers because they create artificial scarcity for shares to drive up realised employee compensation — their own included. Employees who are cheesed to realise that their projects are perennially short-staffed are encouraged not to make a stink through <a href="https://www.investopedia.com/terms/r/restricted-stock-unit.asp"><abbr title="restricted stock options">RSU</abbr></a> appreciation. Everyone gets a cut, <abbr>RSU</abbr>-rich managers most of all. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fnref-buybacks-3" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-apples-cash-drawdown-4" class="footnote-item"><p>Different analysts use different ways of describing <a href="https://www.macrotrends.net/stocks/charts/AAPL/apple/cash-on-hand">Apple's &quot;cash on hand&quot;</a>. Some analysts lump in all marketable securities, <a href="https://www.investopedia.com/ask/answers/042915/what-difference-between-current-and-noncurrent-assets.asp">current and non-current</a>, which consistently pushes the number north of $150 billion. Others report only the literal cash value on the books ($34 billion as of <time datetime="2020-05">May 2020). All of this means that it can require more context to compare the numbers in <a href="https://www.apple.com/newsroom/pdfs/FY22_Q2_Consolidated_Financial_Statements.pdf">Apple's consolidated financial statements (PDF)</a> with public reporting on them.</time></p>
<p>The picture is also clouded by changes in the way Apple manages its cash horde. Over the past two years, Apple has begun to draw from this almighty pile of dollars and spend more to inflate its stock price through share buybacks and dividends. This may cast Apple as more cash-poor than it is. A better understanding of the actual situation is derived from <a href="https://www.macrotrends.net/stocks/charts/AAPL/apple/free-cash-flow">free cash flow</a>. Perhaps Apple will continue to draw down from its tall cash mountain to inflate its stock price via buybacks, but that's not a material change in the amount Apple can potentially spend on improving its products. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fnref-apples-cash-drawdown-4" class="footnote-backref">⇐</a></p>
</li>
<li id="fn-mo-money-5" class="footnote-item"><p>Since this post first ran, several commenters have noted a point I considered while writing, but omitted in order to avoid heaping scorn on a victim; namely that Mozilla's management has been asleep at the switch regarding the business of its business.</p>
<p>Historically, when public records were available for both Opera and Mozilla, it was easy to understand how poorly Mozilla negotiated with search partners. Under successive leaders, Mozilla negotiated deals that led to payments <em>less than as half as much per point of share.</em> There's no reason to think MoCo's negotiating skills have improved dramatically in recent years. Apple, therefore, is likely to capture much more revenue per search than Mozilla ears from a Firefox user.</p>
<p>But even if Mozilla only made 1/3 of Apple's haul for equivalent use, the combined taxes of iOS feature re-development and loss of revenue would be material to the Mozilla Foundation's bottom line.</p>
<p>Obviously, to get that share, Mozilla would need to prioritise mobile, which it has not done. This is a deep own-goal and a point of continued sadness for me.</p>
<p>A noble house reduced to rubble is a tragedy no matter who demolishes the final wall. Management incompetence is in evidence, and <a href="https://www.mozilla.org/en-US/about/leadership/#directors">Mozilla's Directors</a> are clearly not fit for purpose.</p>
<p>But none of that detracts from what others have done <em>to</em> the Foundation and the web, and it would be wrong to claim Mozilla should have been perfect in ways its enemies and competitors were not. <a href="https://infrequently.org/2022/06/apple-is-not-defending-browser-engine-choice/#fnref-mo-money-5" class="footnote-backref">⇐</a></p>
</li>
</ol>
</section>

    ]]></content>
  </entry>
</feed>
