Latar Belakang: Bottleneck pada Monolit Next.js

Penskalaan aplikasi web satu monolit Next.js pada tim rekayasa perangkat lunak berskala besar sering kali membentur batasan organisasi dan infrastruktur. Masalah utama muncul bukan dari performa runtime, melainkan dari efisiensi siklus pengembangan (developer experience) dan operasional deployment:

  • Waktu Build Linear: Peningkatan rute static generation (SSG), kompilasi TypeScript, bundling Webpack/Turbopack, dan optimasi gambar memperpanjang waktu Continuous Integration (CI). Antrean deployment membengkak secara eksponensial seiring bertambahnya halaman.
  • Keterikatan Rilis (Release Coupling): Beberapa tim domain (misalnya tim Checkout, Akun, dan Blog) berbagi satu siklus deployment yang sama. Bug kritis pada satu modul di halaman sekunder dapat membatalkan atau menunda rilis fitur inti produk.
  • Blast Radius Luas: Kesalahan fatal pada satu dependensi runtime atau konfigurasi middleware global dapat menyebabkan downtime ke seluruh platform secara menyeluruh.

Next.js Multi-Zones menyediakan pendekatan berbasis mikro-frontend yang memungkinkan penggabungan beberapa aplikasi Next.js independen di bawah satu domain routing tunggal tanpa memerlukan konfigurasi Module Federation yang kompleks.

Mekanisme Routing dan Konfigurasi Multi-Zones

Prinsip kerja Multi-Zones bergantung pada penanganan rute URL HTTP melalui rewrites. Satu aplikasi Next.js bertindak sebagai rute utama (root zone), lalu meneruskan permintaan rute tertentu ke aplikasi Next.js lainnya (child zones) yang berjalan pada host atau port terpisah.

1. Konfigurasi Child Zone

Aplikasi hilir (misalnya aplikasi blog atau dokumentasi) harus mengetahui prefiks jalurnya melalui properti basePath. Ini memastikan semua routing internal dan pemanggilan aset statis diawali dengan rute yang benar.

// apps/blog/next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  basePath: '/blog',
  reactStrictMode: true,
};

module.exports = nextConfig;

2. Konfigurasi Root Zone

Aplikasi utama mengatur aturan rewrites untuk memetakan prefix URL ke server child zone. Pemetaan ini mencakup rute HTML dan aset statis Next.js (seperti bundle JavaScript dan CSS di bawah /_next/).

// apps/main/next.config.js
const BLOG_ZONE_URL = process.env.BLOG_ZONE_URL || 'http://localhost:3001';

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: '/blog',
        destination: `${BLOG_ZONE_URL}/blog`,
      },
      {
        source: '/blog/:path*',
        destination: `${BLOG_ZONE_URL}/blog/:path*`,
      },
      {
        source: '/blog-static/_next/:path*',
        destination: `${BLOG_ZONE_URL}/blog/_next/:path*`,
      },
    ];
  },
};

module.exports = nextConfig;

Catatan: Alternatif yang lebih efisien di level produksi adalah mendelegasikan proxy routing ke CDN atau reverse proxy terluar (seperti Cloudflare Workers, AWS CloudFront, atau Nginx Ingress Controller) daripada membebankan server Node.js dari root zone untuk melakukan reverse-proxying stream HTTP.

Analisis Trade-off Teknis dan Performa

Membagi aplikasi Next.js menjadi beberapa zona menghasilkan isolasi yang kuat, tetapi mengorbankan sejumlah kemampuan runtime Single Page Application (SPA).

1. Hard Navigation dan Dampak terhadap Core Web Vitals

Navigasi di dalam zona yang sama tetap menggunakan next/link berbasis SPA (soft navigation). Namun, transisi lintas zona (misalnya dari /dashboard di root zone ke /blog/post-1 di child zone) memaksa browser melakukan navigasi penuh (hard navigation).

  • Largest Contentful Paint (LCP): Navigasi penuh memicu parsing ulang seluruh dokumen HTML, pemuatan stylesheet, dan runtime JavaScript dari awal. Browser tidak dapat memanfaatkan persistent shared layout.
  • Interaction to Next Paint (INP): Eksekusi hidrasi React berjalan kembali dari nol pada setiap transisi lintas zona, meningkatkan pemblokiran thread utama sesaat setelah navigasi.
  • In-Memory Cache Eviction: State global client-side (seperti Redux, Zustand, atau React Query cache) terhapus. Data bersama harus disimpan ulang di localStorage, sessionStorage, atau dimuat kembali melalui API request baru.

