Big Pineapple adalah sistem di balik layanan DNS Cloudflare, termasuk 1.1.1.1, Gateway DNS, DNS Firewall, dan AS112. Setiap saat, sistem ini menyimpan lebih dari 250 miliar entri cache DNS. Pada skala sebesar itu, membuang satu byte saja per entri berarti memboroskan lebih dari 250 gigabyte memori di seluruh jaringan server Cloudflare.
Melalui lima perubahan berturut-turut pada cara data cache disimpan, tim Cloudflare berhasil memangkas ukuran penyimpanan per entri lebih dari 50%. Di seluruh jaringan server mereka, perubahan ini membebaskan sekitar 100 terabyte memori — setara dengan total RAM dari 130 unit server generasi terbaru mereka. Yang lebih menarik, cache ini juga menjadi lebih cepat: kecepatan penyimpanan data baru naik 43%, sementara waktu pencarian data turun 19%. Dengan kata lain, penghematan ruang ini tidak mengorbankan kecepatan sama sekali.
Apa yang Disimpan dalam Cache DNS
Setiap kali seseorang mengakses sebuah website, perangkat mereka perlu menerjemahkan nama domain (misalnya, example.com) menjadi alamat server yang sesungguhnya. Proses ini disebut pencarian DNS. Agar tidak perlu mengulang proses ini setiap saat, hasil pencarian tersebut disimpan sementara dalam sebuah cache, sehingga permintaan berikutnya untuk domain yang sama bisa dijawab jauh lebih cepat.
Saat sistem baru dinyalakan, cache-nya masih kosong. Seiring permintaan DNS masuk, cache mulai terisi hingga mencapai kapasitas maksimalnya. Setelah itu, entri yang paling lama atau paling jarang digunakan akan dihapus untuk memberi ruang bagi entri baru.
Ukuran cache berbeda-beda di setiap lokasi data center. Ketika fitur EDNS Client Subnet (ECS) digunakan, server otoritatif akan memberikan jawaban yang berbeda-beda tergantung jaringan asal pengguna, sehingga satu pencarian yang sama bisa memiliki beberapa versi jawaban yang harus disimpan sekaligus di cache. Hal ini membuat jumlah entri sekaligus memori yang dibutuhkan menjadi lebih besar — sehingga optimasi yang dibahas di artikel ini justru memberi dampak paling besar di lokasi-lokasi dengan penggunaan ECS yang tinggi.
Setiap entri dalam cache terdiri dari dua bagian: sebuah kunci pencarian dan sebuah nilai. Kunci pencarian berisi identitas dari apa yang dicari — nama domain, jenis datanya, dan beberapa penanda lain:
pub struct CacheKey {
qname: Name,
qtype: Rtype,
authenticated: bool,
tag: Vec<u8>,
}Sementara itu, nilainya menyimpan jawaban DNS itu sendiri — mencakup jawaban utama, informasi otoritas, dan informasi tambahan — beserta metadata pendukung seperti kapan data tersebut disimpan, berapa kali data itu diakses (hit counter), dan berapa lama data tersebut masih berlaku (TTL):
pub struct CacheEntry {
timestamp: UnixTimeStamp,
pub inception: Instant,
pub ttl: Ttl,
pub hits: u32,
pub answers: Vec<Record>,
pub authority: Vec<Record>,
pub additional: Vec<Record>,
pub errors: Vec<ExtendedError>,
...
}Kedua struktur data ini masih menyimpan sejumlah kolom yang, tanpa disadari, memakai lebih banyak ruang daripada yang sebenarnya dibutuhkan setelah data tersebut tersimpan di cache. Bagian-bagian berikut menjelaskan bagaimana tim Cloudflare menemukan dan memperbaiki pemborosan ini satu per satu.
Cara Mengukur Penghematan Memori
Untuk mengukur dampak dari setiap perubahan, tim Cloudflare mengisi cache dengan data uji coba yang meniru pola trafik sesungguhnya di server produksi mereka. Mereka mencatat berapa banyak memori yang digunakan oleh setiap entri, sekaligus mengukur kecepatan penyimpanan dan pencarian data, untuk memastikan penghematan memori tidak dibayar dengan performa yang lebih lambat.
Karena data uji coba ini hanya mendekati kondisi sesungguhnya, tim juga memantau langsung penggunaan memori di server produksi selama proses penerapan perubahan berlangsung, untuk memastikan hasilnya konsisten dengan yang diharapkan.
Menghilangkan Ruang Cadangan yang Tidak Terpakai
Struktur data yang umum digunakan untuk menyimpan daftar (seperti daftar jawaban DNS) biasanya menyediakan ruang cadangan tambahan, agar daftar tersebut bisa bertambah besar tanpa perlu terus-menerus dialokasikan ulang. Ruang cadangan ini berguna ketika daftar memang masih akan diubah-ubah.
Namun, begitu sebuah jawaban DNS disimpan ke dalam cache, jawaban tersebut tidak akan pernah diubah lagi. Ruang cadangan yang disediakan pun menjadi sia-sia — tidak hanya menghabiskan sedikit memori tambahan untuk mencatat kapasitas cadangan itu sendiri, tetapi juga menyisakan ruang kosong yang tidak pernah terpakai di dalamnya.

