# Arsitektur Resilien Next.js SSR dengan Edge Caching Cloudflare

> Diterbitkan oleh Literally Web ID pada 20 Oct 2026
> Sumber: https://literally.web.id/articles/arsitektur-resilien-nextjs-ssr-dengan-edge-caching-cloudflare

---

## 1. Alarm Tengah Malam: Saat Layanan Produksi Mulai Tumbang

Pukul 02.14 WIB. PagerDuty di ponsel saya menjerit melengking, membangunkan tidur nyenyak saya dengan ritme yang hanya bisa diartikan satu hal: produksi sedang sekarat. Sembari menyapu mata, saya membuka laptop di atas meja kerja yang remang-remang. Dashboard Grafana menampilkan pemandangan yang membuat jantung berdegup kencang: latensi *p99* loncat dari biasanya 180 milidetik menjadi lebih dari 8.50onan detik, sementara *Error Rate* HTTP 504 Gateway Timeout merangkak naik menyentuh angka 42%. Di saat yang sama, kluster Kubernetes yang menjalankan aplikasi Node.js kami berteriak minta tolong karena utilisasi CPU menembus batas kritis 98%, disusul oleh metrik *connection pool* database MySQL yang jebol akibat antrean ribuan koneksi paralel yang menggantung.

```bash
# Pengecekan awal kesehatan pod Kubernetes saat insiden
kube-ctl get pods -n production | grep nextjs-ssr
# Hasilnya mencengangkan: 12 dari 15 pod mengalami OOMKilled atau restart loop secara konstan
```

Pengguna di luar sana mengeluh tidak bisa mengakses halaman utama portal e-commerce kami yang sedang menggelar kampanye flash sale tengah malam. Beban trafik melonjak hingga 45.000 req/s, melampaui kapasitas normal harian sebanyak sepuluh kali lipat. Namun, yang membuat saya penasaran bukanlah tingginya volume trafik itu sendiri, melainkan mengapa aplikasi Next.js dengan fitur Server-Side Rendering (SSR) yang biasanya tangguh ini mendadak kolaps begitu cepat. Untuk menjawab misteri ini, kita harus menyelami apa yang sebenarnya terjadi di balik layar mesin Node.js ketika ribuan request masuk secara bersamaan.

## 2. Jejak Digital: Menelusuri Anomali Log & Lonjakan Metrik

Tanpa membuang waktu, saya langsung melompat ke terminal untuk mengekstrak log akses dari Nginx *reverse proxy* yang berada di garda terdepan sebelum trafik diteruskan ke aplikasi Node.js. Menggunakan mantra *awk* dan *grep* kesayangan, saya menyaring pola akses yang masuk pada detik-detik sebelum alarm berbunyi.

```bash
# Membedah log Nginx untuk mencari URL yang paling sering direquest dan membebani server
cat /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -n 10
```

Hasilnya langsung menunjuk pada halaman produk dan kategori utama. Masalahnya, meskipun halaman-halaman tersebut dirender secara dinamis menggunakan `getServerSideProps` di Next.js untuk mengambil data stok real-time dari database MySQL, setiap request ternyata memaksa Node.js melakukan eksekusi JavaScript yang berat secara berulang-ulang. Tidak ada satupun *byte* respons yang singgah di *cache layer* luar. Akibatnya, setiap kali seorang pengguna merefresh halaman, Node.js harus memproses ulang komponen React, melakukan *serialization* HTML, dan memanggil kueri SQL yang sama persis ke database secara masif. Ini adalah definisi klasik dari *Anatomi SSR Bottleneck di Node.js*—di mana arsitektur SSR yang tidak diimbangi dengan strategi caching yang tepat berubah menjadi bumerang yang mencekik backend-nya sendiri. Database MySQL kami kewalahan melayani pembacaan berulang, *connection pool* habis terkuras, dan Node.js yang sifatnya *single-threaded* langsung kehabisan napas memproses beban CPU yang tidak perlu ini. Dari sinilah, jejak digital mengarahkan kita pada akar masalah yang sebenarnya.

## 3. Membongkar Biang Kerok: Akar Masalah yang Sebenarnya

Setelah menggali lebih dalam ke dalam kode sumber dan konfigurasi infrastruktur, kami menemukan tiga dosa besar arsitektur yang saling bersekongkol menjatuhkan sistem:

1. **Absennya Edge Caching**: Cloudflare dikonfigurasi secara naif hanya meneruskan seluruh trafik dinamis langsung ke origin server tanpa instruksi *cache* yang jelas melalui header `Cache-Control`. Setiap request dianggap unik dan *bypass* total dari jaringan global Cloudflare.
2. **Kueri Database yang Redundan**: Di dalam fungsi `getServerSideProps`, terdapat pemanggilan kueri SQL kompleks tanpa memanfaatkan *in-memory cache* seperti Redis untuk data referensi yang sifatnya semi-statis.
3. **Kesalahpahaman Konsep ISR**: Tim sebelumnya mencoba mengandalkan Incremental Static Regeneration (ISR), namun gagal menerapkannya pada halaman dengan trafik tinggi karena salah mengatur parameter `revalidate` dan mengabaikan karakteristik invalidasi di tingkat edge CDN.

> [!WARNING]
> Mengandalkan SSR murni tanpa lapisan *edge caching* pada platform berskala besar adalah undangan terbuka bagi bencana latensi dan kegagalan infrastruktur total.

