🎁
Bonus Top-up 50%!Promo Terbatas
Upvote
postgresqldatabasehelipoddeploymentbackend

Deploy PostgreSQL di Helipod: Database Production-Ready dalam Menit

Tim Helipod

7 menit baca

Panduan lengkap setup PostgreSQL di Helipod — dari deploy service, koneksi via internal network, konfigurasi persistent storage, backup, sampai optimasi untuk production.

Hampir setiap aplikasi web butuh database. Dan PostgreSQL adalah pilihan terbaik untuk sebagian besar use case: reliable, feature-rich, performa tinggi, dan open source.

Di Helipod, deploy PostgreSQL semudah menambahkan service baru di canvas — tidak perlu konfigurasi manual, tidak perlu setup user dan permission dari nol, dan database langsung terhubung ke aplikasimu via internal network.

Cara Deploy PostgreSQL

Langkah 1: Tambah Service PostgreSQL

Di canvas dashboard Helipod:

  1. Klik tombol + untuk menambah service baru
  2. Pilih PostgreSQL dari daftar template
  3. Beri nama service — misalnya postgres atau db
  4. Klik Deploy

Helipod akan menjalankan container PostgreSQL dengan konfigurasi default yang sudah production-ready.

Langkah 2: Lihat Kredensial

Setelah PostgreSQL running, buka tab Variables pada service PostgreSQL. Kamu akan melihat:

POSTGRES_DB=mydb
POSTGRES_USER=postgres
POSTGRES_PASSWORD=auto-generated-password
DATABASE_URL=postgresql://postgres:password@postgres:5432/mydb

Catat nilai-nilai ini untuk dipakai di service aplikasimu.

Langkah 3: Hubungkan ke Aplikasi

Di service aplikasi (Laravel, Django, NestJS, dll), buka tab Variables dan tambahkan:

Laravel:

DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=mydb
DB_USERNAME=postgres
DB_PASSWORD=auto-generated-password

Django / FastAPI / Flask:

DATABASE_URL=postgresql://postgres:password@postgres:5432/mydb

NestJS (TypeORM):

DB_HOST=postgres
DB_PORT=5432
DB_NAME=mydb
DB_USER=postgres
DB_PASSWORD=auto-generated-password

postgres di DB_HOST adalah nama service yang kamu beri saat membuat PostgreSQL di canvas. Ini langsung bisa dipakai sebagai hostname karena semua service dalam satu project terhubung via internal network.

Setup Persistent Volume untuk PostgreSQL

Ini langkah yang paling penting dan sering terlupakan.

Secara default, data PostgreSQL disimpan di ephemeral storage container — artinya semua data akan hilang jika container di-restart atau redeploy.

Untuk production, kamu wajib mount persistent volume:

  1. Buka service PostgreSQL → tab Settings
  2. Scroll ke Storage Volumes → Add Volume
  3. Isi:
    • Mount Path: /var/lib/postgresql/data
    • Size: 10GB (atau lebih sesuai kebutuhan)
  4. Klik Save

Atau via helipack.json (jika PostgreSQL dari custom image):

{
  "volume": {
    "mountPath": "/var/lib/postgresql/data",
    "size": 20
  }
}

Setelah volume di-mount, data PostgreSQL akan persist meski container di-restart atau di-redeploy.

⚠️ Warning: Jika kamu menambahkan volume setelah PostgreSQL sudah berjalan dan ada data, pastikan path mount benar. Mount ke path yang salah bisa menyebabkan PostgreSQL tidak bisa start (karena menemukan direktori kosong alih-alih data directory yang sudah ada).

Konfigurasi Database Pertama Kali

Setelah PostgreSQL running dan persistent volume terpasang, setup database dari terminal:

Akses psql dari Terminal Aplikasi

Buka terminal di service aplikasi (bukan PostgreSQL) dan jalankan:

# Test koneksi
psql $DATABASE_URL -c "SELECT version();"

# Atau dengan individual params
psql -h postgres -U postgres -d mydb

# List semua database
psql -h postgres -U postgres -l

