Skip to main content

Database Connection

Dokumentasi koneksi database PostgreSQL dengan GORM.

Overview

Package infra/database menangani koneksi ke PostgreSQL dengan support untuk:

  • Master-Replica configuration
  • Connection pooling
  • Query logging

Global Variables

var (
DB *gorm.DB
err error
)

Functions

DbConnection

Membuat koneksi database dengan master dan replica.

func DbConnection(masterDSN, replicaDSN string) error

Parameters

ParameterTypeDeskripsi
masterDSNstringData Source Name untuk master database
replicaDSNstringData Source Name untuk replica database

DSN Format

host=localhost user=postgres password=secret dbname=sisappra port=5432 sslmode=disable

GetDB

Mendapatkan instance database connection.

func GetDB() *gorm.DB

Implementation

func DbConnection(masterDSN, replicaDSN string) error {
logMode := viper.GetBool("DB_LOG_MODE")
debug := viper.GetBool("DEBUG")

loglevel := logger.Silent
if logMode {
loglevel = logger.Info
}

// Connect to master
db, err = gorm.Open(postgres.Open(masterDSN), &gorm.Config{
Logger: logger.Default.LogMode(loglevel),
})

// Setup replica (only in production)
if !debug {
db.Use(dbresolver.Register(dbresolver.Config{
Replicas: []gorm.Dialector{
postgres.Open(replicaDSN),
},
Policy: dbresolver.RandomPolicy{},
}))
}

if err != nil {
log.Fatalf("Db connection error")
return err
}

DB = db
return nil
}

Master-Replica Architecture

┌─────────────────────────────────────────────────────────────┐
│ APPLICATION │
│ │
│ ┌─────────────────┐ │
│ │ GORM │ │
│ │ DB Resolver │ │
│ └────────┬────────┘ │
│ │ │
│ ┌──────────────┼──────────────┐ │
│ │ │ │ │
│ ▼ │ ▼ │
│ ┌─────────────────┐ │ ┌─────────────────┐ │
│ │ MASTER │ │ │ REPLICA │ │
│ │ (Read/Write) │ │ │ (Read Only) │ │
│ └─────────────────┘ │ └─────────────────┘ │
│ │ │
└────────────────────────────┼────────────────────────────────┘

┌─────────┴─────────┐
│ Automatic │
│ Routing: │
│ - Write → Master│
│ - Read → Replica│
└───────────────────┘

Configuration

Environment Variables

VariableTypeDefaultDeskripsi
DB_LOG_MODEboolfalseEnable SQL query logging
DEBUGboolfalseDebug mode (skip replica)

Database DSN Variables

Master:

  • MASTER_DB_HOST
  • MASTER_DB_PORT
  • MASTER_DB_NAME
  • MASTER_DB_USER
  • MASTER_DB_PASSWORD
  • MASTER_SSL_MODE

Replica:

  • REPLICA_DB_HOST
  • REPLICA_DB_PORT
  • REPLICA_DB_NAME
  • REPLICA_DB_USER
  • REPLICA_DB_PASSWORD
  • REPLICA_SSL_MODE

Usage

Initialize Connection

// In main.go
func main() {
config.SetupConfig()

masterDSN, replicaDSN := config.DbConfiguration()

if err := database.DbConnection(masterDSN, replicaDSN); err != nil {
log.Fatal("Failed to connect to database")
}

// ...
}

Use in Repository

package repository

import "api-gateway/infra/database"

func GetUsers() ([]models.User, error) {
var users []models.User
err := database.DB.Find(&users).Error
return users, err
}

Logging

Enable Query Logging

Set di .env:

DB_LOG_MODE=true

Log Output

2026/01/22 10:00:00 [info] [rows:1] SELECT * FROM "users" WHERE "id" = '123'

Connection Pooling

GORM secara otomatis mengelola connection pool. Untuk konfigurasi custom:

sqlDB, _ := db.DB()

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool
sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns sets the maximum number of open connections to the database
sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused
sqlDB.SetConnMaxLifetime(time.Hour)

Error Handling

if err := database.DbConnection(masterDSN, replicaDSN); err != nil {
switch {
case strings.Contains(err.Error(), "connection refused"):
log.Fatal("Database server is not running")
case strings.Contains(err.Error(), "authentication failed"):
log.Fatal("Invalid database credentials")
case strings.Contains(err.Error(), "does not exist"):
log.Fatal("Database does not exist")
default:
log.Fatalf("Database connection error: %v", err)
}
}

Best Practices

  1. Use Connection Pooling - Jangan buat koneksi baru setiap request
  2. Enable Logging di Development - Untuk debugging query
  3. Disable Logging di Production - Untuk performance
  4. Monitor Connection Pool - Pantau metrics koneksi
  5. Graceful Shutdown - Tutup koneksi saat aplikasi shutdown
    defer func() {
    sqlDB, _ := database.DB.DB()
    sqlDB.Close()
    }()