Cloudflare has cut aggregate memory consumption by roughly 100 TB across the infrastructure running its Big Pineapple DNS platform, after changing how it represents and stores cache entries in RAM. The work wasn’t about adding more servers, but about five successive changes to data structures written in Rust that reduced the memory footprint per entry by 56% while also improving cache performance.
Cloudflare’s memory optimization in 30 seconds
- Big Pineapple simultaneously holds more than 250 billion DNS entries for services such as 1.1.1.1, Gateway DNS, and DNS Firewall.
- Cloudflare cut the average footprint per entry from 953 to 420 bytes, a 56% reduction.
- The aggregate savings amount to roughly 100 TB of memory, equivalent to the RAM in about 130 of the company’s Gen 13 servers.
- Insertions increased 43% and query latency dropped 19%.
- Much of the improvement comes from reducing allocations, eliminating redundant data, and storing DNS records more compactly.
The case is especially interesting for systems administrators and developers because it shows just how much a few dozen bytes stop being trivial once an application operates at massive scale. Big Pineapple holds more than 250 billion cached items at any given moment. At that volume, a single wasted byte per entry adds up to more than 250 GB of memory across the whole infrastructure.
Cloudflare began rolling out these changes on May 18, 2026, and finished extending them to all services on July 6. The results were measured both through benchmarks and by observing the resident memory usage of real production instances.
From Vec and String to structures that use exactly what’s needed
A DNS cache entry holds considerably more information than an IP address. Big Pineapple stores the query, the record type, authentication data, DNS answers, authority records, and additional information, plus metadata such as creation time, access count, and TTL (Time to Live).
One of the first improvements came from a common Rust characteristic.
A Vec<T> needs to keep track of three things: a pointer to the elements, its current length, and its capacity. That extra capacity is essential while a collection can still keep growing.
The problem is that a DNS response stored in Cloudflare’s cache no longer changes once it’s inserted.
Keeping capacity for future elements was therefore pointless.
Cloudflare replaced several Vec<T> instances with Box<[T]>, a fixed-size structure that doesn’t need to store extra capacity. It applied a similar idea to text strings, replacing certain String instances with Box<str>.
Each entry held eight fields of these types. Removing eight bytes per field saved 64 bytes per entry, on top of the space that vectors could have reserved without using.
Across the whole platform, this change alone accounts for more than 15 TB of memory, according to Cloudflare’s calculations.
It’s a good example of how consumption needs to be analyzed in large-scale services. A perfectly reasonable structure for a conventional application can become too expensive when there are hundreds of billions of instances of it.
Fewer lists, fewer pointers
Cloudflare also reviewed how it stored the three main sections of a DNS response: answer, authority, and additional information.
Initially, each section had its own list.
The new representation uses a single collection of records and small offsets to know where each section begins.
Since the number of records can be represented with u16 values, each offset only needs two bytes.
The company estimates this change saves 28 bytes per entry by eliminating two separate lists along with their respective pointers and lengths.
There are also details specific to low-level programming. Rust introduces padding to keep certain fields properly aligned within a structure. That’s why removing or reorganizing small fields can produce savings larger than the apparent size of that data.
Cloudflare took advantage of this by also grouping several boolean values using bitflags.
Removing duplicate information and cutting the cost of Rust enums
Another change focused on the owner of each DNS record.
A query for an A record for a domain usually returns records whose owner exactly matches the requested domain. Repeatedly storing that name inside each record means keeping information that’s already available in the cache key.
Cloudflare decided not to store it when both values match.
It only explicitly keeps the owner when it’s actually different, which can happen, for example, after following a CNAME record.
When the response is later reconstructed, Big Pineapple retrieves the original domain from the cache key itself.
The result is less memory used and fewer heap allocations for the most common case.
The next optimization is particularly interesting from a Rust standpoint.
An enum can contain variants of very different sizes, but the structure has to reserve enough space to hold its largest variant.
Cloudflare had a representation similar to this:
pub enum RecordData {
A(Ipv4Addr),
Aaaa(Ipv6Addr),
Txt(Txt),
Naptr(Naptr),
Svcb(Svcb),
}The problem was NAPTR.
Its structure could need around 136 bytes, pushing the enum, once you add the variant tag and alignment, up to 144 bytes.
However, an IPv4 A record only needs four bytes of data, and an AAAA record uses 16.
The difference matters because A and AAAA records account for more than 80% of the traffic Cloudflare used in its tests.
That meant reserving more than 120 unnecessary bytes for many of the most common records.
Box solved part of the problem, but created another one
An initial solution was to keep small records directly inside the enum and place the large variants on the heap using Box.
The size of the main structure dropped considerably.
But a new cost appeared.
Each Box requires a separate heap allocation. Big Pineapple uses jemalloc, which groups allocations into different size classes, so a request can end up using slightly more memory than requested.
The more interesting problem, however, was on the CPU side.
By scattering data across different areas of the heap, the processor has to follow pointers to retrieve each record. That data can end up far apart from each other, causing more accesses to different cache lines.
In other words, saving memory could end up hurting data locality.
Cloudflare kept looking for a different representation.
Storing part of DNS almost as it travels over the network improved memory and speed
The final solution was to move closer to the actual binary format used by DNS.
The company considered storing complete DNS responses directly in wire format, but ruled out doing so across the board because it would have introduced other complications. DNSSEC, name compression, and certain fields that change depending on the client would have forced it to keep several representations or re-parse entire packets on every query.
The middle ground was to store record data as bytes, while keeping the rest of the entry as structured fields.
Instead of having numerous enums and individual allocations, records are stored back-to-back inside a single Box<[u8]>.
Each element carries a two-byte length prefix followed by the encoded record.
This decision brings two advantages.
The first is obvious: much of the overhead associated with enums, pointers, and separate allocations disappears.
The second affects the processor: the data ends up stored contiguously, improving locality in CPU caches.
In exchange, Cloudflare loses the ability to randomly access any record through a traditional index. It has to walk through the buffer sequentially.
In this case, the company considers the cost acceptable because a DNS entry typically contains few records.
In addition, certain types can be copied almost directly from the cache into the DNS response.
This happens with A, AAAA, TXT, and various DNSSEC records. Others that contain domain names, such as CNAME, NS, MX, or SOA, still require processing to correctly apply DNS name compression.
Cloudflare attributes this reorganization alone to an additional 5% reduction in query latency.
It also uses a reusable temporary buffer to build records before storing them. Since that space has already grown during previous operations, it can typically be reused without constantly requesting new memory.
According to its benchmarks, this last change alone increased cache insertion performance by 13%.
From 953 to 420 bytes per entry
The cumulative effect of the five optimizations is far greater than that of any single one of them.
| Metric | Before | After | Change |
|---|---|---|---|
| Net footprint per entry | 953 bytes | 420 bytes | -56% |
| Memory allocated per entry | 1.1 KB | 461 bytes | -58% |
| Cache insertions | 625,000/s | 893,000/s | +43% |
| Query latency | 828 ns | 670 ns | -19% |
The results come from Cloudflare’s benchmarks, which try to approximate its real traffic using a mix of 56% A records, 25% AAAA, and 19% TXT, with one to four records per entry.
The company itself notes that these tests don’t exactly reproduce production conditions. Real-world consumption depends, among other factors, on traffic mix, cache occupancy, allocator state, and other memory used by the process.
That’s why it also measured its real instances.
At the 99th percentile, resident memory usage dropped from 9.3 GB to 5.3 GB, a 43% reduction. At the 90th percentile, it went from 6.5 to 3.8 GB, a 42% reduction.
Once the rollout was complete and caches had stabilized, Cloudflare calculates that the aggregate working set across the whole infrastructure had shrunk by roughly 100 TB.
The company compares that amount to the memory installed in roughly 130 of its Gen 13 servers.
But it doesn’t necessarily plan to leave those 100 TB unused.
Cloudflare plans to reinvest part of the freed-up capacity into expanding its caches without increasing total memory consumption. A cache capable of holding more entries can improve its hit rate and reduce the number of queries that need to be sent to external DNS servers.
It isn’t the company’s only cache-related fix this year: it also recently corrected an issue that was diverting cache traffic for sites hosted on public clouds.
The Big Pineapple case also offers a fairly concrete technical lesson for large-scale services: choosing the right data structure can matter just as much as choosing the algorithm.
Vec, String, enum, or Box aren’t inherently better or worse. Their cost depends on how they’re used, how long they stay in memory, and how many millions or billions of objects end up existing simultaneously.
In a conventional application, saving 64 bytes might not justify a complete overhaul of the memory model. With 250 billion entries, those same 64 bytes turn into terabytes.
Frequently Asked Questions
How did Cloudflare manage to save 100 TB of RAM?
Cloudflare changed how it represents its DNS cache entries in memory, reducing dynamic structures, eliminating redundant information, reorganizing records, and storing part of them in a compact binary buffer.
How many DNS entries does Cloudflare keep cached?
Big Pineapple simultaneously holds more than 250 billion entries across services such as 1.1.1.1, Gateway DNS, DNS Firewall, and other Cloudflare DNS systems.
Did the optimizations reduce 1.1.1.1’s performance?
According to the benchmarks Cloudflare published, the opposite happened. Insertion performance rose 43% and query latency dropped 19%.
What will Cloudflare use the freed-up memory for?
The company plans to use part of that capacity to increase the size of its caches without increasing total RAM consumption, aiming to raise hit rates and reduce queries sent to upstream servers.
Source: Cloudflare

