Sering Kena Limit Max Connection PostgreSQL? Pasang PgBouncer Dulu untuk Database Anda

Pernahkah website atau aplikasi Anda tiba-tiba lumpuh saat sedang ramai pengunjung, dan log sistem Anda menampilkan pesan seperti ini?

FATAL: sorry, too many clients already

Bagi pengguna database PostgreSQL, error batas maksimal koneksi (Max Connections) adalah salah satu masalah yang paling sering terjadi. Banyak orang mengambil “jalan pintas” dengan cara masuk ke konfigurasi dan menaikkan batas limit max_connections menjadi 500 atau 1000.

Namun, cara tersebut sangat berbahaya dan berisiko membuat server Anda mati total. Mengapa demikian? Dan apa solusi terbaiknya? Mari kita bahas tuntas di artikel ini.

Bahaya Mengubah Limit max_connections Sembarangan

Berbeda dengan MySQL/MariaDB yang menggunakan sistem Thread (yang sangat ringan), arsitektur PostgreSQL merespon setiap koneksi yang masuk dengan melahirkan satu buah Proses sistem operasi yang mandiri.

Satu proses koneksi PostgreSQL membutuhkan RAM sekitar 5 MB hingga 10 MB. Jika Anda menaikkan limit hingga 500 koneksi, Anda memaksa server untuk selalu menyiapkan RAM kosong sebesar 2.5 GB hingga 5 GB HANYA untuk menjaga koneksi (belum termasuk kebutuhan RAM untuk OS dan proses perhitungan query).

Saat RAM server Anda habis, fitur OOM-Killer (Out of Memory) pada sistem Linux akan otomatis aktif dan mematikan servis PostgreSQL Anda secara paksa. Hasilnya? Website Anda akan down total.

Apa Itu PgBouncer?

Solusi paling aman atau best practice untuk mengatasi masalah ini bukanlah dengan menambah RAM server, melainkan dengan menggunakan PgBouncer. PgBouncer adalah aplikasi connection pooler (pengelola antrean koneksi) yang sangat ringan khusus untuk PostgreSQL.

Secara teknis, PostgreSQL memakan cukup banyak RAM untuk setiap koneksi yang masuk. Jika ada 1.000 koneksi dari aplikasi yang masuk secara bersamaan, server database bisa kehabisan memori dan berujung crash. Di sinilah PgBouncer bekerja sebagai connection pooler. Alih-alih membiarkan ribuan koneksi tersebut langsung membebani PostgreSQL, PgBouncer menampungnya terlebih dahulu. Ia hanya membuka sedikit koneksi aktif ke database misalnya 20 koneksi saja lalu menggilir 1.000 permintaan dari aplikasi tadi untuk menggunakan 20 koneksi tersebut dalam hitungan milidetik. Hasilnya, performa aplikasi tetap cepat dan server database tidak tumbang.

Aplikasi tetap lancar menerima ribuan pengunjung, sementara pemakaian RAM server tetap awet dan stabil!

Tutorial Install PgBouncer (Skenario Remote Database)

Untuk membuktikan keandalannya, disini kita akan membuat skenario yang memisahkan web server dan database server:

  • Aplikasi Web (PHP): Berada di layanan Hosting (misalnya cPanel).
  • Database Server: Berada di Cloud VPS Linux tersendiri (menggunakan Ubuntu/Debian).

Disini kita asumsikan anda sudah menginstal PostgreSQL di VPS Anda dan sudah dapat diakses dari luar (listen_addresses = '*' pada file postgresql.conf).

Berikut adalah panduan instalasi PgBouncer di server VPS Anda:

Install Aplikasi PgBouncer

Login ke SSH VPS Anda sebagai root, lalu jalankan perintah berikut:

apt update
apt install pgbouncer -y

(Catatan: Jika Anda menggunakan AlmaLinux/CentOS, gunakan perintah dnf install pgbouncer -y).

Tarik Data User & Password PostgreSQL

PgBouncer membutuhkan daftar username dan password agar bisa memvalidasi pengunjung yang ingin login ke database. Gunakan perintah berikut untuk menyalin password dari PostgreSQL ke PgBouncer:

su - postgres -c "psql -Atq" <<EOF > /etc/pgbouncer/userlist.txt
SELECT '"' || usename || '" "' || passwd || '"' FROM pg_shadow;
EOF

Cek hasilnya dengan mengetik cat /etc/pgbouncer/userlist.txt. Jika sukses, Anda akan melihat username Anda diikuti dengan kode hash password (MD5/SCRAM).

