mdashikjs/blog
All posts
API Gateway Patterns with Kong in Production
System Design

API Gateway Patterns with Kong in Production

System Design5 min

API Gateway Patterns with Kong in Production

Without an API gateway, every microservice reimplements authentication, rate limiting, and logging. Kong centralizes these concerns so your services can focus on business logic.

API GatewayKongMicroservicesSystem Design
Share:

What an API gateway does

An API gateway sits between clients and your microservices. It handles:

  • Routing: /api/users/* goes to the user service, /api/orders/* goes to the order service
  • Authentication: verify JWTs before requests reach any service
  • Rate limiting: enforce per-consumer limits in one place
  • Logging: capture request metadata for every API call
  • Transformation: add, remove, or modify headers and bodies

Why Kong

Kong is built on Nginx and runs as a reverse proxy. It is fast (sub-millisecond overhead for most plugins), extensible (200+ plugins), and can run in DB-less mode with declarative configuration.

Declarative configuration

# kong.yaml
_format_version: "3.0"

services:
  - name: user-service
    url: http://user-service:3000
    routes:
      - name: user-routes
        paths:
          - /api/users
        strip_path: false
    plugins:
      - name: rate-limiting
        config:
          minute: 100
          policy: redis
          redis_host: redis

  - name: order-service
    url: http://order-service:3000
    routes:
      - name: order-routes
        paths:
          - /api/orders
        strip_path: false

plugins:
  - name: jwt
    config:
      claims_to_verify:
        - exp
  - name: correlation-id
    config:
      header_name: X-Trace-Id
      generator: uuid
  - name: file-log
    config:
      path: /dev/stdout
      reopen: true

This configuration routes two services, enforces JWT authentication globally, adds trace IDs, logs every request, and rate-limits the user service at 100 requests per minute.

JWT authentication

Kong validates JWTs without your services knowing. The flow:

  1. Client sends Authorization: Bearer <token>
  2. Kong validates the signature, expiration, and issuer
  3. If valid, Kong forwards the request with decoded claims in headers
  4. If invalid, Kong returns 401 — the request never reaches your service
consumers:
  - username: mobile-app
    jwt_secrets:
      - algorithm: RS256
        key: mobile-app-iss
        rsa_public_key: |
          -----BEGIN PUBLIC KEY-----
          ...
          -----END PUBLIC KEY-----

Rate limiting with Redis

For multiple Kong instances behind a load balancer, use Redis-backed rate limiting:

plugins:
  - name: rate-limiting
    config:
      minute: 1000
      hour: 10000
      policy: redis
      redis_host: redis
      redis_port: 6379
      redis_database: 0
      fault_tolerant: true

fault_tolerant: true means if Redis is down, requests pass through unthrottled rather than being blocked. This is the right choice for most systems — rate limiting is a protection, not a gate.

Health checks and circuit breaking

Kong can health-check upstream services and stop routing to unhealthy ones:

services:
  - name: user-service
    url: http://user-service:3000
    connect_timeout: 5000
    read_timeout: 10000
    retries: 2
    healthchecks:
      active:
        http_path: /health
        interval: 10
        healthy:
          successes: 3
        unhealthy:
          http_failures: 3

The deployment pattern

Client → Kong (gateway) → Service A
                       → Service B
                       → Service C

Kong runs as a Kubernetes Ingress Controller or as standalone Docker containers. We run it in DB-less mode — the YAML config is mounted as a ConfigMap. Changes go through Git, reviewed like code.

When not to use an API gateway

If you have fewer than three services, an API gateway adds complexity without proportional benefit. A simple Nginx reverse proxy or even Next.js API routes can handle routing and auth for a small system.

MA

Written by Md Ashik

Senior Software Engineer building reliable backends. I write about the practical tradeoffs behind shipping software that holds up in production.