# Buat database baru
createdb -h postgres -U postgres newdatabase

# Buat user baru
psql -h postgres -U postgres -c "CREATE USER myuser WITH PASSWORD 'mypassword';"
psql -h postgres -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;"

Atau Akses dari Terminal PostgreSQL langsung

Buka tab Terminal pada service PostgreSQL:

# Masuk ke psql
psql -U postgres

# Perintah psql yang berguna
\l                    -- list databases
\c mydb               -- connect ke database
\dt                   -- list tables
\d tablename          -- describe table
\du                   -- list users
\q                    -- quit

Jalankan Migrasi

Setelah database siap, jalankan migrasi dari terminal service aplikasi:

Laravel:

php artisan migrate --force
php artisan migrate:status

Django:

python manage.py migrate
python manage.py showmigrations

NestJS + TypeORM:

npx typeorm migration:run -d dist/data-source.js

NestJS + Prisma:

npx prisma migrate deploy
npx prisma db seed  # opsional, untuk seed data

FastAPI + Alembic:

alembic upgrade head

Otomasi via helipack.json

Agar migrasi berjalan otomatis setiap deploy:

{
  "run": {
    "before": "php artisan migrate --force"
  }
}

Konfigurasi PostgreSQL untuk Production

PostgreSQL default sudah cukup untuk kebanyakan use case. Tapi untuk optimasi lebih lanjut, kamu bisa override konfigurasi via environment variable di service PostgreSQL:

# Jumlah max connections
POSTGRES_MAX_CONNECTIONS=100

# Shared buffers (25% dari RAM yang tersedia)
# Untuk pod 1GB RAM:
POSTGRES_SHARED_BUFFERS=256MB

# Effective cache size (50-75% dari RAM)
POSTGRES_EFFECTIVE_CACHE_SIZE=512MB

# Work memory per sort operation
POSTGRES_WORK_MEM=4MB

# Maintenance work memory
POSTGRES_MAINTENANCE_WORK_MEM=64MB

Atau mount custom postgresql.conf sebagai Secret File.

Connection Pooling

Jika aplikasimu menjalankan banyak proses (gunicorn workers, replicas), setiap proses akan membuka koneksi ke PostgreSQL. Dengan max_connections=100 default, ini bisa menjadi bottleneck.

PgBouncer sebagai Connection Pooler

Deploy PgBouncer sebagai pod terpisah:

  1. Tambah service baru di canvas dengan Docker image pgbouncer/pgbouncer
  2. Beri nama pgbouncer
  3. Set environment variables:
DATABASE_URL=postgresql://postgres:password@postgres:5432/mydb
POOL_MODE=transaction
MAX_CLIENT_CONN=100
DEFAULT_POOL_SIZE=20
  1. Di service aplikasi, ubah DB_HOST dari postgres ke pgbouncer

Dengan PgBouncer, ratusan koneksi dari aplikasi akan di-multiplex menjadi puluhan koneksi aktual ke PostgreSQL — jauh lebih efisien.

Connection Pool di ORM

Sebagai alternatif PgBouncer, konfigurasi connection pool di ORM:

Laravel (config/database.php):

'pgsql' => [
    'driver' => 'pgsql',
    'host' => env('DB_HOST'),
    // ...
    'options' => [
        PDO::ATTR_PERSISTENT => true,
    ],
    'pool' => [
        'min' => 2,
        'max' => 10,
    ],
],

SQLAlchemy (Python):

engine = create_async_engine(
    os.environ['DATABASE_URL'],
    pool_size=10,           # koneksi yang selalu ada
    max_overflow=20,        # koneksi extra saat load tinggi
    pool_timeout=30,        # waktu tunggu dapat koneksi (detik)
    pool_recycle=3600,      # recycle koneksi tiap 1 jam
)

TypeORM (NestJS):

TypeOrmModule.forRoot({
  type: 'postgres',
  // ...
  extra: {
    max: 10,           // max pool size
    min: 2,            // min pool size
    idleTimeoutMillis: 30000,
  },
})

Backup PostgreSQL

