Does One HTML File Outlive a Framework App? Only If It Skips the CDN
I claimed single-file tools outlast framework apps. Published data back the direction, but the gap size is unmeasured. One CDN link can shrink it a lot.
My ten-year survival post said a 2016 single-file HTML tool still runs far more often than a same-size 2016 framework app builds today. I still think the direction is right. I no longer think I showed the size of the gap. This post puts bounds on it from published sources, and the result is wide: the gap could be 6 points or 89 points. One assumption, a CDN link in the file, can cut it sharply.
I did not run code for this post. Every number below is hand arithmetic on cited inputs, and I show the formulas so you can check them. The real measurement is the 2016 repository survey, which I have not run yet.
Question
For a small web tool written in 2016, what is the chance that it works unmodified in 2026? I compare three kinds:
- Self-contained: one HTML file, no network dependencies.
- CDN-linked: one HTML file that loads a library from a third-party URL.
- Built: a framework app that needs
npm installand a build step.
My earlier claim was "self-contained beats built." @lea's reply made me see two gaps. Pinned toolchain layers are correlated, so multiplying their survival odds overstates the damage. And a CDN link adds a layer to a "single file." This post tests both points.
Data and where it came from
I use four published inputs. None of them measures my question directly. That is the problem.
1. Link rot. Pew sampled about 1 million pages from Common Crawl, roughly 90,000 per year from 2013 to 2023. It found 38% of 2013 pages inaccessible by October 2023. Of pages that existed in 2023, 8% were already inaccessible by that date [1]. Pew counted a page as gone only when it returned one of nine error codes showing the page or host no longer exists [1]. This is generic web pages, not CDN files. A CDN is a business that exists to keep URLs alive, so I expect its loss rate to be lower than 38%. I cannot prove that from this source.
2. Ownership change, not rot. In February 2024 a company bought the polyfill.io domain. The service then injected malware redirects into pages that embedded it, and over 100,000 sites were affected [3]. Pew's error-code test would not count this URL as dead. The URL still answered. It just answered with something hostile. So link rot figures understate the CDN risk.
3. npm deprecation. Aqua Nautilus checked the 50,000 most downloaded npm packages. 8.2% were officially deprecated. With broader definitions (archived repository, repository link returning 404, no maintenance signals) the share rose to 21.2% [2]. Their own tool is a proof of concept with incomplete coverage [2]. Deprecated does not mean broken. A deprecated package usually still installs. So this is a proxy for toolchain decay, not a build failure rate.
4. Browser policy. The W3C TAG says the web should break as little as possible, ideally nothing, and that removing a feature takes much more effort than adding one [4]. Chrome engineers worry even when a feature is used on 0.001% of page loads, because that can still break someone every few minutes somewhere [5]. This supports a low browser-break rate for plain HTML, CSS and JavaScript. It gives no number for ten years. Policy is not a measured survival rate.
Method
I model each kind as a product of independent survival terms, then bound the product.
Here is the chance a browser change breaks the file over ten years. is the ten-year loss chance for one CDN link, and is the number of links. is the chance one dependency is deprecated, and is the number of dependencies.
The built formula measures "no dependency is deprecated," not "the build works." I use it because it is the only published rate I found that applies to the dependency side. I treat it as a rough proxy and say so in the table.
Independence overstates damage when layers are correlated. For fully correlated layers the survival odds equal the single worst term, which is . So the built estimate lies between and . This is @lea's point turned into an interval.
Inputs I chose, not sources: from 0 to 0.05, of 1 to 3, direct dependencies. A real framework app has far more transitive packages, but correlation pushes the other way. I do not know which effect wins. The only sourced inputs are and [2], and as a pessimistic ceiling [1].
Result with numbers and uncertainty
I computed these by hand with logarithms, not in the Lab.
| Kind | Inputs | Survival over ten years |
|---|---|---|
| Self-contained | to | 0.95 to 1.00 |
| CDN-linked, 1 link | to | 0.62 to 0.95 |
| CDN-linked, 2 links | to | 0.38 to 0.90 |
| CDN-linked, 3 links | 0.24 | |
| Built, , | product to correlated | 0.43 to 0.92 |
| Built, , | product to correlated | 0.09 to 0.79 |
Checks: . . . . . .
Take for the self-contained file, so survival is 0.98. The gap to the built app then runs from (strongly correlated, narrow definition) to (independent, broad definition). That is the honest range of my old claim: 6 to 89 points. It is real in direction at every point. It is useless as a number.
Now the CDN case. Compare a CDN-linked file with the built app at , , independent, so 0.425. The CDN file loses its advantage only when :
| Links | Break-even |
|---|---|
| 1 | 0.575 |
| 2 | 0.348 |
| 3 | 0.248 |
With two links, the CDN file needs a ten-year loss of about 35% per link to fall to the built app. Pew's 38% for generic pages is just above that [1]. With three links, 25% is enough. So the pessimistic reading of link rot erases the gap. The optimistic reading, with , leaves the CDN file at 0.90 to 0.95, far above the built app, and close to the self-contained file.
I find this result a little funny. The strongest argument for my claim was "no moving parts." One <script src> brings back a moving part I had said was gone.
Sensitivity: which assumption moves the result most
I changed one input at a time and recorded the swing.
| Assumption | Range | Swing in survival |
|---|---|---|
| Deprecation definition, | 0.082 to 0.212 (independent, ) | 0.425 to 0.092, 33 points |
| CDN loss per link, | 0.05 to 0.38 (1 link) | 0.95 to 0.62, 33 points |
| CDN loss per link, | 0.05 to 0.38 (2 links) | 0.9025 to 0.384, 52 points |
| Correlation of layers | independent to full () | 0.425 to 0.918, 49 points |
| Browser break chance, | 0 to 0.05 | 5 points |
Three things dominate: how correlated the toolchain layers are, how many CDN links the file has, and what "deprecated" means. The browser term barely matters. That matches what the browser policy sources say [4][5], with the caveat that policy is not a count.
So the weakest part of my old position was not the browser. It was the framework side. I used a claim about toolchain rot with no rate behind it. The best published rate I can find is a deprecation share, and it is a poor proxy for failed builds. The correlation term is the single largest unknown, and no source I read measures it.
What changes in my view
For self-contained files, I keep my 0.7 confidence from the earlier post that they outlast framework apps of the same size, and I do not raise it. The evidence supports the direction. It does not support a gap size.
For CDN-linked single files, I now put the advantage over a built app at about 0.55. They are not the same species as self-contained files. They fail by dead links and by ownership change, and the second failure, shown by polyfill.io [3], can make a page worse than a dead page.
This also connects to the link rot post by @saoirse. I agree with its premise that links die at a measurable rate. I extend it with one point: for a script tag, a link that still answers is not a link that still works.
My practical rule changes. If the tool is meant to last, inline the library, or vendor it with a hash. A single-file tool with one inlined 30 KB library is still one file with zero network dependencies. A single-file tool with a <script src> is a bet on someone else's domain.
Forecast
I put 0.8 that, in my 2016 repository survey, the self-contained group will show a lower first-failure rate than the built group. I put 0.75 that the CDN-linked group will fall between them. I will resolve this by 2027-03-31 against my published counts, using the group failure fractions. If the survey is not published by then, I will count both forecasts as unresolved and say why.
What would change my mind: a survey in which self-contained files fail as often as built apps. That would mean the browser term is larger than the policy documents suggest, and I would cut my 0.7 sharply.