Belajar GraphQL - Horizontal & Vertical Scaling Strategies
Episode 34 of 51

Belajar GraphQL - Horizontal & Vertical Scaling Strategies

Episode 34 membahas scaling GraphQL: vertical scaling dengan optimasi resource dan memory, horizontal scaling dengan load balancing dan stateless design, scaling database dengan read replicas dan PgBouncer, caching berlapis, scaling WebSocket subscriptions dengan Redis PubSub, hingga circuit breaker dan bulkhead pattern.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Traffic kalian naik — dan pertanyaannya bukan "apakah server akan jebol", tapi "kapan dan bagaimana menanganinya". Episode 34 membahas scaling GraphQL: menambah kekuatan mesin, menambah jumlah mesin, dan memastikan seluruh komponen dari database sampai WebSocket ikut naik.

Kita akan membahas vertical scaling, horizontal scaling, scaling database, caching berlapis, scaling subscriptions, dan pola ketahanan seperti circuit breaker dan bulkhead.

Vertical Scaling

Resource dan Node.js Tuning

Vertical scaling menambah resource pada satu mesin — cara termudah, tapi punya batas. Langkah yang masuk akal sebelum pindah ke horizontal:

  • Naikkan CPU dan memori instance.
  • Batasi ukuran request HTTP dan payload GraphQL.
  • Atur batas memori dan concurrency Node.js.
Batasi memori Node
{
  "scripts": {
    "start": "node --max-old-space-size=2048 dist/index.js"
  }
}

Optimasi lain: DataLoader batching (episode 9), caching (episode 19-20), dan pemangkasan query kompleks (episode 15) mengurangi beban per request sehingga satu mesin bisa melayani lebih banyak.

Horizontal Scaling

Load Balancing dan Stateless Design

Horizontal scaling menambah jumlah instance di belakang load balancer:

Load balancing GraphQL
client -> load balancer -> instance 1
                        -> instance 2
                        -> instance 3

Syarat utama: server harus stateless — jangan simpan session atau cache di memori lokal instance. Semua state bersama diletakkan di Redis:

  • Cache query dan field: Redis (episode 20).
  • State autentikasi: JWT (stateless by nature, episode 13).
  • Subscriptions: Redis PubSub agar peristiwa tersebar antar instance.

Jalankan beberapa instance dengan cluster pm2 start dist/index.js -i max.

Load balancer (nginx, ALB, atau Kubernetes Service) mendistribusikan request. Konsistensi diperoleh karena tidak ada state lokal yang harus dijaga sinkron.

Database Scaling

Read Replicas dan Connection Pooling

Database sering menjadi bottleneck pertama. Strateginya:

  • Read replicas: pisahkan read (query GraphQL) dari write (mutation) dengan mengarahkan read ke replica.
  • Connection pooling: setiap instance membuka banyak koneksi; pooler seperti PgBouncer memusatkan koneksi ke database.
  • Sharding: pecah data ke beberapa database berdasarkan key — kompleks dan jadi pilihan terakhir.
Jalankan PgBouncer
docker run -d --name pgbouncer \
  -e DB_HOST=db-primary -e DB_USER=app -e DB_PASSWORD=pass \
  -p 6432:5432 edoburu/pgbouncer

Koneksi aplikasi diarahkan ke PgBouncer (localhost:6432) sebagai ganti database langsung. Ini sangat penting di lingkungan serverless (episode 37) di mana koneksi dibuka tutup terus-menerus.

Caching Layers dan WebSocket Scaling

Multi-Tier Caching

Cache di beberapa lapisan untuk memotong beban database:

  • CDN: cache query publik di edge (episode 20).
  • Redis cluster: cache aplikasi yang terdistribusi, dengan eviction dan TTL.
  • Database cache: pola akses berulang dipangkas di tingkat query.

Untuk invalidation di skala besar, gunakan pola event-based: mutation mem-publish event (episode 16) dan cache dihapus secara terpusat, bukan mengandalkan TTL semata.

WebSocket dan Subscriptions Scaling

Subscriptions yang melibatkan WebSocket membutuhkan perhatian khusus:

  • Sticky sessions agar koneksi WebSocket tetap di instance yang sama, atau
  • Redis PubSub (episode 16) yang menyebarkan peristiwa ke semua instance — ini lebih robust karena tidak bergantung pada afinitas instance.
JSRedis PubSub lintas instance
import { RedisPubSub } from "graphql-redis-subscriptions";
 
const pubsub = new RedisPubSub({
  publisher: new Redis(process.env.REDIS_URL),
  subscriber: new Redis(process.env.REDIS_URL),
});

Koneksi WebSocket dikelola dengan graphql-ws (episode 16) di tiap instance; peristiwa dari mutation mana pun menyebar lewat Redis sehingga semua client menerimanya. Batasi juga jumlah koneksi per user dan gunakan heartbeat untuk membersihkan koneksi mati.

Performance at Scale

Circuit Breaker dan Bulkhead

Di skala besar, kegagalan satu komponen jangan sampai melumpuhkan semuanya:

  • Circuit breaker: jika dependency (misalnya payment API) gagal berulang kali, "buka" sirkuit dan gagalkan cepat tanpa menunggu timeout.
  • Bulkhead: pisahkan kumpulan koneksi per service, sehingga satu service yang lambat tidak menghabiskan semua koneksi.
JSBulkhead untuk database
import { Pool } from "pg";
 
const userPool = new Pool({ connectionString: DB_URL, max: 10 });
const orderPool = new Pool({ connectionString: DB_URL, max: 5 });

Pola-pola ketahanan ini akan kita perdalam di episode 35 bersama strategi high availability.

Penutup

Inti yang harus dibawa pulang:

  • Vertical scaling cepat tapi terbatas; horizontal scaling adalah jalan jangka panjang.
  • Stateless design dengan Redis adalah syarat scaling horizontal.
  • Read replicas dan PgBouncer meringankan beban database.
  • Cache berlapis memangkas beban di setiap lapisan.
  • Redis PubSub membuat subscriptions terdistribusi lintas instance.
  • Circuit breaker dan bulkhead menjaga ketahanan di skala besar.

Di episode 35 selanjutnya kalian akan mempelajari disaster recovery dan high availability — desain multi-region dan failover, strategi backup dengan point-in-time recovery, perencanaan disaster recovery dengan RTO dan RPO, circuit breaker pattern, hingga graceful degradation dengan feature flags. API kalian akan tahan banting!

Belajar GraphQL - Horizontal & Vertical Scaling Strategies | Belajar GraphQL