nestjs adalah kerangka kerja Node.js yang cocok untuk membangun templat produksi back-end menggunakan Prisma dan PostgreSQL.
Artikel ini memandu langkah demi langkah: arsitektur modul, setup proyek, desain schema Prisma, migrasi dan seed, praktik autentikasi dan keamanan, serta strategi deployment dan monitoring agar aplikasi siap skala dan andal di lingkungan produksi. Termasuk contoh konfigurasi, snippet Prisma schema, dan rekomendasi tool observability serta backup.
Arsitektur Back-end Modular untuk Templat Produksi
Arsitektur modular bertujuan untuk separasi concern, meningkatkan testability, serta memudahkan scalability saat fitur bertambah; hasilnya kode lebih mudah diuji dan komponen dapat diganti tanpa efek samping luas. Mengapa penting? Karena pengelolaan dependensi dan batas tanggung jawab mencegah perubahan kecil menjadi bencana besar pada produksi.
💻 Mulai Belajar Pemrograman
Belajar pemrograman di Dicoding Academy dan mulai perjalanan Anda sebagai developer profesional.
Daftar SekarangPola lapisan umum terdiri dari controller sebagai antarmuka, service untuk logika bisnis, repository/data access untuk interaksi Prisma/PostgreSQL, module sebagai pengelompokan fitur, dan gateway untuk real-time. Contoh struktur sederhana yang direkomendasikan sebagai berikut.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
src/ main.ts app.module.ts modules/ auth/ auth.module.ts auth.controller.ts auth.service.ts auth.repository.ts dtos/ users/ users.module.ts users.controller.ts users.service.ts users.repository.ts common/ filters/ interceptors/ guards/ |
Pilih monolith modular untuk tim kecil karena lebih cepat iterasi; skala tim besar bisa mempertimbangkan microservices meski kompleksitas operasional meningkat. Checklist keputusan arsitektur sebagai berikut.
- Terapkan logging terpusat dan format terstruktur.
- Siapkan observability (metrics, traces) sejak awal.
- Gunakan config management berbasis environment dan secret store.
- Standardisasi error handling dengan kode dan bentuk respons konsisten.
Langkah praktis berikutnya akan memandu cara menyiapkan proyek NestJS untuk templat produksi.
Menyiapkan Proyek nestjs untuk Templat Produksi
Pada inisialisasi pilih antara NestJS dengan Express atau Fastify: Fastify memberi throughput lebih tinggi dan latensi lebih rendah untuk API, sedangkan Express lebih matang di ekosistem middleware. Pilih Fastify bila kebutuhan performa dan skalabilitas penting; gunakan Express jika kompatibilitas middleware pihak ketiga jadi prioritas.
Konfigurasi proyek meliputi TypeScript, ESLint, Prettier, serta husky dan lint-staged untuk menjaga kualitas commit. Kamu bisa memaksa format dan pengecekan sebelum push sehingga standar kode konsisten dalam tim tanpa harus mengorbankan kecepatan development.
Buat struktur modul awal: AuthModule untuk autentikasi, UserModule untuk logika domain user, DatabaseModule yang membungkus inisialisasi Prisma dan koneksi PostgreSQL, serta SharedModule untuk provider bersama. Gunakan @nestjs/config untuk pengelolaan konfigurasi per environment sehingga variabel sensitif tidak hardcode.
Terapkan DTO dengan class-validator, aktifkan ValidationPipe secara global, tambahkan global exception filter dan interceptor untuk logging serta pengukuran performa. Pola ini meningkatkan keamanan, konsistensi, dan observabilitas produksi.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ValidationPipe } from '@nestjs/common'; import { FastifyAdapter } from '@nestjs/platform-fastify'; async function bootstrap() { const app = await NestFactory.create(AppModule, new FastifyAdapter()); app.setGlobalPrefix('api'); app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); app.enableCors(); await app.listen(process.env.PORT || 3000); } bootstrap(); |
Selanjutnya kita akan membahas desain schema database dengan Prisma dan PostgreSQL, langkah penting setelah struktur proyek berdiri.
Desain Skema Database dengan Prisma dan PostgreSQL
Mulai dari analisis kebutuhan: identifikasi entitas inti, relasi one-to-one, one-to-many, dan many-to-many, serta constraints yang wajib ditegakkan pada level database.
Pilih tipe data berdasarkan perilaku: gunakan UUID untuk cross-service identifier, timestamptz untuk cap waktu global, dan jsonb untuk payload fleksibel; keputusan normalisasi versus denormalisasi harus mempertimbangkan beban baca tulis—apakah kamu butuh query cepat atau konsistensi kuat.
Tambahkan field audit (createdAt, updatedAt, createdBy), pola soft delete (nullable deletedAt) dan version untuk optimistic concurrency; indeks dan enum memperkuat integritas serta performa.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Role { id String @id @default(uuid()) @db.Uuid name String @unique users User[] } model User { id String @id @default(uuid()) @db.Uuid email String @unique roleId String? @db.Uuid role Role? @relation(fields: [roleId], references: [id]) meta Json? @db.JsonB createdAt DateTime @default(now()) @db.Timestamptz updatedAt DateTime @updatedAt @db.Timestamptz deletedAt DateTime? @db.Timestamptz version Int @default(1) @@index([email]) } model AuditLog { id String @id @default(uuid()) @db.Uuid entity String entityId String action String data Json @db.JsonB createdAt DateTime @default(now()) @db.Timestamptz } |
Setelah schema siap, jalankan npx prisma generate di lingkungan yang aman; jangan commit DATABASE_URL—letakkan di CI/CD secrets. Untuk produksi, gunakan prisma migrate deploy dan hindari menjalankan migrate dev langsung; gunakan shadow database hanya untuk pengembangan. Ini menyiapkan basis yang konsisten sebelum bab berikutnya tentang strategi migrasi dan seed.
Strategi Migrasi Seed Dan Versi Skema Database
Gunakan workflow Prisma Migrate yang jelas: migrate dev untuk pengembangan lokal, promosi ke staging untuk review, lalu migrate deploy pada production. Selalu review file migration sebelum apply; file yang repeatable dan terdeskripsikan memudahkan code review dan audit. Anggap migration sebagai kode yang harus dites—jalankan pada shadow database agar deteksi konflik dan perintah destruktif lebih awal.
Strategi seeding: buat seed idempotent dengan upsert untuk data seperti initial admin dan lookup tables sehingga tidak menimpa data produksi. Untuk perubahan besar, pakai pendekatan dua fase: tambah kolom nullable, lakukan backfill, baru ubah menjadi not null. Ini menjaga backward-compatible changes dan mengurangi downtime; ibarat menambah lorong sebelum menutup jalan lama.
Rollback bukan hanya revert migration; rencanakan script balik yang eksplisit, snapshot database dan tes migrasi pada staging. Automasi pada CI/CD: langkah safe—run migrations dalam staging, jalankan test suite, buat maintenance window, lalu eksekusi prisma migrate deploy pada produksi dan jalankan seed. Contoh seed singkatnya berikut.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { await prisma.user.upsert({ where: { email: 'admin@example.com' }, update: {}, create: { email: 'admin@example.com', role: 'ADMIN', passwordHash: '...' }, }); await prisma.lookup.upsert({ where: { key: 'COUNTRY' }, update: {}, create: { key: 'COUNTRY', value: 'Indonesia' } }); } main().finally(() => prisma.$disconnect()); |
Keamanan Autentikasi dan Otorisasi pada Produksi
Pilih mekanisme autentikasi berdasarkan kebutuhan: JWT cocok untuk skala distribusi karena stateless, sedangkan session lebih sederhana untuk kontrol revoke; kombinasikan akses token pendek dan refresh token dengan refresh token rotation serta simpan pada httpOnly secure cookie untuk secure storage. Simpan hash refresh token dalam database dan sediakan daftar revoke sehingga logout serta rotasi kunci efektif.
Untuk otorisasi gunakan RBAC dan pola guard dalam NestJS, buat decorator untuk izin serta satu PermissionGuard terpusat yang membaca klaim token dan mengecek hak akses dari database atau cache. Contoh singkat implementasi guard sebagai berikut.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class PermissionGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const required = this.reflector.get('permissions', context.getHandler()) || []; const req = context.switchToHttp().getRequest(); const user = req.user; return required.every(p => user?.permissions?.includes(p)); } } |
Lindungi secrets dengan KMS atau Secret Manager (AWS/GCP/HashiCorp), minimalkan env var langsung dalam repo dan terapkan key rotation; enkripsi kolom sensitif pada aplikasi bila perlu.
Gunakan Prisma untuk mencegah SQL injection melalui parameterized queries, aktifkan validasi input (class-validator), sanitasi output untuk XSS, proteksi CSRF saat pakai cookie, dan terapkan rate limiting (mis. Throttler).
Audit logging harus merekam siapa, kapan, dan apa yang diakses; simpan log immutable, anonymize untuk kepatuhan GDPR/PDPA, dan siapkan alerting serta ekspos metrik autentikasi ke pipeline CI/CD agar pemantauan dan rotasi rahasia terotomasi sebelum deployment.
Deployment CI/CD dan Monitoring untuk Lingkungan Produksi
Rancang pipeline CI/CD yang jelas: langkah build, unit, dan integration test, lalu tahap migrasi sebelum deployment. Sertakan job terpisah untuk Prisma migrate yang berjalan hanya pada branch produksi; gunakan artefak build untuk konsistensi image Docker. Contoh ringkas GitHub Actions:
|
1 2 3 4 5 6 7 8 9 10 11 |
name: CI on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - run: npm ci && npm run build - run: npx prisma migrate deploy - run: docker build -t registry/myapp:latest . && docker push registry/myapp:latest |
Pilih hosting berdasarkan kebutuhan: VPS untuk biaya rendah, registry + container untuk fleksibilitas, Kubernetes untuk autoscaling, atau PaaS untuk operasional minimal. Pertimbangkan biaya, latensi, dan tim operasi saat memutuskan.
Agar tanpa downtime, pakai rolling updates atau blue-green, dan desain migrasi schema yang backward-compatible; gunakan feature flags untuk memisahkan deploy kode dari release fitur. Untuk migrasi besar, pertimbangkan logical replication atau pg_repack agar kueri tidak terblok.
Observability wajib: logging terpusat (ELK atau Grafana Loki), metrics dengan Prometheus + Grafana, tracing via OpenTelemetry, serta alerting terintegrasi. Backup PostgreSQL dengan pg_basebackup plus WAL archiving, jadwalkan verifikasi restore otomatis. Sebelum go-live, lakukan security scan (Snyk), dependency audit, performance test, dan siapkan runbook insiden.
Penutup
Ringkasan: artikel ini memberi panduan praktis untuk membuat templat produksi back-end yang robust dengan NestJS, Prisma, dan PostgreSQL. Pembaca akan mendapatkan pola arsitektur, konfigurasi database, migrasi, praktik keamanan, dan langkah deployment yang dapat langsung diadaptasi. Hasilnya: proyek lebih konsisten, mudah dipelihara, dan siap dioperasikan pada lingkungan produksi skala kecil hingga menengah.