Dengan mengganti struktur data ini menjadi versi yang berukuran tetap (tidak bisa bertambah setelah dibuat), penghematan ini saja menghasilkan penghematan lebih dari 15 terabyte di seluruh sistem yang menyimpan 250 miliar entri.

Menggabungkan Beberapa Daftar Menjadi Satu
Setiap jawaban DNS sebenarnya terdiri dari beberapa bagian: jawaban utama, informasi otoritas, dan informasi tambahan. Sebelumnya, ketiga bagian ini disimpan sebagai tiga daftar terpisah, yang masing-masing membutuhkan ruang tersendiri untuk mencatat lokasi dan ukurannya di memori.

Karena jumlah data dalam setiap bagian selalu kecil, ketiganya bisa digabung menjadi satu daftar tunggal, dengan penanda kecil yang menunjukkan di mana setiap bagian dimulai. Perubahan sederhana ini menghemat 28 byte lebih lanjut per entri — dan karena struktur data ikut menyusut, penghematan totalnya bahkan sedikit lebih besar dari itu.
Tidak Perlu Menyimpan Ulang Informasi yang Sudah Diketahui
Setiap catatan DNS memiliki “pemilik” — yaitu nama domain yang menjadi asal catatan tersebut. Pada kebanyakan kasus, pemilik ini sama persis dengan domain yang sedang dicari penggunanya. Sebagai contoh, pencarian untuk example.com A menghasilkan dua catatan dengan pemilik yang sama:
$ dig example.com A
;; ANSWER SECTION:
example.com. 300 IN A 198.51.100.1
example.com. 300 IN A 198.51.100.2Namun, dalam kasus tertentu — misalnya ketika sebuah domain dialihkan lewat CNAME — pemilik catatan bisa berbeda dari domain yang dicari:
$ dig example.com A
;; ANSWER SECTION:
example.com. 300 IN CNAME cdn.example.com.
cdn.example.com. 300 IN A 198.51.100.1
cdn.example.com. 300 IN A 198.51.100.2Format DNS di jaringan sebenarnya sudah punya cara untuk menghemat penulisan nama domain yang berulang ini (disebut name compression): alih-alih menuliskan domain yang sama dua kali, kemunculan berikutnya cukup diwakili oleh penunjuk 2-byte ke kemunculan pertamanya. Namun, mengikuti penunjuk semacam ini setiap kali ada pencarian di cache justru memperlambat proses — sehingga sebelumnya tim Cloudflare memilih menyimpan nama pemilik secara lengkap di setiap catatan, demi kecepatan.
Karena pada kebanyakan kasus nama domainnya identik, tim Cloudflare hanya perlu menyimpan nama pemilik saat pemilik tersebut memang berbeda dari domain yang dicari. Bila sama, nama tersebut cukup ditebak ulang dari kunci pencarian yang sudah tersedia — tanpa perlu menyimpannya dua kali:
pub struct Record {
owner: Option<Box<Name>>,
class: Class,
ttl: Ttl,
rtype: Rtype,
data: RecordData,
}Ketika owner bernilai None, nama domain yang dicari akan diambil ulang dari kunci pencarian saat jawaban DNS disusun, tanpa perlu ada alokasi memori tambahan. Ketika pemiliknya berbeda — seperti pada catatan A di balik sebuah CNAME — Some menyimpan penunjuk ke nama lengkap tersebut di memori.

