Skip to content
Logo
arrow_backBackKembali

API Gateway — Enterprise Pattern

Microservice architectures introduce a fundamental problem: how do you centrally manage authentication, rate limiting, and failure isolation without coupling every service to shared infrastructure? Most solutions reach for Kong, NGINX, or Envoy — but understanding the patterns themselves requires building them from scratch.

Three Enterprise Patterns, Zero Dependencies

  • JWT Authentication — HMAC-SHA256 token signing and verification using only Node.js crypto module, with timingSafeEqual preventing timing attacks. Issues demo tokens at /auth/token.
  • Sliding Window Rate Limiter — per-client request counting in SQLite with automatic window cleanup. Configurable per-route limits (e.g. 100 req/min for /api/users). Returns x-ratelimit-remaining headers on every response.
  • Circuit Breaker — per-service failure tracking. After 5 consecutive failures, the circuit opens and requests return HTTP 503 without touching the upstream. After 30s timeout, transitions to half-open for recovery testing.

Architecture

Client Bearer Token API Gateway Auth → Rate Limit → Circuit → Proxy Native Node.js (http + crypto + better-sqlite3) SQLite (gateway.db) Clients · Rate Limits · Circuit States Service 1 (Users) :3001 Service 2 (Orders) :3002 Docker Compose: Gateway + 2 Services (bridge network) Local dev: node server.js | Production: docker compose up

Design Decisions

  • Zero-dependency HTTP — Uses native node:http for both server and proxy. No Express, no Axios, no node-fetch. This is deliberate: it eliminates a whole class of supply-chain vulnerabilities and keeps the gateway ~300 lines of code.
  • JWT without libraries — HMAC-SHA256 via node:crypto. The timingSafeEqual call prevents timing side-channel attacks. Token payload includes sub (client API key) and iat (issued at).
  • SQLite for state — Rate limit counters and circuit states survive restarts. The rate limiter runs a DELETE query on each request to keep the window table bounded — old entries are pruned automatically.
  • Dual-mode deployment — Runs natively on any Node.js host (Fly.io, VPS) or containerized via Docker Compose with TARGET_HOST environment variable.

Quick Start

  # Local dev
  node services/service1.js &
  node services/service2.js &
  node server.js

  # Get token
  $ curl -X POST http://localhost:8080/auth/token
  {"token":"eyJ..."}

  # Proxy!
  $ curl http://localhost:8080/api/users -H "Authorization: Bearer <token>"
  {"service":"users","data":[{"id":1,"name":"Alice",...}]}

  # Docker
  $ docker compose up --build

Key Metrics

  • Proxy overhead: <50ms per request (local network)
  • Rate limiter: 100 req/min default, configurable per-route
  • Circuit breaker: opens after 5 consecutive failures, resets after 30s
  • Deployment: Docker Compose (3 containers) or standalone Node.js
Stack
Node.jsSQLiteJWTDockerFly.io
Zero-frameworkJWTCircuit Breaker