Database Connection Pool: Konsep, Masalah Umum, dan Best Practice (Contoh Golang + GORM)
4 min read

Database Connection Pool: Konsep, Masalah Umum, dan Best Practice (Contoh Golang + GORM)

Dalam aplikasi backend modern, database connection pool adalah salah satu komponen paling krusial—namun sering diremehkan. Banyak masalah performa, latency tinggi, bahkan outage di production bukan karena query lambat, tapi karena connection pool yang salah konfigurasi.

Artikel ini akan membahas:

  • Apa itu connection pool (secara realistis, bukan textbook)
  • Masalah umum jika tidak disetel dengan benar
  • Cara kerja connection pool di Go
  • Contoh implementasi Golang + GORM
  • Best practice: max open connection, max idle connection, max idle timeout, dll
  • Rekomendasi angka + cara berpikirnya

Apa Itu Database Connection Pool?

Secara sederhana:

Connection pool adalah sekumpulan koneksi database yang dipertahankan dan digunakan ulang oleh aplikasi.

Tanpa pool:

  • Setiap request → buka koneksi baru
  • Query selesai → koneksi ditutup
  • Overhead besar (TCP, TLS, auth, dsb)

Dengan pool:

  • Koneksi dibuat di awal
  • Disimpan di pool
  • Dipakai ulang oleh banyak request

Kenyataan di Production

  • Koneksi database itu mahal
  • Database punya limit koneksi
  • Terlalu banyak koneksi = database overload
  • Terlalu sedikit koneksi = request antre (latency naik)

Connection pool adalah alat untuk mengontrol tekanan ke database.


Masalah Umum Tanpa / Salah Konfigurasi Connection Pool

Default Setting (Paling Berbahaya)

Banyak engineer berpikir:

“Kan sudah pakai GORM / database/sql, pasti aman.”

Faktanya:

  • Default MaxOpenConns = 0unlimited
  • Default MaxIdleConns = 2
  • Default timeout → tidak jelas

Akibatnya:

  • Traffic spike → ribuan koneksi
  • Database kehabisan resource
  • Aplikasi terlihat “random timeout”

Max Connection Terlalu Besar

Contoh:

  • DB limit: 100 connections
  • Aplikasi punya 5 pod
  • Set MaxOpenConns = 50

Total:

5 × 50 = 250 connections

Database langsung sekarat.

Max Connection Terlalu Kecil

Kebalikannya:

  • Banyak goroutine
  • Semua menunggu koneksi
  • CPU idle tapi latency tinggi

Ini sering terjadi di Go karena goroutine murah, tapi DB connection tidak murah.


Cara Kerja Connection Pool di Go

Di Go:

  • Connection pool dikelola oleh database/sql
  • GORM hanya membungkusnya
  • Semua setting pool dilakukan di sql.DB

Alurnya:

GORM → database/sql → actual DB connection

Artinya:

Kalau kamu pakai GORM, tetap wajib mengatur connection pool secara eksplisit.


Contoh Implementasi Golang + GORM

Setup Database

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
    log.Fatal(err)
}

Ambil *sql.DB dari GORM:

sqlDB, err := db.DB()
if err != nil {
    log.Fatal(err)
}

Konfigurasi Connection Pool (WAJIB)

Max Open Connections

sqlDB.SetMaxOpenConns(20)

Artinya:

  • Maksimal 20 koneksi aktif ke database
  • Jika habis → request akan menunggu

Best Practice:

  • Jangan pakai angka besar tanpa alasan

  • Hitung berdasarkan:

    • DB max connections
    • Jumlah instance aplikasi

Max Idle Connections

sqlDB.SetMaxIdleConns(10)

Artinya:

  • Koneksi yang menganggur tapi tetap disimpan
  • Menghindari overhead buka koneksi baru

Best Practice:

  • Biasanya 50–75% dari MaxOpenConns
  • Jangan lebih besar dari MaxOpenConns

Connection Max Lifetime

sqlDB.SetConnMaxLifetime(30 * time.Minute)

Artinya:

  • Koneksi akan dipaksa ditutup setelah waktu tertentu

  • Mencegah:

    • Koneksi “tua”
    • Masalah network
    • Load balancer timeout

Best Practice:

  • 15–60 menit
  • Lebih kecil dari idle timeout di database / proxy

Connection Max Idle Time (Go ≥ 1.15)

sqlDB.SetConnMaxIdleTime(10 * time.Minute)

Artinya:

  • Jika koneksi idle terlalu lama → ditutup
  • Menghemat resource

Best Practice:

  • 5–15 menit
  • Cocok untuk traffic tidak stabil

Contoh Konfigurasi Ideal (Umum)

Untuk 1 service instance:

sqlDB.SetMaxOpenConns(20)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(30 * time.Minute)
sqlDB.SetConnMaxIdleTime(10 * time.Minute)

Cara Menentukan Angka yang Benar

Lihat DB Limit

Misal:

Postgres max_connections = 100

Hitung Jumlah Instance

Misal:

5 pods

Bagi Secara Aman

100 / 5 = 20

➡️ MaxOpenConns = 20

Sisakan buffer untuk:

  • Migration
  • Admin
  • Background job

Sesuaikan dengan Traffic

  • Query cepat → bisa lebih kecil
  • Query berat / lama → jangan kebanyakan

Anti-Pattern yang Harus Dihindari

  1. Tidak set connection pool sama sekali ❌
  2. Set MaxOpenConns terlalu besar “biar aman” ❌
  3. Menganggap database bisa autoscale seperti aplikasi ❌
  4. Menggunakan satu database untuk terlalu banyak service tanpa perhitungan ❌

Observability: Jangan Blind

Wajib monitor:

  • Active connections
  • Idle connections
  • Wait time (connection wait)

Jika:

  • CPU rendah
  • Latency tinggi
  • Banyak goroutine blocked

➡️ besar kemungkinan bottleneck di connection pool


Kesimpulan

Database connection pool bukan detail kecil, tapi bagian dari arsitektur sistem.

Di Go:

  • Goroutine murah
  • Connection database mahal

Tanpa konfigurasi pool yang benar:

  • Aplikasi terlihat scalable
  • Database jadi single point of failure

Dengan connection pool yang tepat:

  • Sistem stabil
  • Latency konsisten
  • Database lebih awet di production

Rule of thumb: Lebih baik request menunggu koneksi daripada database mati.