Dalam praktiknya, mayoritas catatan DNS memiliki pemilik yang identik dengan domain yang dicari, sehingga sebagian besar data tidak lagi membutuhkan ruang memori tambahan untuk informasi ini.
Menghindari Pemborosan Ruang untuk Tipe Data yang Jarang Dipakai
Masalahnya: Semua Jenis Data Diperlakukan Sebesar Data Terbesar
Cache DNS perlu menyimpan berbagai jenis catatan — mulai dari alamat IP yang sederhana, hingga jenis catatan lain yang jauh lebih kompleks dan jarang muncul. Ketika berbagai jenis data ini disimpan dalam satu wadah yang sama, wadah tersebut akan selalu berukuran sebesar jenis data yang paling besar, meskipun jenis data yang sedang disimpan sebenarnya jauh lebih kecil.
Secara teknis, hal ini terjadi karena struktur data seperti enum dalam bahasa pemrograman Rust — meski praktis untuk menampung berbagai jenis nilai — akan selalu berukuran sebesar variannya yang paling besar. Sebagai gambaran sederhana, tipe Option
pub enum Option<T> {
None,
Some(T),
}Pola yang sama berlaku pada RecordData, struktur yang menampung seluruh kemungkinan jenis catatan DNS:
pub enum RecordData {
A(Ipv4Addr),
Aaaa(Ipv6Addr),
Txt(Txt),
Naptr(Naptr),
Svcb(Svcb),
// ...
}Pada kasus Cloudflare, jenis catatan alamat IP paling sederhana (yang mencakup lebih dari 80% seluruh trafik mereka) hanya membutuhkan beberapa byte saja, tetapi karena harus mengikuti ukuran jenis data paling besar (NAPTR), ia ikut memakai ruang hingga lebih dari 140 byte — sebagian besar terbuang percuma sebagai ruang kosong.

Solusinya: Pisahkan Data yang Besar ke Tempat Lain
Untuk jenis data yang berukuran besar dan jarang dipakai, variannya dalam enum tersebut “dikotakkan” (boxing) — datanya dipindahkan ke lokasi memori terpisah (heap), dan yang disimpan di tempat asal hanyalah sebuah penunjuk kecil (Box) menuju lokasi tersebut:
rust
pub enum RecordData {
// Small and common variants are stored inline
A(Ipv4Addr),
Aaaa(Ipv6Addr),
// Large variants are stored on the heap
Txt(Box<Txt>),
Naptr(Box<Naptr>),
Svcb(Box<Svcb>),
// ...
}Dengan begitu, jenis data yang kecil dan sering dipakai (seperti A dan AAAA) tidak lagi perlu ikut menanggung ukuran jenis data yang besar dan jarang muncul — untuk catatan A dan AAAA, langkah ini saja berhasil menghemat 120 byte per catatan.

