Database branching adalah fitur powerful, tapi tanpa best practices yang benar, bisa jadi masalah. Branch lama menumpuk, storage membengkak, dan performance menurun.
Artikel ini panduan lengkapnya.
1. Naming Convention yang Konsisten
Pattern yang Direkomendasikan
# Untuk environment
production → Database utama
staging → Testing sebelum production
development → Development lokal
# Untuk pull requests
pr-{number} → PR branches (otomatis)
pr-{number}-{slug} → PR dengan deskripsi
# Untuk feature branches
feature-{name} → Feature development
hotfix-{name} → Hotfix production
# Untuk experiments
experiment-{name} → Testing ide baru
Contoh Implementasi
# PR branches
pr-123
pr-123-add-payment
pr-124-fix-login-bug
# Feature branches
feature-new-checkout
feature-user-avatar
feature-notification
# Hotfix branches
hotfix-critical-bug
hotfix-security-patch
Hindari
# ❌ Jangan lakukan ini
test123
temporary branch
my-database-v2-final-FINAL
2. TTL (Time-to-Live) untuk Branches
Setup Auto-Cleanup
Konfigurasi auto-cleanup bisa dilakukan melalui dashboard Helipod:
- Buka Settings → Integrations → Neon
- Aktifkan Auto Cleanup
- Set TTL untuk setiap branch type:
- PR branches: 7 hari
- Feature branches: 30 hari
- Staging: Permanent
- Production: Permanent
Manual Cleanup
# Lihat semua branches
turso db branches list my-database
# Hapus branch lama
turso db branches delete my-database old-branch-name
# Hapus semua branches kecuali main dan staging
turso db branches list my-database | \
grep -v "main\|staging" | \
xargs -I {} turso db branches delete my-database {}
Cleanup via API
// Cleanup branches lebih dari 7 hari
async function cleanupOldBranches() {
const branches = await neon.listBranches();
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
for (const branch of branches) {
if (branch.created_at < sevenDaysAgo &&
!['main', 'staging'].includes(branch.name)) {
await neon.deleteBranch(branch.id);
console.log(`Deleted: ${branch.name}`);
}
}
}
3. Connection Pooling
Konfigurasi yang Benar
# ❌ Salah - tanpa pooling
DATABASE_URL=postgresql://user:pass@host/dbname
# ✅ Benar - dengan pooling
DATABASE_URL=postgresql://user:pass@host:5432/dbname?pgbouncer=true
# ✅ Benar - dengan connection limit
DATABASE_URL=postgresql://user:pass@host:5432/dbname?connection_limit=20
Konfigurasi per ORM
Prisma:
DATABASE_URL="postgresql://...?pgbouncer=true&connection_limit=20&pool_timeout=20"
Sequelize:
const sequelize = new Sequelize(database, username, password, {
dialect: 'postgres',
pool: {
max: 20,
min: 5,
acquire: 30000,
idle: 10000
}
});
TypeORM:
{
type: 'postgres',
url: process.env.DATABASE_URL,
extra: {
max: 20,
connectionTimeoutMillis: 20000,
}
}
4. Monitoring dan Alerting
Metrics yang Perlu Dipantau
1. Branch Count
- Total branches aktif
- Branches per environment
- Growth rate
2. Storage Usage
- Total storage terpakai
- Storage per branch
- Storage growth rate
3. Connection Count
- Active connections
- Connection pool usage
- Connection wait time
4. Query Performance
- Average query time
- Slow queries
- Query count per branch
Setup Monitoring
// Monitor branch usage
async function monitorBranchUsage() {
const branches = await neon.listBranches();
const metrics = {
totalBranches: branches.length,
branchesByName: {},
totalStorage: 0,
};
for (const branch of branches) {
metrics.branchesByName[branch.name] = {
createdAt: branch.created_at,
storage: branch.storage_bytes,
};
metrics.totalStorage += branch.storage_bytes;
}
return metrics;
}
Alert Thresholds
# alerts.yml
alerts:
- name: too_many_branches
condition: total_branches > 50
action: notify
- name: storage_warning
condition: storage_usage > 80%
action: notify
- name: old_branch
condition: branch_age > 30d
action: cleanup
5. Backup Strategy
Backup Sebelum Branching
# Backup sebelum buat branch baru
pg_dump $DATABASE_URL > backup-$(date +%Y%m%d).sql
# Atau backup ke S3
pg_dump $DATABASE_URL | \
aws s3 cp - s3://my-backups/db-$(date +%Y%m%d).sql
Backup Otomatis
// Auto backup setiap hari
const cron = require('node-cron');
cron.schedule('0 2 * * *', async () => {
const backup = await pg_dump(DATABASE_URL);
await uploadToS3(`backups/${date}.sql`, backup);
console.log(`Backup completed: ${date}`);
});
Restore dari Backup
# Restore database
psql $DATABASE_URL < backup-20260617.sql
# Atau restore ke branch baru
psql "postgresql://...@branch-name" < backup.sql
6. Security Best Practices
Environment Variables
# ❌ Jangan lakukan ini
DATABASE_URL=postgresql://admin:password123@host/dbname
# ✅ Gunakan environment variables
DATABASE_URL=${DATABASE_URL}
# ✅ Gunakan connection pooling dengan SSL
DATABASE_URL=postgresql://...?sslmode=require&pgbouncer=true
Access Control
// Buat user khusus untuk setiap environment
const users = {
production: { user: 'app_prod', password: '***' },
staging: { user: 'app_staging', password: '***' },
development: { user: 'app_dev', password: '***' },
};
Audit Log
-- Enable audit logging
CREATE EXTENSION IF NOT EXISTS pgaudit;
-- Log all queries
SET pgaudit.log = 'all';
7. Performance Optimization
Index Strategy
-- Index untuk query yang sering dipakai
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
CREATE INDEX CONCURRENTLY idx_orders_user ON orders(user_id);
CREATE INDEX CONCURRENTLY idx_products_category ON products(category);
-- Partial index untuk data yang sering di-query
CREATE INDEX idx_active_users ON users(email) WHERE active = true;
Query Optimization
-- ❌ Slow query
SELECT * FROM orders WHERE user_id = 123;
-- ✅ Optimized query
SELECT id, status, total FROM orders
WHERE user_id = 123
ORDER BY created_at DESC
LIMIT 10;
Connection Pool Monitoring
-- Cek active connections
SELECT count(*) FROM pg_stat_activity;
-- Cek connection pool usage
SELECT
state,
count(*)
FROM pg_stat_activity
GROUP BY state;
8. CI/CD Integration
GitHub Actions Setup
# .github/workflows/database-branch.yml
name: Database Branch
on:
pull_request:
types: [opened, synchronize]
jobs:
create-branch:
runs-on: ubuntu-latest
steps:
- name: Create Neon Branch
run: |
BRANCH_NAME="pr-${{ github.event.pull_request.number }}"
curl -X POST "https://console.neon.tech/api/v2/projects/{id}/branches" \
-H "Authorization: Bearer ${{ secrets.NEON_API_KEY }}" \
-d "{\"branch\": {\"parent_id\": \"main\"}, \"name\": \"$BRANCH_NAME\"}"
Cleanup on Merge
# .github/workflows/cleanup-branch.yml
name: Cleanup Branch
on:
pull_request:
types: [closed]
jobs:
delete-branch:
runs-on: ubuntu-latest
steps:
- name: Delete Branch
run: |
BRANCH_NAME="pr-${{ github.event.pull_request.number }}"
curl -X DELETE "https://console.neon.tech/api/v2/projects/{id}/branches/$BRANCH_NAME" \
-H "Authorization: Bearer ${{ secrets.NEON_API_KEY }}"
Checklist Best Practices
- Naming convention konsisten
- TTL setup untuk auto-cleanup
- Connection pooling dikonfigurasi
- Monitoring dan alerting aktif
- Backup strategy terimplementasi
- Security best practices diterapkan
- Performance optimization dilakukan
- CI/CD integration terpasang
Kesimpulan
Database branching adalah fitur powerful yang memudahkan development workflow. Dengan best practices di atas, kamu bisa:
- ✅ Menjaga cleanliness branches
- ✅ Mengoptimalkan storage usage
- ✅ Memastikan performance optimal
- ✅ Menjaga keamanan data
- ✅ Mengotomasi cleanup dan monitoring
Butuh bantuan? Hubungi [email protected]
Baca juga: