Episode penutup seri Belajar Fullstack: teknik optimasi tingkat lanjut — profiling aplikasi, pengendalian bundle size, tuning query dan index database, serta workflow tuning produksi yang terukur dan berulang.

Ini episode terakhir dari 28 — dan optimasi adalah tema yang pantas menutupnya, karena ia menyentuh semua yang sudah kalian pelajari: rendering (episode 3), data fetching (episode 8), caching (episode 15), keamanan (episode 16), dan observability (episode 24). Episode ini membahas performance & optimization lanjutan — bukan trik cepat, tapi metodologi: mengukur, menemukan penyebab sebenarnya, dan menerapkan perbaikan yang tepat.
Aturan pertamanya: optimasi tanpa pengukuran adalah tebakan. Setiap bagian dimulai dari ukuran — bukan intuisi.
Disiplinnya: satu perubahan, satu pengukuran. Menerapkan tiga optimasi sekaligus membuat kalian tidak tahu mana yang bekerja (atau mana yang merusak).
"Lambat" bukanlah diagnosis. Alat profiling membedah di mana waktu benar-benar terpakai:
| Lapisan | Alat | Pertanyaan |
|---|---|---|
| Browser | Chrome DevTools (Performance) | Render atau JavaScript? |
| Server | next build --debug / tracing episode 24 | Render atau query? |
| Database | EXPLAIN ANALYZE | Full scan atau index scan? |
| Jaringan | Performance insights (Vercel) | TTFB vs rendering? |
Contoh pembuka mata yang klasik:
EXPLAIN ANALYZE
SELECT * FROM "Note"
WHERE organization_id = 'org-1'
ORDER BY created_at DESC
LIMIT 10;
-- tanpa index: Seq Scan ... 1800 ms
-- dengan index: Index Scan ... 3 msSatu baris output Seq Scan vs Index Scan menjelaskan lebih banyak daripada seminggu menebak. 600x perbedaan dari satu index — itulah kenapa profiling selalu pertama.
Important
Rule profiling yang wajib: ukur di production (atau profil yang setara), bukan di development. Data development terlalu kecil — query yang "cepat" di lokal bisa jadi bencana dengan 10 juta baris. EXPLAIN ANALYZE dengan dataset nyata adalah pembeda besar antara optimasi nyata dan latihan.
Bundle yang gemuk memperlambat waktu interaksi (INP) meski server cepat. Tiga senjata utama:
Dynamic import — muat kode berat hanya saat dibutuhkan:
const MarkdownEditor = dynamic(() => import("@/components/markdown-editor"), {
loading: () => <EditorSkeleton />,
})Tree-shaking — jangan import seluruh library:
// JANGAN — menarik seluruh lodash
import _ from "lodash"
// BAIK — hanya yang dipakai
import orderBy from "lodash/orderBy"Pemeriksaan terus-menerus — jadikan ukuran bagian dari CI:
pnpm build && pnpm next bundle-analyzerIngat aturan emas episode 3 dan 8: semakin banyak di server (Server Components), semakin sedikit yang harus dikirim ke browser. Sebagian besar "optimasi bundle" di aplikasi Next.js sebenarnya adalah "pindahkan ke server".
Di episode 22 kita membahas scaling; di sini detail tuning-nya. Tiga pola yang paling berdampak:
Composite index sesuai urutan query — kolom yang difilter = dulu, lalu yang di-ORDER BY:
CREATE INDEX idx_notes_org_created
ON "Note" (organization_id, created_at DESC);Hindari SELECT * di query panas — ambil hanya kolom yang dirender:
const notes = await prisma.note.findMany({
where: { organizationId },
select: { id: true, title: true, createdAt: true },
take: 20,
})Waspadai N+1 — jangan query dalam loop. Pola episode 8 (include relasi) atau query terpisah lalu gabung di memori, bukan query per baris:
// JANGAN
const notes = await prisma.note.findMany({ where: { organizationId } })
const authors = await Promise.all(notes.map((n) => prisma.user.findUnique({ where: { id: n.authorId } })))
// BAIK — satu query dengan relasi
const notes = await prisma.note.findMany({
where: { organizationId },
include: { author: true },
})Warning
Hati-hati premature optimization. Sebelum menambahkan index atau mencabut query, pastikan ada bukti query itu lambat atau sering — dari profiling/observability (episode 24), bukan dari perasaan. Index menambah biaya tulis dan memori; dynamic import menambah kompleksitas. Optimasi hanya layak jika data menunjukkan masalah.
Optimasi bukan peristiwa sekali — ia proses berulang. Workflow produksi yang sehat:
Timeline nyatanya: kebanyakan kemenangan besar datang dari 3-4 perbaikan terukur per kuartal — bukan pesta optimasi mingguan.
Selesaikan dengan urutan berikut:
EXPLAIN ANALYZE).curl -s -o /dev/null -w "TTFB: %{time_starttransfer}s total: %{time_total}s\n" \
http://localhost:3000/notesInti episode ini — dan seluruh seri:
EXPLAIN ANALYZE.Kalian mulai dari create-next-app dan prisma init di episode 0. Sekarang kalian telah melewati 28 episode: frontend dan backend, auth dan database, queue dan real-time, security dan scaling, AI dan observability. Kalian bukan lagi pemula — kalian fullstack developer. Terus bangun, terus ukur, dan sampai jumpa di proyek berikutnya!