Cloudflare's September 1, 2026 prototype starts from an almost embarrassingly simple question: if a text response enters the cache uncompressed, why keep storing and moving those same raw bytes between data centers?1
Cloudflare calls the experiment Cache Transcoding. On an eligible cache miss, the Pingora proxy encodes the body with Zstandard level 3 before writing it to disk. The zstd representation stays compressed while it moves through Tiered Cache, then the client-facing hop decodes it back to the original bytes before serving the response.1
The browser neither needs to receive zstd nor even needs to know that the cache used it internally.
That is what makes the experiment more interesting than another HTTP compression benchmark: Cloudflare treats compression as an internal storage representation, separated from the wire format seen outside the cache.
Compress once
The CPU bill is asymmetric: encoding spends compute when an object enters the cache, while decoding spends it every time that object is served.1
On Cloudflare's controlled corpus, the measured numbers were:
- 2.834× compression ratio;
- 4.31 ns per byte to encode, around 232 MB/s;
- 1.56 ns per byte to decode, around 641 MB/s.1
Encoding is the more expensive operation per byte, but it happens on the fill. If the object is later served ten, one hundred or one thousand times, it is not compressed again one thousand times.
This is fundamentally different from recompressing a raw object on every request.
The cache already owns a compact representation. The repeated operation is decompression, which is exactly where zstd is designed to stay fast.13
Cache as codec
Cloudflare says its cache traditionally stores an asset using the content encoding supplied by the origin. If the origin sends an identity response with no Content-Encoding, those uncompressed bytes can be stored and transferred between data centers in that form.1
Cache Transcoding adds another layer, with metadata recording that the on-disk object is encoded with zstd and preserves its original content length. A storage marker also prevents another cache layer from encoding an object a second time.1
That matters especially with Tiered Cache.
When a lower tier misses but an upper tier already has the object, the compact zstd representation moves directly between cache tiers. It remains compressed on the internal link and on the lower tier's disk, with decoding delayed until the client-facing hop.1
The cache stops being merely a warehouse for whatever bytes arrived and begins choosing its own physical representation.
Pingora is a natural place for that decision because Cloudflare's open-source Rust proxy framework is built around large-scale network request paths.2
Refuse most bytes
Profitable compression begins with knowing what not to compress.
In the traffic sample Cloudflare describes, images, video and fonts represented only 21.4% of requests but 63.3% of bytes.1
Because those formats are normally compressed already, running them through zstd again would spend CPU for little benefit.
Text has a different profile. HTML, JSON, CSS and JavaScript represented 67.3% of requests and 22.3% of bytes, and about 71% of that text slice arrived without Content-Encoding.1
The prototype therefore requires all of the following: 200 OK, no existing Content-Encoding, a compressible text Content-Type, a known Content-Length and at least 4 KiB of content.1
Range requests, slice subrequests, binary data, precompressed responses, unknown-length bodies and some active upstream-compression paths are left alone.1
The cheapest compression operation remains the one that never runs.
Four kibibytes
The 4 KiB threshold is not a law of compression.
Cloudflare chose it because the cutoff removes many tiny requests while excluding only about 1% of otherwise eligible bytes in its sample.1
Below that point, per-object overhead begins to eat the benefit; above it, the prototype captures nearly all the measured storage saving.
The same applies to the zstd setting. The first prototype uses level 3, deliberately conservative, and Cloudflare says higher levels can be tested once the CPU budget is understood.1
That matches Zstandard's design.
The reference implementation exposes many levels so users can move gradually between speed and ratio while preserving fast decompression.3 Meta described the same idea in 2018: zstd produced different wins when replacing zlib, LZ4 or XZ because those systems optimized for different constraints.4
There is no universally best zstd setting.
There is a point where compute is cheaper than bytes.
One million requests
The 2.834× figure needs a large “controlled test” label, because Cloudflare sent more than one million requests across ten cache servers rather than sampling the full production distribution. Half the performance campaign used Tiered Cache and half ran without it.1
The two test assets were roughly 195 KiB and 272 KiB, selected precisely because they were compressible. Both shrank by about 2.8 times.1
Cloudflare states the limitation explicitly: that corpus creates a clean signal for validating the architecture, but it does not represent every text object on the Internet. A broader corpus is needed before treating the measured ratio as a fleet-wide constant.1
That caveat changes how “save petabytes” should be read: the prototype obviously does not prove that every current petabyte automatically becomes 353 terabytes.
It shows that a meaningful class of currently uncompressed cache objects could buy much more effective capacity if the measured ratio remains favorable across representative traffic.
A few percent
Cloudflare's model puts the extra CPU cost at a few percent under the traffic and reuse assumptions it tested with zstd level 3.1
At CDN scale, that percentage of CPU can translate into a great deal of hardware and energy. The other side of the trade is global too: more customer content retained in the same disk capacity, fewer evictions caused by large identity objects and fewer bytes crossing between cache tiers.1
The economics are therefore slightly strange: spend compute to save storage and network.
Distributed systems make this trade constantly, but Cache Transcoding makes the units unusually visible: CPU nanoseconds per byte, bytes occupied on disk and bytes transferred over the backbone.
Zstd's compression performance was already known; the interesting result is an architecture that can move the balance without asking the origin or client to change.
Why not only hot objects?
The team also tested a natural intuition: transcode only popular content, since a hot object is served many times and looks like the obvious place to amortize the initial encoding cost.
The result does not follow that intuition cleanly.
Decoding happens on every serve, whether the object is moderately popular or extremely hot. Restricting the feature to the hottest objects therefore sacrifices storage savings without reducing CPU by the same proportion.1
The simpler policy performed better in the model: transcode all eligible compressible text at 4 KiB or larger.1
This is a useful case where an “intelligent” popularity heuristic buys less than a blunt but well-placed boundary.
The system therefore avoids predicting the future popularity of each object and only checks whether an object belongs to a class where compression has a good chance of paying for itself.
Not the Internet yet
Cloudflare repeatedly calls Cache Transcoding a prototype,1 wording that should survive the trip from engineering note to headline instead of turning into a fleet-wide deployment announcement.
The correctness campaign covered cache misses, cache hits, single-hop fills and Tiered Cache fills. Jaeger traces and Prometheus metrics were used to confirm where encoding and decoding actually occurred.1
That is serious architecture validation, but it is not yet evidence for the complete distribution of Cloudflare traffic.
The article says so directly: a broader corpus is required before the measured compression ratio can be treated as representative of the fleet.1
Other knobs remain open too, including size threshold, zstd level, eligibility categories, acceptable CPU budget and behavior on text that compresses much less readily.
At this scale, an algorithm is not finished when it works.
It is finished when it works without moving the problem onto a more expensive resource.
Internal format
The strongest idea in Cache Transcoding may be the permission it gives the cache to stop preserving bytes in exactly the form they arrived, rather than Zstandard itself.
Databases already transform their physical representations and compressed filesystems do too; Cloudflare applies the same idea to an HTTP object while keeping the transformation invisible at the endpoints.
The origin can keep producing an identity response and the client can keep receiving a representation it understands, while the cache chooses a cheaper internal form between them.
That independence makes the design adjustable: zstd level 3 and 4 KiB today, perhaps a different threshold, level or policy later if measurements justify it.
The storage representation becomes an implementation detail rather than an external contract.
Buy cache with CPU
“Petabytes saved” is naturally the headline number, although the prototype becomes more useful when reduced to its actual costs.
Once per fill: 4.31 ns per byte to encode.
Every serve: 1.56 ns per byte to decode.
On disk and between cache tiers: roughly one third of the original size for the two controlled assets.1
At Cloudflare scale, a few percent more CPU can be an enormous expense, while adding physical petabytes and moving more bytes between data centers is expensive in a different column of the same bill.
Cache Transcoding searches for the point where available compute costs less than the storage and backbone capacity it releases.
The 2026 result is not yet “Cloudflare recompressed its CDN.” At this stage it is more useful than that: Cloudflare built a precise place in Pingora where this trade can be measured without forcing every origin and every client to participate.
In a distributed system, making a trade measurable is often the first real optimization.