Belajar Drizzle ORM - Production Deployment & Best Practice
Episode 20 of 21

Belajar Drizzle ORM - Production Deployment & Best Practice

Production deployment Drizzle ORM: database connection management untuk serverless dan traditional, migration strategy dengan generate + review + apply via CI/CD, performance monitoring dengan EXPLAIN ANALYZE dan slow query logging, security best practice, CI/CD integration, dan health check endpoint untuk memverifikasi koneksi database.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 19 kita mempelajari Project Structure & Scalability — modular schema, query service pattern, dan scaling ke microservices — pada episode ini — episode terakhir — kita menutup series dengan production deployment: bagaimana menjalankan Drizzle ORM di production dengan aman, scalable, dan reliable.

Production deployment berbeda dari development: connection management lebih kritis, migration harus terkontrol, performance harus dimonitor, dan keamanan harus diutamakan.

Database Connection Management

Serverless (Lambda, Vercel Functions, Cloudflare Workers)

Serverless: driver handles connection
import { drizzle } from 'drizzle-orm/neon-http'
import { neon } from '@neondatabase/serverless'
 
const sql = neon(process.env.DATABASE_URL!)
export const db = drizzle(sql)

Serverless tidak membutuhkan connection pooling — driver handles. Neon, Turso, dan D1 sudah dioptimasi untuk request-response pattern.

Traditional (Express, Fastify, Hono di VPS)

Traditional: connection pool
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
 
const client = postgres(process.env.DATABASE_URL!, {
  max: 20,
  idle_timeout: 20,
})
export const db = drizzle(client)

Connection pool memastikan koneksi di-reuse, tidak dibuat baru setiap request.

Migration Strategy for Production

Production migration workflow
# 1. Update schema TypeScript
# 2. Generate migration
npx drizzle-kit generate
# 3. Review generated SQL
cat drizzle/0001_add_column.sql
# 4. Apply via CI/CD
npx drizzle-kit migrate

Rollback Strategy

Jika migration gagal:

  • Reverse migration: buat migration baru yang membatalkan perubahan.
  • Manual SQL: jalankan SQL rollback secara manual.

Jangan edit migration files yang sudah di-apply — buat migration baru untuk perubahan apapun.

Performance Monitoring

EXPLAIN ANALYZE

Analisis query performance
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'john@example.com';

Pastikan query menggunakan index, bukan sequential scan.

Slow Query Logging

Log slow queries di PostgreSQL
# postgresql.conf
log_min_duration_statement = 100  # Log queries > 100ms

Identifikasi query yang lambat dan optimasi dengan index.

Index Monitoring

Cek apakah index digunakan
EXPLAIN SELECT * FROM users WHERE email = 'john@example.com';
-- Pastikan: Index Scan, bukan Seq Scan

Security Best Practice

Parameterized Queries

Drizzle ORM sudah menggunakan prepared statements secara default — aman dari SQL injection. Tidak perlu khawatir.

Least Privilege

Database user dengan permissions terbatas
CREATE USER app_user WITH PASSWORD 'secure_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
-- Jangan grant DROP, ALTER, atau CREATE untuk app user

Database user hanya punya permissions yang dibutuhkan — tidak lebih.

Environment Variables

DATABASE_URL dari secret manager
# Jangan hardcode! Gunakan environment variables
DATABASE_URL=postgresql://user:password@host:5432/db

Di production, gunakan secret manager (AWS Secrets Manager, Vercel Environment Variables, Cloudflare Secrets).

CI/CD Integration

GitHub Actions: migration + deploy
name: Deploy
on:
  push:
    branches: [main]
jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx drizzle-kit generate
      - run: npx drizzle-kit migrate
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
  deploy:
    needs: [migrate]
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
      - run: ./deploy.sh

Health Check Endpoint

Health check endpoint
import { sql } from 'drizzle-orm'
 
app.get('/health', async (c) => {
  try {
    await db.execute(sql`SELECT 1`)
    return c.json({ status: 'healthy', database: 'connected' })
  } catch (error) {
    return c.json({ status: 'unhealthy', database: 'disconnected' }, 503)
  }
})

Health check memverifikasi bahwa aplikasi bisa terhubung ke database — kritis untuk load balancer dan orchestrator (Kubernetes, ECS).

Warning

Health check endpoint harus cepat dan tidak mengembalikan data sensitif. Cukup SELECT 1 untuk memverifikasi koneksi. Jangan log query di health check — ini akan membanjiri logs dengan false positives.

Refleksi Akhir Series

Sepanjang 21 episode, kita telah menempuh perjalanan lengkap Drizzle ORM dari fondasi hingga production:

  • Episode 0-2: Prasyarat, sejarah, arsitektur Drizzle ORM.
  • Episode 3-6: Setup, schema, CRUD, advanced select.
  • Episode 7-9: Relations, JOIN, sub-query & CTE.
  • Episode 10-12: Migrations, introspection, Drizzle Studio.
  • Episode 13-15: Transactions, prepared statements, raw SQL.
  • Episode 16-18: Zod integration, drivers & serverless, testing.
  • Episode 19-20: Project structure, production deployment.

Drizzle ORM adalah tool yang ringan, powerful, dan TypeScript-native. Dengan pemahaman yang solid tentang konsep-konsep ini, kalian bisa membangun database layer yang scalable, maintainable, dan production-ready. Selamat menempuh perjalanan ini, dan semoga kalian bisa memanfaatkan Drizzle ORM secara optimal di proyek kalian!

Belajar Drizzle ORM - Production Deployment & Best Practice | Belajar Drizzle ORM