2. Sinkronisasi Sesi dan Autentikasi

Karena setiap zona adalah aplikasi independen, sinkronisasi status login tidak dapat mengandalkan React Context lintas zona. Praktik standar yang harus diterapkan:

  • Gunakan cookie berbasis HTTP-Only dengan atribusi domain tingkat atas, misal Domain=.domain.com; SameSite=Lax; Secure, agar token sesi dapat dibaca oleh setiap sub-aplikasi.
  • Hindari penyimpanan token pada memori JavaScript client. Mengandalkan middleware Next.js pada masing-masing zona untuk memverifikasi validitas token JWT secara mandiri guna mencegah cascading failures ke service auth pusat.

3. Isolasi Blast Radius

Keuntungan terbesar Multi-Zones terletak pada isolasi kegagalan. Jika child zone mengalami memory leak atau crash fatal akibat uncaught exception pada Server-Side Rendering (SSR), dampaknya terbatas pada rute spesifik zona tersebut. Root zone dan zona lainnya tetap dapat melayani traffic dengan normal.

Evaluasi Biaya Operasional dan Infrastruktur

Pemisahan aplikasi monolit menjadi multi-zone secara langsung meningkatkan kompleksitas serta alokasi resource komputasi.

Komparasi Alokasi Resource

  • Monolit: Hanya memerlukan satu Horizontal Pod Autoscaler (HPA) di Kubernetes. Buffer memori terkonsolidasi, sehingga penyerapan lonjakan lalu lintas (traffic spike) lebih efisien karena resource terbagi rata di seluruh halaman.
  • Multi-Zones: Setiap zona memerlukan deployment terpisah dengan minimum replica pod (umumnya minimal 2 pod per zone untuk High Availability). Node.js runtime overhead (rata-rata 80MB-150MB per pod idle) terduplikasi di setiap zona. Baseline pemakaian CPU dan RAM cluster meningkat drastis meskipun sebagian zona memiliki traffic rendah.

Biaya Networking

Jika proxy dilakukan pada layer aplikasi Next.js (menggunakan konfigurasi rewrites), terjadi double-hop latency dan peningkatan konsumsi network bandwidth internal pod. Request masuk ke root pod, dibuka kembali, lalu dikirim via internal request ke child pod. Ini menambah latency 15ms-50ms tergantung topologi cluster.

Maintainability: Monorepo dan Shared Library

Menerapkan Multi-Zones idealnya dipadukan dengan struktur Monorepo (menggunakan pnpm workspaces, Turborepo, atau Nx) untuk menyeimbangkan isolasi kode dengan konsistensi antarmuka.

1. Dependency Drift

Setiap zona berpotensi menggunakan versi dependensi yang berbeda jika tidak dikunci secara ketat. Perbedaan versi minor React atau Next.js antar zona dapat menghasilkan inkonsistensi perilaku UI atau breaking changes pada shared hooks.

2. Shared Component Library

Komponen UI terbagi (design system) perlu dikelola sebagai internal package. Untuk menghindari masalah kompilasi ganda, gunakan properti transpilePackages pada next.config.js masing-masing zona:

// next.config.js
module.exports = {
  transpilePackages: ['@company/ui'],
};

Matriks Keputusan Migrasi

Gunakan checklist berikut sebelum memutuskan membagi monolit Next.js ke arsitektur Multi-Zones:

Parameter PenilaianTetap Gunakan MonolitMigrasi ke Multi-Zones
Jumlah Engineer Frontend< 15 orang> 20 orang (terbagi dalam multiple domain squads)
Durasi Build CI< 10 menit> 25 menit dan memblokir kecepatan rilis
Kebutuhan Frekuensi Rilis1-2 kali per hari secara kolektifMultiple rilis per jam secara independen antar tim
Ekspektasi Navigasi PenggunaKritikal terhadap fluiditas SPA lintas seluruh halamanDapat mentoleransi hard reload saat berpindah domain fungsional
Budget Infrastruktur & DevOpsTerbatas, tim fokus pada pengembangan produkTersedia alokasi resource untuk observabilitas dan micro-service pods

Arsitektur Multi-Zone bukan solusi untuk optimasi performa runtime, melainkan solusi arsitektur organisasi untuk mengatasi inefisiensi koordinasi tim dan proses deployment. Jika bottleneck organisasi belum terjadi, mempertahankan kesederhanaan monolit Next.js adalah pilihan teknis yang lebih rasional.