API gateway adalah pintu masuk tunggal (single entry point) untuk semua request dari client ke service-service di belakangnya. Dia meneruskan tiap request ke service yang tepat, dan sekalian mengurus hal yang dibutuhkan semua service: cek login, membatasi request, dan mencatat log. Bayangin resepsionis gedung kantor. Tamu cuma tahu satu pintu. Resepsionis mengecek KTP, menunjukkan lantai yang dituju, menolak orang yang datang 50 kali sejam, dan mencatat buku tamu. Tapi kalau resepsionisnya cuma satu dan dia sakit, gak ada tamu yang bisa masuk.
🧪 Tebakan cepat: halaman "Pesanan saya" di aplikasi HP TiketNada butuh data dari dua service, dan satu kali bolak-balik HP ke server makan 80 ms. Kalau gateway yang menggabungkan dua panggilan itu, halamannya lebih cepat berapa: 2 ms, 82 ms, atau 160 ms? Tebak dulu, jawabannya ada di bagian "Agregasi: satu request, dua service".
Tanpa gateway: client tahu semua alamat
TiketNada sekarang punya beberapa service: konser, order, bayar, dan akun. Tanpa gateway, aplikasi HP harus tahu alamat masing-masing:
https://konser.tiketnada.test/events/42
https://order.tiketnada.test/orders
https://bayar.tiketnada.test/charges
https://akun.tiketnada.test/me
Masalahnya: tiap service harus mengecek login sendiri (empat kali kode yang sama, empat kali peluang salah), rate limit gak seragam, dan begitu satu service pindah alamat atau dipecah, aplikasi HP yang sudah terpasang di jutaan ponsel ikut rusak.
Routing: satu pintu, banyak service
Dengan gateway, client cuma kenal satu alamat: https://api.tiketnada.test. Gateway punya tabel routing: method dan awalan path menentukan service tujuan.
| Request | Diteruskan ke | Butuh login |
|---|---|---|
GET /api/events/42 |
konser |
gak (halaman publik) |
POST /api/orders |
order |
ya |
GET /api/me/orders |
order lalu konser |
ya |
Client gak perlu tahu ada berapa service di belakang. Service konser mau ditulis ulang di Go? Cukup ubah tabelnya.
Auth di pintu masuk
Gateway memeriksa token di header Authorization sekali, sebelum request menyentuh service mana pun. Token gak ada atau gak sah? Gateway langsung menjawab 401 Unauthorized, dan service order gak menerima apa-apa. Token sah? Gateway meneruskan request dengan identitas user-nya, misalnya header X-User-Id: 7.
Ini authentication (siapa kamu). Authorization (boleh gak kamu melakukan ini, misalnya membatalkan pesanan orang lain) tetap dicek di service, karena cuma service yang tahu pesanan itu milik siapa.
Rate limiting: membatasi request
Rate limiting adalah membatasi jumlah request per user atau per IP dalam periode tertentu, untuk mencegah abuse dan menjaga sistem tetap stabil. Saat war tiket, bot bisa mengirim ratusan pesanan per detik. Aturan TiketNada (model contoh): maksimal 5 POST /api/orders per 10 detik per user. Bot yang mengirim 12 pesanan dalam 10 detik dapat 5 jawaban 201, lalu 7 jawaban 429 Too Many Requests. Ketujuh request itu berhenti di gateway, gak membebani service order. Algoritma rate limit (fixed window, token bucket) dibahas di lesson Rate Limiting (track API).
Ini gateway TiketNada sebagai model kecil yang bisa dijalankan:
// API gateway TiketNada (model contoh)
const routes = [
{ method: "GET", prefix: "/api/events", service: "konser", publik: true },
{ method: "POST", prefix: "/api/orders", service: "order", limit: 5 },
{ method: "GET", prefix: "/api/me/orders", service: "order + konser" },
];
const tokens = { "tok-budi": 7 }; // token sah -> user id
const WINDOW_MS = 10000; // jendela rate limit: 10 detik
const jendela = new Map(); // "user|path" -> { mulai, n }
function gateway(req) {
const route = routes.find((r) => r.method === req.method && req.path.startsWith(r.prefix));
if (!route) return { status: 404 };
const userId = tokens[req.token];
if (!route.publik && !userId) return { status: 401 }; // auth di pintu masuk
if (route.limit) {
const key = userId + "|" + route.prefix;
const w = jendela.get(key);
if (!w || req.t - w.mulai >= WINDOW_MS) jendela.set(key, { mulai: req.t, n: 1 });
else if (++w.n > route.limit) return { status: 429 }; // rate limit
}
return { status: req.method === "POST" ? 201 : 200, ke: route.service, userId };
}
console.log(gateway({ method: "POST", path: "/api/orders", t: 0 })); // { status: 401 }
for (let i = 0; i < 7; i++) {
const res = gateway({ method: "POST", path: "/api/orders", token: "tok-budi", t: i * 800 });
console.log(i + 1, res.status); // 1 sampai 5: 201, lalu 6 dan 7: 429
}
routes.find(...): routing. Method dan awalan path memilih service.tokens[req.token]: cek token. Di gateway sungguhan ini verifikasi tanda tangan JWT atau tanya ke serviceakun.if (!route.publik && !userId) return { status: 401 }: request tanpa login berhenti di sini.jendela: hitungan request per user per route dalam 10 detik. Yang keenam di jendela yang sama dapat429. Di produksi hitungan ini disimpan di tempat bersama seperti Redis, supaya semua instance gateway menghitung jendela yang sama.
Agregasi: satu request, dua service
Halaman "Pesanan saya" butuh daftar pesanan dari order (40 ms), lalu detail konsernya dari konser (30 ms). HP Budi di jaringan 4G butuh 80 ms untuk satu kali bolak-balik ke server, dan gateway menambah 2 ms.
| Tanpa agregasi | Dengan agregasi | |
|---|---|---|
| Request dari HP | 2 | 1 |
| Hitungan | (80 + 2 + 40) + (80 + 2 + 30) | 80 + 2 + 40 + 30 |
| Total | 234 ms | 152 ms |
Gateway memanggil kedua service di dalam data center, yang jaraknya cuma sekejap, lalu mengirim satu response gabungan. Jawaban tebakannya 82 ms: satu kali bolak-balik HP (80 ms) plus satu kali kerja gateway (2 ms) hilang.
Single point of failure
Semua request lewat gateway. Kalau TiketNada cuma menjalankan satu instance gateway dan instance itu mati, load balancer di depannya menjawab 503 Service Unavailable untuk semua request, padahal konser, order, dan bayar sehat semua. Itu single point of failure. Obatnya sama seperti server lain: jalankan minimal dua instance di belakang load balancer, dengan health check dan failover otomatis (lesson Load Balancing). Gateway juga bisa jadi bottleneck, jadi jaga dia tetap tipis: routing, auth, rate limit, log. Logika bisnis tetap di service.
🎯 Gateway yang dipakai orang
Kong, AWS API Gateway, Nginx, Traefik, dan Envoy bisa jadi API gateway. Kalau client-nya beragam (web, HP, partner), kadang tiap jenis client dapat gateway sendiri yang bentuk response-nya pas untuknya: Backend for Frontend (BFF). Pola ini dan pola lainnya dibahas di lesson API Gateway Patterns.
⚠️ Jebakan yang sering ketemu
- Gateway jadi monolith baru. Logika bisnis (hitung harga, cek stok) ditaruh di gateway. Tiap tim harus mengubah gateway, dan gateway yang gemuk jadi bottleneck.
- Cuma satu instance gateway. Satu mesin mati, seluruh API mati. Minimal dua, di belakang load balancer.
- Authentication di gateway, authorization dilupakan. Gateway tahu kamu Budi, tapi cuma service
orderyang tahu pesanan #1001 milik Budi atau bukan. Cek kepemilikan tetap di service. - Panggilan antarservice lewat gateway publik.
ordermemanggilbayarlewatapi.tiketnada.testmenambah hop dan antre di rate limit yang sama dengan pengguna. Panggilan internal lewat jaringan internal.
TL;DR: API gateway adalah single entry point: client cuma kenal api.tiketnada.test, dan gateway meneruskan request ke service yang tepat (routing), mengecek token sekali di pintu masuk (401 sebelum service tersentuh), membatasi request per user atau IP dalam periode tertentu (rate limiting: request keenam dalam 10 detik dapat 429), dan mencatat log. Agregasi menggabungkan dua panggilan service jadi satu request dari client: 234 ms jadi 152 ms. Risikonya: gateway adalah single point of failure dan bisa jadi bottleneck, jadi jalankan minimal dua instance di belakang load balancer dan jaga gateway tetap tipis. Authorization tetap dicek di service.