tutorial

70 Load Balancing dan Scaling graphql-go

70 Load Balancing dan Scaling graphql-go

Di era aplikasi modern, skalabilitas dan distribusi beban kerja bukan lagi sekadar pilihan, melainkan kebutuhan. Apalagi bila API core Anda berjalan di GraphQL dengan library seperti graphql-go. Mengapa banyak developer masih terjebak di pola scaling konvensional? Apa saja tantangan load balancing pada GraphQL? Yuk kita bedah bersama secara teknis!


Mengapa Perlu Load Balancing di GraphQL?

GraphQL memberikan client kebebasan memilih data yang dibutuhkan. Implikasinya, satu endpoint bisa memproses query sederhana sampai komplek, dengan beban komputasi sangat beragam. Ini berbeda dengan REST API tradisional yang cenderung predictable.

Saat trafik pengguna bertambah, single instance GraphQL tak lagi reliabel: request antrian, timeout, bahkan crash. Maka solusi mendasar: scaling dan load balancing.

Skema Scaling graphql-go

graphql-go adalah library idiomatik untuk membangun GraphQL server di Go. Secara default, endpoint GraphQL berjalan single process. Kita punya tiga pilihan skema scaling:

  1. Vertical Scaling
    Upgrade resource server (CPU/RAM lebih besar).
  2. Horizontal Scaling
    Jalankan beberapa instance aplikasi di banyak mesin/VM/container sekaligus.
  3. Hybrid
    Kombinasi vertical & horizontal, optimal secara cost dan performa.

Load Balancing: Alur Proses

Mari kita visualisasikan alurnya. Asumsikan service kita sudah di-containerize (misal Docker), dan berjalan di 3 instance.

graph LR
    A[Client] -->|HTTP Request| B[Load Balancer]
    B --> I1[graphql-go Instance 1]
    B --> I2[graphql-go Instance 2]
    B --> I3[graphql-go Instance 3]
    I1 --> R[Database/API]
    I2 --> R
    I3 --> R

Penjelasan:

  • Request client mendarat di Load Balancer (misal: Nginx, HAProxy, ALB AWS)
  • Load balancer mendistribusikan request ke salah satu instance graphql-go (round-robin, least-connections, dsb)
  • Setiap instance berkomunikasi ke resource backend (database, etc)

Studi Kasus: Load Balancing dengan Nginx

Mari kita simulasikan skenario sederhana load balancing instance GraphQL di Go menggunakan Nginx.

Langkah 1: Bootstrap Program graphql-go

Setup sederhana API GraphQL dalam 1 file:

package main

import (
    "log"
    "net/http"
    "os"
    "github.com/graphql-go/graphql"
    "github.com/graphql-go/handler"
)

var schema, _ = graphql.NewSchema(
    graphql.SchemaConfig{
        Query: graphql.NewObject(
            graphql.ObjectConfig{
                Name: "RootQuery",
                Fields: graphql.Fields{
                    "hello": &graphql.Field{
                        Type: graphql.String,
                        Resolve: func(params graphql.ResolveParams) (interface{}, error) {
                            // Gunakan env untuk instance label
                            instance := os.Getenv("INSTANCE_NAME")
                            return "Hello from " + instance, nil
                        },
                    },
                },
            },
        ),
    },
)

func main() {
    instance := os.Getenv("INSTANCE_NAME")
    h := handler.New(&handler.Config{
        Schema:   &schema,
        Pretty:   true,
        GraphiQL: true,
    })

    addr := ":8080"
    log.Printf("%s berjalan di %s", instance, addr)
    http.Handle("/graphql", h)
    log.Fatal(http.ListenAndServe(addr, nil))
}

Catatan:
Jalankan tiga instance server dengan env berbeda, misal INSTANCE_NAME=app1, app2, dst.

Langkah 2: Nginx Sebagai Load Balancer

http {
    upstream graphql_upstream {
        server 127.0.0.1:8081;
        server 127.0.0.1:8082;
        server 127.0.0.1:8083;
    }

    server {
        listen 8000;

        location /graphql {
            proxy_pass http://graphql_upstream;
            proxy_set_header Host $host;
        }
    }
}

Jalankan ketiga instance di port 8081, 8082, dan 8083. Kemudian request GraphQL bisa diarahkan ke localhost:8000/graphql.

Simulasi: Load Test Simple

Uji distribusi request dengan curl:

for i in {1..6}; do
  curl -s -X POST \
  -H "Content-Type: application/json" \
  --data '{"query":"{ hello }"}' \
  http://localhost:8000/graphql
done

Output akan saling bergantian:
Hello from app1, lalu Hello from app2, Hello from app3, dan seterusnya — membuktikan round robin berjalan.


Scaling: Challenge & Solution

Tantangan Besar

  1. Stateful vs Stateless
    Setiap instance harus stateless. Jangan simpan session di memory, gunakan Redis/DB untuk session/state sharing.
  2. Caching Layer
    GraphQL kadang query berulang. Caching bisa dilakukan di resolvers (misal Redis), atau via response HTTP cache.
  3. Database Connection Pool
    Terlalu banyak instance bisa over-limit database! Gunakan pool atau tools seperti PgBouncer (PGSQL).
  4. Healthcheck
    Load balancer wajib cek health endpoint sebelum mendistribusikan traffic.
  5. Respon Lambat akibat N+1 query problem
    Gunakan DataLoader pattern.

Tabel: Perbandingan Skema

MetodeKelebihanKekuranganSkenario Ideal
Vertical ScalingImplementasi cepatBiaya tinggi, limit fisikBeban naik gradual
Horizontal ScalingMudah autoscalePerlu load balancer, stateAplikasi stateless
HybridFleksibel, cost efisienImplementasi kompleksGrowth unpredictable

Best Practices Load Balancing & Scaling graphql-go

  1. Stateless First:
    Semua instance replaceable. Gunakan env/config central, hindari local cache/temporary file.
  2. Monitor Pooling Database:
    Tuning max_connections & gunakan middle-layer low overhead (ex: PgBouncer).
  3. Automasi Scaling:
    Orkestrasi dengan Docker Swarm, Kubernetes, ECS, etc.
    Minimalis downtime.
  4. Observability:
    Implement metrics & tracing (OpenTelemetry, Prometheus), pantau bottleneck tiap query.
  5. Health Check Endpoint:
    Sediakan /healthz yang cepat untuk load balancer.

Diagram: Scaling di Kubernetes

graph TD
  A[Client] --> LB[Ingress/Load Balancer]
  LB --> D1[Pod: graphql-go-1]
  LB --> D2[Pod: graphql-go-2]
  LB --> D3[Pod: graphql-go-n]
  D1 --> DB[(Database)]
  D2 --> DB
  D3 --> DB
  style DB fill:#f9f,stroke:#333,stroke-width:2px

Kesimpulan

Load balancing dan scaling pada aplikasi GraphQL di Go (graphql-go) bukan sekadar menambah replica, tapi menuntut desain arsitektur yang stateless, observability kuat, dan database-aware.
Dengan strategi yang tepat, aplikasi Anda siap menangani lonjakan trafik — sambil tetap lincah dan stabil.

Andai besok pagi tiba-tiba traffic naik 10x, yakin arsitektur GraphQL Anda sudah siap scale?
Let’s make your system load-proof—go beyond single instance!


Referensi:

Sekian, happy scaling! 🚀

comments powered by Disqus