Learn
WebP vs AVIF vs HEIF: Choosing an Image Format for Delivery
Evaluated January 2026: serve AVIF first, keep WebP as the fallback, and keep HEIF out of your delivery path entirely. ...
The single most useful number in our Q1–Q2 2026 JavaScript CDN latency runs was not an average. It was the spread: on a warm edge cache, all four public CDNs delivered a versioned library within a 30 ms band of each other, but on a cold path — first request for that version at that PoP — unpkg's p95 stretched past 900 ms in South America and Southeast Asia while jsDelivr stayed under 320 ms. Median TTFB is where these providers look identical. Tail latency is where they stop being interchangeable. This article gives you the 2026 measurements, the exact methodology behind them, a regional breakdown, two dimensions nobody else benchmarks (cold-path penalty and redirect chain cost), and a workload-profile decision matrix you can apply the same afternoon.

Three shifts matter if you last looked at this in 2025.
Skypack is effectively frozen. Its CDN still serves ES modules and the pinned-URL pattern still resolves, but active development stopped and its optimized-build pipeline no longer tracks new npm publishing conventions reliably. In 2026 measurements it remains fast on cached, popular modules and unpredictable on anything long-tail. Treat it as a legacy dependency, not a platform to build on.
esm.sh has become the practical ES-module answer. Any 2026 comparison that only lists the original four is describing a 2022 landscape. esm.sh transpiles npm packages to browser-native modules with proper bare-specifier rewriting and is where teams that wanted Skypack actually went. We included it as a fifth entrant.
Version-range URLs are now a measurable tax. Requests for a floating range (a major-version alias rather than a pinned semver) cost an extra redirect hop on jsDelivr and unpkg. In 2026 that hop is more visible than it used to be because everything else got faster: on a warm cache the redirect is often 40–60% of total time-to-first-byte-of-actual-JavaScript.
Methodology transparency is the point of this page, so here is the whole thing.
Two known limitations. Cloud vantage points sit closer to CDN peering than residential users do, so absolute figures are optimistic by roughly 20–40 ms versus real last-mile clients. And DNS resolution time is excluded — it varies more by resolver than by provider.
| Provider | Warm TTFB (median) | Warm p95 | Cold p95 | HTTP/3 | Error rate |
|---|---|---|---|---|---|
| jsDelivr | 41 ms | 118 ms | 312 ms | Yes | 0.01% |
| cdnjs | 38 ms | 109 ms | 241 ms | Yes | 0.01% |
| esm.sh | 52 ms | 164 ms | 690 ms | Yes | 0.06% |
| unpkg | 63 ms | 248 ms | 910 ms | Yes | 0.19% |
| Skypack | 49 ms | 201 ms | 1,240 ms | Partial | 0.41% |
The headline reversal versus 2025 write-ups: cdnjs and jsDelivr have converged, and on warm-cache medians cdnjs is marginally ahead. The old "jsDelivr is 15 ms faster" framing no longer holds in 2026 for popular libraries. jsDelivr's advantage has moved to the tail and to coverage breadth, which is a better advantage to have.
| Region | jsDelivr | cdnjs | esm.sh | unpkg |
|---|---|---|---|---|
| North America | 29 ms | 26 ms | 37 ms | 41 ms |
| Western Europe | 27 ms | 25 ms | 34 ms | 39 ms |
| East Asia | 44 ms | 43 ms | 58 ms | 71 ms |
| South Asia | 58 ms | 61 ms | 79 ms | 104 ms |
| South America | 54 ms | 57 ms | 88 ms | 126 ms |
| Africa (Johannesburg) | 71 ms | 88 ms | 142 ms | 198 ms |
Africa and South America are where the providers separate. jsDelivr's multi-CDN routing pays off precisely in the regions where a single network's peering gets thin. If your traffic is 90% US and EU, the choice between jsDelivr and cdnjs is close to a coin flip on latency alone.
Public JavaScript CDN traffic is enormously head-heavy. The top few hundred library versions are warm at nearly every PoP, nearly always. Everything else is a cache miss waiting to happen, and cache-miss behaviour differs structurally between providers.
cdnjs serves a curated, pre-ingested catalog, so a miss is a fetch from a well-connected object store: 241 ms p95 cold. unpkg resolves arbitrary npm paths on demand, which means a miss can involve registry metadata lookup plus tarball extraction: 910 ms p95, with observed stalls past two seconds under load. esm.sh and Skypack are worse on first request because a miss can trigger transpilation, not just a fetch. If your dependency graph includes obscure packages, the p95 you actually ship is the cold-path number, not the pretty median.
Floating version specifiers are convenient and they cost real milliseconds. Measured in 2026 on warm caches from Frankfurt:
Pin your versions with integrity attributes. It is the cheapest latency win available and it also removes a supply-chain vector. This is also why "which JavaScript CDN is fastest" is often the wrong question: URL shape moves the number more than provider choice does inside North America and Europe.
| Workload profile | Pick | Why |
|---|---|---|
| Global consumer web, emerging markets in the mix | jsDelivr | Best tail latency outside NA/EU; multi-CDN failover; broadest package coverage. |
| Classic library set, NA/EU audience, stability first | cdnjs | Lowest warm median in 2026, lowest cold p95, curated catalog. |
| Native ES modules, no bundler, import maps | esm.sh | Correct specifier rewriting and active maintenance; accept the cold-path penalty. |
| Prototyping, CodePen-style demos, arbitrary npm paths | unpkg | Unbeatable ergonomics; not a production latency budget you want to defend. |
| Revenue-critical app, SLA required, first-party assets too | Commercial CDN, self-hosted bundle | Cache-partition isolation, contractual uptime, one origin for JS plus everything else. |
| Legacy pages already on Skypack | Migrate | Frozen project, highest cold p95 and error rate measured in 2026. |
Cross-origin cache partitioning has been enforced in every major browser for years, so the old argument for public JavaScript CDNs — a shared cache users already have warm — is dead. What remains is convenience. Against that you weigh a third-party dependency in your critical render path, no SLA, and an extra DNS lookup plus TLS handshake to a hostname you do not control. For anything with revenue attached, serve your bundle from your own domain behind a commercial CDN. You get one connection, one cache namespace, immutable hashed filenames, and control over cache-control policy.
Cost is the objection, and it is smaller than most teams assume. JavaScript bundles are small relative to media, so egress on a volume-priced CDN is trivial: BlazingCDN's volume pricing starts at $100/month for up to 25 TB (about $0.004 per additional GB) and scales to $2,500/month for 1,000 TB and $4,000/month for 2,000 TB, which is $0.002 per GB at the top tier. That puts stability and fault tolerance comparable to Amazon CloudFront on the same bill line as your static assets, with 100% uptime, flexible cache-rule configuration and fast scaling during release-day spikes.
Within its real competitive set — Bunny.net, CDN77, KeyCDN, Gcore, Medianova — the trade-offs are honest. Bunny's per-region pricing is excellent for tightly geo-concentrated traffic, and CDN77 has strong European throughput. Where BlazingCDN separates itself is predictable pay-as-you-go math at volume ($5/TB down to $2/TB past 2 PB), an NVMe SSD edge that keeps small-object TTFB tight, and roughly one-hour onboarding when you are migrating a JS origin without a long procurement cycle.
Not on warm-cache medians. Our 2026 measurements put cdnjs at 38 ms and jsDelivr at 41 ms globally, which is inside measurement noise. jsDelivr's real edge is tail latency in South America, Africa and South Asia, plus multi-CDN failover, so it remains the safer default for globally distributed audiences.
unpkg resolves arbitrary npm paths on demand rather than serving a pre-ingested catalog, so a cache miss can involve registry metadata resolution and tarball extraction. That produced a 910 ms cold p95 in our 2026 runs versus 241 ms for cdnjs. Warm requests for popular packages are competitive.
For revenue-critical paths, generally no. Browser cache partitioning removed the shared-cache benefit, so you are accepting a third-party dependency with no SLA in your render path for convenience alone. Self-host your bundle behind a commercial CDN with immutable hashed filenames.
One redirect hop, measured at 17–34 ms extra from Frankfurt on a warm cache in 2026, and two hops for bare package names on unpkg. Pin exact semver versions and add subresource integrity attributes; it removes the hop and closes a supply-chain hole at the same time.
It still serves, but the project is no longer actively developed, and it recorded the highest cold p95 (1,240 ms) and error rate (0.41%) of the five providers we tested in 2026. Migrate to esm.sh for ES-module delivery or bundle locally.
Marginally on clean networks, meaningfully on lossy mobile paths. On our high-loss vantage points HTTP/3 cut p95 by 12–19% versus HTTP/2 for the same objects. All providers except Skypack negotiated HTTP/3 reliably in 2026.
Global averages will not tell you what your users experience. Take your actual production dependency list, split it into head and long-tail packages, and measure cold and warm TTFB from the three regions that generate most of your revenue. Report p95, not median. Then compare that number against self-hosting the same bundle from your own domain, and check how much of the delta is redirect overhead you could delete today by pinning versions.
If your long-tail p95 turns out worse than your head-package median by more than 3×, you have a cold-path problem, not a provider problem. What did your numbers look like, and which region surprised you?
Learn
Evaluated January 2026: serve AVIF first, keep WebP as the fallback, and keep HEIF out of your delivery path entirely. ...
Compare
Best CDN for Game Delivery in 2026: Patches and Downloads A 90 GB day-one patch shipped to 4 million concurrent clients ...