Image on Table #
Dalam banyak sistem—terutama pada tahap awal pengembangan atau tool internal—developer sering tergoda untuk menyimpan gambar langsung di dalam database, baik sebagai BLOB (Binary Large Object) maupun sebagai string Base64. Sekilas terlihat sederhana, tetapi pendekatan ini hampir selalu berujung pada masalah performa, skalabilitas, biaya, dan operasional.
Artikel ini membahas mengapa menyimpan gambar di database adalah ide buruk, perbandingan BLOB vs Base64, serta best practice yang digunakan pada sistem produksi modern.
Cara Umum Menyimpan Gambar di Database #
BLOB (Binary Large Object) #
Gambar disimpan sebagai data biner mentah di kolom database.
CREATE TABLE images (
id BIGINT PRIMARY KEY,
data BLOB
);
String Base64 #
Gambar dikonversi menjadi teks Base64 lalu disimpan di kolom TEXT atau VARCHAR.
{
"image": "iVBORw0KGgoAAAANSUhEUgAA..."
}
Keduanya terlihat praktis, namun keduanya memiliki banyak kekurangan serius.
Mengapa Menyimpan Gambar di Database Itu Buruk #
Performa Database Menurun Drastis #
Database dioptimalkan untuk:
- Data terstruktur
- Query dan indexing
- Transaksi
- Join
Database tidak dirancang untuk menangani payload biner besar.
Masalah yang sering muncul:
- Query menjadi lambat karena ukuran row membengkak
- Tekanan I/O dan memori meningkat
- Cache database terpolusi oleh data gambar
- Index scan menjadi jauh lebih berat
Jika melakukan SELECT tanpa fungsi LEFT() atau filter khusus, setiap query yang menarget row dengan data gambar akan membaca semua data BLOB/Base64. Akibatnya:
- Query sederhana terasa lambat
- Transfer data ke aplikasi membengkak
- Memory footprint meningkat drastis
Efek tambahan pada index yang sangat besar:
- Index menjadi kurang efektif karena row sangat besar
- Clustered index (di MySQL / MariaDB) atau heap (di PostgreSQL) harus menyimpan pointer ke data besar
- Scan index menjadi lebih lambat, terutama jika tabel memiliki jutaan row
- Query tanpa fungsi
LEFT()atauSELECTterbatas akan men-trigger full row read, mengakibatkan I/O tinggi dan latensi query meningkat drastis
Base64 membuat efek ini lebih buruk karena menambah ~33% ukuran data, sehingga query, transfer data, dan index scan semakin berat.
Backup dan Restore Menjadi Sangat Berat #
Data biner besar membuat ukuran backup database membengkak.
Konsekuensinya:
- Backup lebih lambat
- Restore jauh lebih lama
- Risiko tinggi saat disaster recovery
- Biaya storage backup meningkat
Dalam kasus nyata, restore database yang menyimpan gambar bisa memakan waktu berjam-jam lebih lama, memperpanjang downtime sistem.
Skalabilitas Menjadi Sangat Terbatas #
Database adalah komponen yang paling mahal dan paling sulit di-scale.
Jika gambar disimpan di dalam database:
- Vertical scaling dibutuhkan lebih cepat
- Traffic replikasi meningkat
- Read replica ikut terbebani
- Sharding menjadi jauh lebih kompleks
Padahal, beban akses gambar bersifat:
- Read-heavy
- Stateless
- Sangat cacheable
Semua ini adalah hal yang database tangani dengan sangat buruk.
Kehilangan Manfaat CDN dan HTTP Optimization #
Jika gambar berada di database:
- Sulit atau tidak bisa memakai CDN
- Tidak optimal menggunakan
Cache-Control,ETag - Tidak mendukung range request (partial download)
- Tidak bisa image optimization otomatis (resize, WebP, AVIF)
Akhirnya database Anda dipaksa menjadi image server yang mahal dan tidak efisien.
Coupling Transaksi Menjadi Berbahaya #
Menggabungkan penyimpanan gambar dengan data transaksional meningkatkan risiko:
- Update data gagal → upload gambar ikut rollback
- Upload gambar gagal → transaksi utama ikut gagal
- Upload besar menahan koneksi database terlalu lama
Hal ini memperbesar lock time dan blast radius kegagalan.
Kapan (Jarang) BLOB Masih Bisa Diterima? #
Ada beberapa kondisi terbatas di mana BLOB masih dapat diterima:
- File sangat kecil (ikon < 50 KB)
- Tool internal dengan traffic rendah
- Kebutuhan transaksional sangat kuat (misalnya dokumen terenkripsi yang harus konsisten)
- Data sementara (temporary / short-lived)
Bahkan pada kondisi ini, hindari Base64 sebisa mungkin.
Best Practice: Simpan Gambar di Luar Database #
Gunakan Object Storage #
Rekomendasi:
- Amazon S3
- Google Cloud Storage
- Azure Blob Storage
- MinIO (self-hosted)
Database hanya menyimpan metadata dan URL:
CREATE TABLE user_photos (
user_id BIGINT,
image_url TEXT,
content_type VARCHAR(50),
size_bytes BIGINT
);
Sajikan Gambar Melalui CDN #
Gunakan:
- CloudFront
- Cloudflare
- Fastly
Manfaat:
- Cache global
- Latensi rendah
- Beban backend berkurang
- Penghematan biaya signifikan
Alur Upload yang Direkomendasikan #
Alur terbaik:
- Client meminta izin upload
- Backend membuat pre-signed URL
- Client upload langsung ke object storage
- Backend menyimpan metadata + URL
Dengan ini, payload besar tidak pernah melewati server aplikasi dan database.
Gunakan Image Processing & Optimization #
Hindari menyimpan banyak versi gambar:
- Resize on-the-fly
- Konversi ke WebP / AVIF
- Lazy loading
Tools populer:
- Cloudinary
- Imgix
- Thumbor
- AWS Lambda + Sharp
Ringkasan Anti-Pattern #
- Jangan simpan gambar sebagai Base64 di database
- Jangan simpan BLOB besar di tabel transaksional
- Jangan serve gambar lewat query database
- Backup & replikasi database penuh file
Query
SELECTlangsung tanpa fungsiLEFT()untuk tabel besar dengan BLOB/Base64 akan:
- Membaca semua data biner
- Membebani memori dan I/O
- Membuat index lebih lambat karena row sangat besar
- Jika row besar dan index ikut menyimpan pointer, query yang hanya butuh field lain tetap memicu overhead tinggi
- Penggunaan Base64 menambah overhead ~33% sehingga efisiensi index semakin berkurang
Ringkasan Pola yang Direkomendasikan #
- Simpan gambar di object storage
- Database hanya menyimpan URL dan metadata
- Gunakan CDN untuk delivery
- Gunakan pre-signed upload
- Optimasi format dan caching
Aturan Emas Terakhir #
Database untuk data, object storage untuk file, CDN untuk delivery.
Jika setiap komponen digunakan sesuai fungsinya, sistem Anda akan:
- Lebih cepat
- Lebih murah
- Lebih mudah di-scale
- Lebih mudah dioperasikan
Jika suatu hari Anda tergoda menyimpan gambar di database, berhentilah sejenak dan tanyakan:
“Apakah saya sedang menyelesaikan masalah kemudahan hari ini atau menciptakan masalah skalabilitas besok?”
Hampir selalu, jawabannya sudah jelas.