Helipod belum menyediakan managed backup otomatis. Setup backup manual:

Backup via pg_dump dari Terminal

# Dari terminal service aplikasi
pg_dump $DATABASE_URL | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz

# Upload ke object storage
# Dengan AWS CLI (untuk S3/DO Spaces/R2):
aws s3 cp backup_*.sql.gz s3://mybucket/postgres-backups/ \
  --endpoint-url https://xxx.r2.cloudflarestorage.com

Cron Backup Otomatis

Deploy pod terpisah sebagai backup worker dengan schedule:

{
  "run": {
    "command": "sh -c 'while true; do pg_dump $DATABASE_URL | gzip | aws s3 cp - s3://mybucket/backup_$(date +%Y%m%d).sql.gz; sleep 86400; done'"
  }
}

Restore dari Backup

# Restore ke database
gunzip -c backup_20260515.sql.gz | psql $DATABASE_URL

# Atau ke database baru
createdb -h postgres -U postgres newdb
gunzip -c backup_20260515.sql.gz | psql -h postgres -U postgres newdb

Monitoring PostgreSQL

Dari terminal service PostgreSQL atau aplikasi:

-- Cek koneksi aktif
SELECT count(*), state 
FROM pg_stat_activity 
GROUP BY state;

-- Cek query yang sedang berjalan
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC;

-- Cek ukuran database
SELECT pg_size_pretty(pg_database_size('mydb'));

-- Cek ukuran tabel terbesar
SELECT relname, pg_size_pretty(pg_total_relation_size(relid))
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

-- Cek index yang tidak pernah dipakai
SELECT relname, indexrelname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY relname;

Scaling PostgreSQL

Untuk PostgreSQL di Helipod, scale via Settings → Scaling & Resources:

RAM lebih penting dari CPU untuk database:

  • 512MB RAM — aplikasi kecil, <10 concurrent users
  • 1GB RAM — aplikasi medium, 10–100 concurrent users
  • 2GB RAM — aplikasi production, 100–1000 concurrent users
  • 4GB+ RAM — high-traffic production

PostgreSQL menggunakan RAM untuk shared_buffers (cache data) dan work_mem (sorting/joining). Lebih banyak RAM = lebih banyak data di-cache = query lebih cepat.

Catatan: PostgreSQL tidak bisa di-horizontal scale dengan cara biasa (tidak bisa multiple replicas yang semuanya write). Untuk read scaling, setup read replica secara manual.

Troubleshooting

"FATAL: role 'myuser' does not exist" Buat user dari psql: CREATE USER myuser WITH PASSWORD 'password';

"Connection refused" dari aplikasi Pastikan nama DB_HOST sama dengan nama service PostgreSQL di canvas. Cek dari terminal aplikasi: nc -zv postgres 5432.

"Too many connections" Implementasikan connection pooling (PgBouncer atau pool di ORM). Atau naikkan max_connections di konfigurasi PostgreSQL.

Data hilang setelah restart Persistent volume belum di-setup! Tambahkan volume mount ke /var/lib/postgresql/data segera.

"directory is not empty" saat pertama kali Ini terjadi jika kamu mount volume ke PostgreSQL yang sudah running. Coba reset volume atau pastikan directory kosong sebelum pertama kali mount.

Kesimpulan

PostgreSQL di Helipod bisa running dalam hitungan menit dengan konfigurasi yang sudah production-ready. Yang terpenting: selalu mount persistent volume ke /var/lib/postgresql/data sebelum mulai memasukkan data production.

Untuk koneksi dari aplikasi ke PostgreSQL, gunakan nama service sebagai hostname — tidak perlu IP, tidak perlu konfigurasi networking tambahan.

Ingin tahu cara koneksi multi-service di Helipod? Baca Internal Network Helipod.

Punya pertanyaan? Hubungi kami di support@helipod.id atau bergabung ke komunitas di hangar.helipod.io.

Siap coba Helipod?

Deploy aplikasi kamu sekarang. Gratis, tanpa kartu kredit.

Mulai Gratis →