PostgreSQL’s JSONB sering menjadi pilihan utama para pengembang berkat fleksibilitasnya, tetapi kolom ini menyimpan rahasia gelap yang bisa menggerogoti performa. Ketika JSONB disimpan secara inline di dalam baris yang ukurannya kurang dari 2 KB, setiap baris bisa membengkak dari ~80 byte menjadi 200‟400 byte, sehingga jumlah baris per halaman 8 KB turun drastis dari sekitar 100 menjadi hanya 20‟40. Hal ini memaksa server untuk membaca lebih banyak halaman, meningkatkan I/O fisik, dan pada akhirnya memperlambat bahkan kueri yang menggunakan indeks.
Misalnya, tabel `events` dengan kolom `metadata jsonb` yang menyimpan objek kecil seperti `{ "ip": "127.0.0.1", "device": "Android", "country": "IN" }` akan mengalami peningkatan ukuran baris yang signifikan. Meskipun indeks GIN atau B‟Tree dibangun pada kunci JSONB (misalnya `CREATE INDEX ON events ((metadata->>'ip'))`), PostgreSQL tetap harus mengambil seluruh baris dari disk untuk setiap baris yang cocok. Karena JSONB disimpan inline, mesin harus memindai banyak halaman, sehingga indeks tidak bisa sepenuhnya menghindari biaya I/O tambahan.
Dampak nyata terlihat pada benchmark yang membandingkan waktu respons kueri sebelum dan sesudah penambahan kolom JSONB inline. Bahkan pada set data kecil, waktu eksekusi bisa meningkat dua hingga tiga kali lipat, terutama pada workload dengan lalu lintas read‟heavy. Para praktisi berpendapat bahwa masalah ini sering kali tidak terdeteksi hingga terjadi degradasi yang signifikan pada layanan produksi.
Untungnya, ada beberapa strategi mitigasi yang bisa diterapkan. Opsi pertama adalah memaksa TOAST dengan membuat ukuran JSONB melebihi 2 KB, misalnya dengan menambahkan padding besar: `UPDATE events SET metadata = metadata || jsonb_build_object('padding', repeat('x', 2000))`. Cara ini membuat PostgreSQL menyimpan JSONB di tabel TOAST terpisah, sehingga baris asli tetap ramping. Alternatif lain adalah memisahkan data JSONB ke dalam tabel terpisah jika kolom tersebut jarang diakses secara langsung, sehingga skema utama tetap efisien. Bagi many startup, pilihan terbaik seringkali adalah kembali ke kolom dengan tipe data terdefinisi dengan baik (JSONB hanya untuk edge cases) untuk menjaga performa tetap optimal.
Secara keseluruhan, artikel ini menekankan bahwa fleksibilitas JSONB tidak boleh mengorbankan performa dasar. Pemahaman mendalam tentang cara PostgreSQL mengelola penyimpanan inline versus TOAST sangat penting bagi arsitek basis data yang ingin membangun sistem yang skalabel, terutama di lingkungan cloud‑native yang kompetitif saat ini. Dengan menyadari dampak tersembunyi ini, tim dapat merancang skema yang seimbang antara fleksibilitas dan efisiensi, sehingga menghindari penurunan kinerja yang tidak terduga.
Bagi pengembang di Indonesia yang mengadopsi PostgreSQL untuk produk SaaS atau analitik, pelajaran ini sangat relevan. Banyak startup lokal masih mengandalkan PostgreSQL untuk operasional mereka, dan penurunan performa yang tidak terdeteksi bisa berdampak langsung pada pengalaman pengguna dan biaya infrastruktur. Oleh karena itu, memantau ukuran baris dan memanfaatkan TOAST secara proaktif harus menjadi bagian dari praktik DevOps sehari‟hari.
Sumber lengkap, diagram, dan kode benchmark tersedia di GitLab: rohit yadav / Postgres‟JsonB‟Performance.