# Optimasi Performa Next.js SSR di Lingkungan Kubernetes

> Diterbitkan oleh Literally Web ID pada 21 Oct 2026
> Sumber: https://literally.web.id/articles/optimasi-performa-nextjs-ssr-di-lingkungan-kubernetes

---

Dalam 15 menit ke depan, kita akan merakit stack ini dari nol sampai berjalan mulus. Pengalaman di lapangan membuktikan bahwa pod Next.js SSR sering kali tumbang bukan karena kurang kapasitas, melainkan karena manajemen memori V8 yang salah urus dan ketiadaan *caching layer* yang solid di Kubernetes. Bayangkan kita sedang menangani lonjakan trafik jutaan *hit* dari kampanye flash sale; jika konfigurasi *Garbage Collection* Node.js dibiarkan *default*, pod Anda akan mengalami *OutOfMemory* (OOM) dalam hitungan menit.

Mari kita bedah dan atasi masalah ini bersama-sama.

## 1. Menu Kita Hari Ini & Alat yang Perlu Disiapkan

Sebelum kita masuk ke ruang mesin, pastikan Anda sudah menyiapkan beberapa bahan utama di lingkungan kerja Anda:
- Klaster Kubernetes (bisa menggunakan Minikube untuk lokal, atau AWS EKS / GCP GKE untuk production).
- `kubectl` dan `helm` yang sudah terhubung ke klaster.
- Redis instance (bisa menggunakan Redis Operator atau managed service seperti ElastiCache).
- Metrik server seperti Metrics Server terpasang di Kubernetes untuk mendukung Horizontal Pod Autoscaler berbasis kustom.

> [!IMPORTANT]
> Pastikan Node.js versi 18+ digunakan agar fitur manajemen memori V8 berjalan optimal.

## 2. Peta Jalan Singkat: Apa yang Sedang Kita Rakit

Perjalanan kita hari ini dirancang seefisien mungkin:
1. Mengatur batas memori V8 Node.js di dalam kontainer Docker agar tidak rakus.
2. Mengintegrasikan Redis dan *Incremental Static Regeneration* (ISR) untuk memangkas beban kerja SSR.
3. Memasang Horizontal Pod Autoscaler (HPA) menggunakan *custom metrics* Prometheus.
4. Melakukan uji beban dan verifikasi.

Mari kita mulai meracik fondasinya di langkah berikutnya.

## 3. Langkah 1: Mempersiapkan Fondasi & Environment

Hal pertama yang sering dilewatkan para insinyur junior adalah membiarkan V8 engine menggunakan batas memori *default* mesin. Di dalam kontainer Kubernetes dengan batas memori 2GB, V8 tetap berasumsi ia berjalan di atas mesin dengan RAM tak terbatas, lalu tiba-tiba *CrashLoopBackOff* karena OOMKilled.

Mari kita buat Dockerfile yang cerdas:

```dockerfile
FROM node:18-alpine AS runner
WORKDIR /app

# Atur environment untuk produksi dan batasi memori V8 heap
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=1536"

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --chown=nextjs:nodejs .next/standalone ./
COPY --chown=nextjs:nodejs .next/static ./.next/static

USER nextjs
EXPOSE 3000
ENV PORT=3000

CMD ["node", "server.js"]
```

Perhatikan baris `NODE_OPTIONS="--max-old-space-size=1536"`. Ini adalah rem tangan pengaman agar Node.js tahu persis kapan harus membersihkan tumpukan memori sebelum Kubernetes mematikan kontainer secara paksa.

## 4. Langkah 2: Meracik Konfigurasi Inti Tanpa Basa-basi

Sekarang pod kita sudah tahu batasan dirinya, saatnya meringankan bebannya menggunakan Redis dan ISR. Kita tidak ingin setiap request menghantam database secara langsung. Konfigurasikan Next.js agar melakukan *fallback* caching ke Redis cluster.

Buat file `cache-handler.js` di root proyek Anda:

```javascript
const { createClient } = require('redis');

const client = createClient({ url: process.env.REDIS_URL });
client.connect().catch(console.error);

module.exports = async function cacheHandler(options) {
  return {
    async get(key) {
      const value = await client.get(key);
      return value ? JSON.parse(value) : null;
    },
    async set(key, data, ctx) {
      await client.set(key, JSON.stringify({ value: data, lastModified: Date.now() }));
    },
    async revalidate(key) {
      await client.del(key);
    },
  };
};
```

> [!TIP]
> Gunakan Redis sentinel atau cluster terkelola untuk memastikan *caching layer* ini memiliki tingkat ketersediaan yang tinggi (*high availability*).

## 5. Langkah 3: Sentuhan Akhir Keamanan & Optimasi

Kubernetes deployment manifes adalah penentu akhir ketahanan sistem. Kita perlu mengatur *resource requests* dan *limits* yang presisi, serta mengonfigurasi Horizontal Pod Autoscaler (HPA) berbasis penggunaan memori kustom atau kueri kustom.

Berikut manifes `deployment.yaml` dan `hpa.yaml` yang siap pakai:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextjs-ssr-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nextjs-ssr
  template:
    metadata:
      labels:
        app: nextjs-ssr
    spec:
      containers:
      - name: nextjs
        image: your-docker-registry/nextjs-app:v1
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        env:
        - name: REDIS_URL
          value: "redis://redis-master.database.svc.cluster.local:6379"
        ports:
        - containerPort: 3000
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nextjs-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nextjs-ssr-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 75
```

## 6. Tes Rasa: Memastikan Semuanya Berjalan Sempurna

Saatnya menguji racikan kita. Jalankan `kubectl apply -f deployment.yaml` dan pantau status pod menggunakan:

```bash
kubectl get pods -l app=nextjs-ssr -w
```

Lakukan *load testing* menggunakan k6 atau Apache Bench untuk melihat bagaimana HPA merespons lonjakan trafik. Jika Anda melihat pod baru berputar secara otomatis saat memori menyentuh 75%, selamat! Arsitektur Anda sudah siap menghadapi badai trafik.

## 7. Pertolongan Pertama: Jika Terjadi Kendala Kendala Kecil

- **Problem:** Pod sering restart dengan status `OOMKilled` meski `--max-old-space-size` sudah diatur.
- **Solusi:** Kurangi nilai heap V8 sedikit (misal ke `1280` atau `1024`) karena kontainer juga membutuhkan ruang memori untuk overhead proses Node.js di luar V8 heap.
- **Problem:** Redis mengalami koneksi putus-putus di bawah beban tinggi.
- **Solusi:** Pastikan Anda mengaktifkan *connection pooling* dan konfigurasi `maxclients` yang cukup pada instance Redis.