Untuk mengatasi hal ini, kita harus mengubah paradigma: jangan biarkan *origin server* Node.js bekerja keras untuk hal-hal yang bisa dilayani oleh *edge server* Cloudflare yang tersebar di ratusan kota di seluruh dunia. Mari kita lihat bagaimana kita merombak total strategi pertahanan ini.

## 4. Tindakan Darurat: Menghidupkan Kembali Layanan dalam Hitungan Menit

Di tengah situasi genting, kami memerlukan tindakan bedah darurat yang bisa dieksekusi dalam hitungan detik untuk menyelamatkan sistem dari kehancuran total. Langkah pertama adalah memaksa Cloudflare untuk menahan beban dengan mengaktifkan *Cache Everything* secara agresif melalui *Cloudflare Page Rules* dan menyuntikkan header `Cache-Control` yang tepat langsung dari aplikasi Next.js.

Berikut adalah cuplikan kode pada file konfigurasi Next.js (`next.config.js`) atau pada fungsi SSR untuk memaksa browser dan Cloudflare melakukan *edge caching* dengan mekanisme *Stale-While-Revalidate*:

```javascript
// next.config.js atau penanganan header respons kustom di middleware Next.js
export async function middleware(req) {
  const res = NextResponse.next();
  
  // Beritahu Cloudflare dan Browser untuk menyimpan cache halaman selama 60 detik,
  // dan tetap melayani versi stale selama 60 detik berikutnya saat background revalidation berjalan.
  res.headers.set(
    'Cache-Control',
    'public, s-maxage=60, stale-while-revalidate=60'
  );
  
  return res;
}
```

Selain itu, untuk meredakan amukan trafik pada database MySQL, kami segera mengaktifkan kembali Redis sebagai lapisan penengah data referensi:

```go
// Contoh implementasi singkat koneksi Redis di backend Go/Node untuk caching data referensi
const getCachedProductData = async (productId) => {
  const cachedData = await redisClient.get(`product:${productId}`);
  if (cachedData) {
    return JSON.parse(cachedData);
  }
  
  const freshData = await db.query('SELECT * FROM products WHERE id = ?', [productId]);
  await redisClient.setex(`product:${productId}`, 30, JSON.stringify(freshData));
  return freshData;
};
```

> [!TIP]
> Penggunaan header `s-maxage` bersama `stale-while-revalidate` adalah senjata paling ampuh untuk meredam lonjakan trafik mendadak tanpa mengorbankan kesegaran data bagi pengguna akhir.

Dengan menerapkan one-liner pembersihan cache di Cloudflare API dan memperbarui header respons tersebut, kurva latensi di Grafana mulai melandai drastis dalam waktu kurang dari 3 menit setelah deployment darurat disebar.

## 5. Kebijakan Retrospektif: Menambal Celah agar Tak Pernah Terulang

Badai telah berlalu, kini saatnya duduk bersama tim untuk merumuskan kebijakan defensif jangka panjang agar insiden serupa tidak terulang di masa depan. Kami menyadari bahwa arsitektur web modern menuntut pergeseran dari *pure SSR* ke *Edge-First Architecture*.

Berikut adalah perbandingan strategi caching yang kini kami adopsi secara ketat:

| Aspek Evaluasi | Sebelum Insiden (Naif SSR) | Sesudah Perbaikan (Edge-Resilient SSR) |
| :--- | :--- | :--- |
| **Lokasi Render** | 100% di Origin Node.js | Hybrid: Edge CDN + Background ISR |
| **Beban Database MySQL** | Tinggi (Kueri masif per request) | Rendah (Teredam Redis & Edge Cache) |
| **Header Cache-Control** | Tidak terdefinisi / `no-cache` | `public, s-maxage=60, stale-while-revalidate=60` |
| **Latensi p99** | > 8500 ms | < 220 ms |

Kami juga memperketat aturan *code review* di mana setiap penambahan halaman baru yang menggunakan `getServerSideProps` wajib menyertakan dokumen spesifikasi strategi *cache* dan persetujuan dari tim infrastruktur. Dengan cara ini, kolaborasi antara frontend dan infrastructure engineer menjadi lebih erat dan terarah.

## 6. Pasang Alarm: Otomasi Deteksi Dini untuk Tim On-Call

Sebagai penutup dari rangkaian mitigasi ini, kami tidak ingin lagi bergantung pada laporan pengguna atau lonjakan error yang terlambat disadari. Kami membangun sistem monitoring proaktif menggunakan Prometheus dan Alertmanager yang terintegrasi langsung dengan webhook PagerDuty.

Berikut adalah aturan *alerting* Prometheus yang kami pasang untuk mendeteksi dini anomali pada latensi *edge* dan tingkat error *gateway* sebelum mereka berubah menjadi bencana tengah malam:

```yaml
groups:
  - name: edge-ssr-alerts
    rules:
      - alert: HighEdgeLatencyP99
        expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 0.5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Latensi p99 melebihi 500ms selama 2 menit berturut-turut!"
          description: "Aplikasi Next.js mengalami perlambatan signifikan di edge atau origin. Segera periksa metrik CPU dan database connection pool."

      - alert: SpikeHTTP504GatewayTimeout
        expr: sum(rate(http_requests_total{status="504\