Konsekuensi dari Solusi Ini
Memindahkan data ke lokasi terpisah bukan tanpa biaya. Pertama, sistem alokasi memori kadang membulatkan ukuran penyimpanan ke atas, sehingga tetap ada sedikit ruang yang terbuang. Kedua, karena data kini tersebar di berbagai lokasi memori dan bukan lagi berdekatan, sistem butuh sedikit waktu tambahan untuk “melompat” mengambil data tersebut, yang berpotensi memperlambat proses pembacaan.

Kedua biaya ini masih tergolong kecil, namun langkah berikutnya berhasil menghapus keduanya sekaligus.
Menyimpan Data dalam Format yang Lebih Ringkas dan Siap Pakai
Sebagai langkah penyempurnaan, alih-alih menyimpan setiap catatan DNS dalam bentuk yang sudah “terurai” ke berbagai kolom data, tim Cloudflare menyimpan catatan tersebut dalam bentuk mentah yang ringkas — mirip dengan format yang nantinya akan langsung dikirim ke pengguna. Setiap catatan disimpan berurutan dan saling berdekatan dalam satu blok memori, lengkap dengan penanda kecil di depannya yang menunjukkan panjang data tersebut.

Pendekatan ini menghilangkan ruang kosong yang terbuang akibat perbedaan ukuran jenis data, sekaligus membuat data tersimpan berdekatan sehingga lebih cepat diakses. Sebagian besar jenis catatan bahkan bisa langsung disalin ke dalam jawaban yang dikirim ke pengguna tanpa perlu diproses ulang terlebih dahulu, karena sudah berada dalam format yang siap pakai. Hanya jenis catatan tertentu yang melibatkan nama domain yang masih memerlukan sedikit pemrosesan tambahan.
Perubahan ini saja meningkatkan kecepatan pencarian data di cache sebesar 5%, dan kecepatan penyimpanan data baru sebesar 13%.
Hasil Akhir: Lebih Hemat dan Lebih Cepat
Setelah kelima perubahan ini diterapkan secara bertahap ke seluruh server produksi antara 18 Mei hingga 6 Juli 2026, penggunaan memori di seluruh server turun secara signifikan di semua level pengukuran.

Pada level penggunaan tertinggi, memori per server turun dari 9,3 GB menjadi 5,3 GB — penurunan sebesar 43%.
| Metrik | Sebelum | Sesudah | Perubahan |
|---|---|---|---|
| Ukuran bersih per entri | 953 byte | 420 byte | -56% |
| Alokasi memori per entri | 1,1 KB | 461 byte | -58% |
| Kecepatan penyimpanan data | 625.000 entri/detik | 893.000 entri/detik | +43% |
| Waktu pencarian data | 828 nanodetik | 670 nanodetik | -19% |
Secara keseluruhan, penghematan ini membebaskan sekitar 100 terabyte memori di seluruh jaringan server Cloudflare. Memori yang dibebaskan ini rencananya akan digunakan kembali untuk memperbesar kapasitas cache tanpa perlu menambah penggunaan memori secara keseluruhan — yang pada akhirnya akan meningkatkan kemungkinan sebuah jawaban DNS sudah tersedia di cache, sehingga mengurangi jumlah permintaan yang perlu diteruskan ke server otoritatif lain.
Kenapa Ini Relevan bagi Pemilik Website
Bagi pemilik website, proses pencarian DNS adalah salah satu langkah pertama yang terjadi setiap kali seseorang mengunjungi situs mereka — sebelum halaman apa pun mulai dimuat. Semakin efisien dan cepat proses ini berjalan di sisi penyedia layanan DNS, semakin cepat pula pengalaman awal yang dirasakan pengunjung situs, terutama pada jaringan dengan variasi lokasi pengguna yang tinggi.
Efisiensi seperti ini juga berarti infrastruktur yang digunakan menjadi lebih stabil dan memiliki ruang lebih besar untuk terus berkembang seiring bertambahnya jumlah pengguna internet, tanpa harus terus-menerus menambah perangkat keras baru.
References
How we saved 100 terabytes of memory by optimizing 1.1.1.1’s DNS cache