Konfigurasi PgBouncer

Buka file konfigurasi PgBouncer menggunakan text editor:

nano /etc/pgbouncer/pgbouncer.ini

Ubah atau pastikan parameter di bawah ini sesuai:

[databases]
* = host=127.0.0.1 port=5432

[pgbouncer]
# Port baru untuk PgBouncer (Ini yang akan dipakai oleh website)
listen_port = 6432
listen_addr = *

# Metode otentikasi
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt

pool_mode = transaction

# Batas maksimal antrean yang bisa ditampung PgBouncer dari web
max_client_conn = 1000
# Jumlah jalur asli ke Postgres yang akan dipinjam-gantikan
default_pool_size = 20

Simpan file tersebut (Ctrl+X, lalu Y, dan Enter).

Buka Port di Firewall VPS

Agar website di hosting bisa menghubungi PgBouncer di VPS, jangan lupa buka port 6432 di firewall VPS Anda.

Terkadang jika web anda berada di hosting, kalian juga perlu meminta provider hosting untuk membuka outgoing port tersebut.

ufw allow 6432/tcp
ufw reload

Jalankan Service PgBouncer

Terakhir, restart service PgBouncer agar pengaturan baru Anda berjalan:

systemctl enable --now pgbouncer
systemctl restart pgbouncer

Pengujian dan Langkah Akhir

Setelah PgBouncer aktif di server VPS Anda, langkah terakhir adalah mengubah kode atau konfigurasi di website Anda. Jika sebelumnya website Anda (seperti Laravel, CodeIgniter, atau PHP Native) terhubung ke database menggunakan port 5432, ubahlah port tersebut menjadi 6432. Dengan perubahan kecil ini, seluruh lalu lintas database website Anda kini sudah dijaga oleh PgBouncer. Meskipun ada ratusan atau ribuan koneksi masuk secara bersamaan, server PostgreSQL Anda tidak akan lagi tumbang terkena serangan max connections!

Sebagai pengujian, disini kita membuat script sederhana untuk membuat koneksi yang cukup banyak ke postgresql dan pgbouncer untuk melihat perbedaannya

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$host     = "103.180.165.143";
$port     = "5432";
$dbname   = "db_test";
$user     = "user_test";
$password = "Rahasia123!";

$conn_string = "host=$host port=$port dbname=$dbname user=$user password=$password";
$jumlah_test = 500; 
$berhasil = 0;

$koneksi_aktif = array(); 

echo "<h2>Memulai Stress Test ke Port $port...</h2>";

if (!function_exists('pg_connect')) {
    die("<h3 style='color:red;'>ERROR: Fungsi pg_connect() tidak ditemukan!</h3>");
}

for ($i = 1; $i <= $jumlah_test; $i++) {
    $conn = @pg_connect($conn_string, PGSQL_CONNECT_FORCE_NEW); 
    
    if ($conn) {
        $berhasil++;
        $koneksi_aktif[] = $conn; 
    } else {
        $error_msg = error_get_last()['message'] ?? 'Koneksi Ditolak oleh Server';
        echo "<br><b style='color:red;'>Koneksi ke-$i GAGAL! Alasan: $error_msg</b><br>";
        break;
    }
}

echo "<h3>Hasil Akhir: $berhasil koneksi berhasil dibuka SECARA BERSAMAAN.</h3>";
?>

Karena maksimal koneksi postgresql kita set 100, maka koneksi ke 98 dan seterusnya di tolak oleh postgresql.

Sekarang kita ubah portnya menjadi milik Pgbouncer (6432), dan hasilnya koneksi web ke postgresql berhasil ditangani dan berjalan dengan lancar

Kesimpulan

Mengatasi error ‘max connections’ pada PostgreSQL dengan cara sekadar menaikkan limit konfigurasi adalah jalan pintas yang sangat berisiko. Alih-alih menyelesaikan masalah, hal tersebut justru dapat menguras kapasitas RAM dan memicu sistem operasi untuk mematikan server secara paksa (OOM Killer).

Solusi best practice yang terbukti paling aman dan efisien adalah menggunakan PgBouncer sebagai connection pooler. Dengan PgBouncer, ribuan koneksi dari website dapat ditampung secara antre dan didistribusikan secara cerdas ke dalam beberapa slot database saja. Hasilnya, performa server tetap stabil, RAM lebih hemat, dan website Anda bebas dari downtime mendadak meskipun sedang diserbu traffic tinggi.

Leave a Reply

Your email address will not be published. Required fields are marked *