Skip to main content

API Gateways: Kong, Envoy, and Modern API Management

Created: March 12, 2026 Larry Qu 14 min read

Introduction

In microservices architectures, API gateways serve as the single entry point for all client requests. They handle cross-cutting concerns like authentication, rate limiting, request routing, and logging, allowing backend services to focus on business logic. In 2026, API gateways have evolved into sophisticated platforms that handle traffic management, security, and observability at scale.

This comprehensive guide explores API gateways in depth, covering architecture patterns, popular solutions like Kong and Envoy, configuration strategies, and best practices for building robust API infrastructure.

API Gateway Architecture

Core Functions

┌─────────────────────────────────────────────────────────────────────┐
│                      API Gateway Functions                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                      API Gateway                             │   │
│  │                                                              │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  │   │
│  │  │ Auth &   │  │ Rate     │  │ Request  │  │ Load     │  │   │
│  │  │ Security │  │ Limiting  │  │ Transform│  │ Balancing│  │   │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘  │   │
│  │                                                              │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  │   │
│  │  │ Logging  │  │ Caching   │  │ Circuit  │  │ Protocol │  │   │
│  │  │ & Metrics│  │          │  │ Breaker  │  │ Translation│ │   │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘  │   │
│  │                                                              │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│        ┌─────────────────────┼─────────────────────┐              │
│        ▼                     ▼                     ▼              │
│   ┌─────────┐          ┌─────────┐          ┌─────────┐           │
│   │ Service │          │ Service │          │ Service │           │
│   │    A   │          │    B   │          │    C   │           │
│   └─────────┘          └─────────┘          └─────────┘           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Deployment Patterns

class APIGatewayDeployment:
    @staticmethod
    def centralized_gateway():
        return {
            "pattern": "Centralized Gateway",
            "description": "Single API gateway handles all requests",
            "pros": [
                "Single entry point for all APIs",
                "Consistent security and policies",
                "Simple client integration"
            ],
            "cons": [
                "Single point of failure",
                "Scaling limitations",
                "Complex gateway logic"
            ]
        }
    
    @staticmethod
    def distributed_gateways():
        return {
            "pattern": "Distributed Gateways",
            "description": "Multiple API gateways deployed close to services",
            "pros": [
                "Lower latency",
                "Better fault isolation",
                "Independent scaling"
            ],
            "cons": [
                "Policy consistency challenges",
                "More complex operations",
                "Increased infrastructure"
            ]
        }
    
    @staticmethod
    def hybrid_approach():
        return {
            "pattern": "Hybrid",
            "description": "Edge gateway + internal service mesh",
            "pros": [
                "Best of both worlds",
                "Optimized for different use cases"
            ],
            "cons": [
                "Complex architecture",
                "Requires expertise in multiple technologies"
            ]
        }

Kong API Gateway

Kong is the most popular open-source API gateway, built on Nginx and Lua.

Kong Installation and Configuration

# docker-compose.yml for Kong
version: '3.8'

services:
  kong-database:
    image: postgres:13
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: kong
    volumes:
      - kong-db:/var/lib/postgresql/data
    networks:
      - kong-net

  kong:
    image: kong:3.4
    depends_on:
      - kong-database
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kong
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
    ports:
      - "8000:8000"
      - "8443:8443"
      - "8001:8001"
    networks:
      - kong-net
    volumes:
      - ./kong.yml:/usr/local/kong/declarative/kong.yml

  kong-migrations:
    image: kong:3.4
    depends_on:
      - kong-database
    command: kong migrations bootstrap
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kong

volumes:
  kong-db:

networks:
  kong-net:
    driver: bridge

Kong Services and Routes

# Create a service
curl -X POST http://localhost:8001/services/ \
  --data name=user-service \
  --data url=http://user-service:8000 \
  --data protocol=http

# Add route to service
curl -X POST http://localhost:8001/services/user-service/routes/ \
  --data name=user-service-route \
  --data paths[]=/api/users \
  --data strip_path=true

# Add plugins to service
curl -X POST http://localhost:8001/services/user-service/plugins/ \
  --data name=rate-limiting \
  --data config.minute=100 \
  --data config.policy=local

Kong Plugins

# Kong plugin configuration examples

# Rate Limiting
rate_limiting_config = {
    "name": "rate-limiting",
    "config": {
        "minute": 100,
        "hour": 1000,
        "policy": "redis",
        "redis_host": "redis-service",
        "redis_port": 6379,
        "hide_client_headers": False
    }
}

# Authentication
jwt_auth_config = {
    "name": "jwt",
    "config": {
        "uri_param_names": ["jwt"],
        "cookie_names": [],
        "header_names": ["Authorization"],
        "claims_to_verify": ["exp", "iat"],
        "maximum_expiration": 3600
    }
}

# Request Transformation
request_transform_config = {
    "name": "request-transformer",
    "config": {
        "add": {
            "headers": ["X-Gateway-Version:1.0"]
        },
        "remove": {
            "headers": ["X-Internal-Debug"]
        },
        "rename": {
            "headers": {"X-Old-Name": "X-New-Name"}
        },
        "replace": {
            "body": {"oldString": "newString"}
        }
    }
}

# Response Caching
caching_config = {
    "name": "proxy-cache",
    "config": {
        "request_method": ["GET", "HEAD"],
        "content_type": ["application/json"],
        "cache_ttl": 300,
        "strategy": "memory",
        "memory": {
            "cache_ttl": 300,
            "max_size": "100m"
        }
    }
}

Kong with Declarative Configuration

# kong.yml - Declarative configuration

_format_version: "3.0"

services:
  - name: user-service
    url: http://user-service:8000
    plugins:
      - name: rate-limiting
        config:
          minute: 100
          policy: local
      - name: jwt
        config:
          claims_to_verify:
            - exp
      - name: correlation-id
        config:
          header_name: X-Request-ID
          generator: uuid

  - name: product-service
    url: http://product-service:8001
    plugins:
      - name: rate-limiting
        config:
          minute: 200
          policy: local

routes:
  - name: user-service-route
    service: user-service
    paths:
      - /api/v1/users
    strip_path: true
    methods:
      - GET
      - POST

  - name: product-service-route
    service: product-service
    paths:
      - /api/v1/products
    strip_path: true

consumers:
  - username: mobile-app
    plugins:
      - name: rate-limiting
        config:
          minute: 1000
          policy: local

  - username: web-app
    plugins:
      - name: rate-limiting
        config:
          minute: 500
          policy: local

Envoy Proxy

Envoy is a high-performance proxy originally built at Lyft, now a CNCF project.

Envoy Configuration

# envoy.yaml - Basic configuration

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 8080
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/api/users"
                          route:
                            cluster: user_service
                            prefix_rewrite: "/users"
                        - match:
                            prefix: "/api/products"
                          route:
                            cluster: product_service
                            prefix_rewrite: "/products"
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
    - name: user_service
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: user_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: user-service
                      port_value: 8000

    - name: product_service
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: product_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: product-service
                      port_value: 8001

Envoy Advanced Features

# envoy-advanced.yaml - Advanced configuration

static_resources:
  listeners:
    - name: https_listener
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 8443
      listener_filters:
        - name: envoy.filters.listener.tls_inspector
      filter_chains:
        - filter_chain_match:
            server_names:
              - api.example.com
          tls_context:
            common_tls_context:
              tls_certificates:
                - certificate_chain:
                    filename: /certs/server.crt
                  private_key:
                    filename: /certs/server.key
          filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: api_https
                route_config:
                  name: api_route
                  virtual_hosts:
                    - name: api
                      domains:
                        - "api.example.com"
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            cluster: backend_service
                http_filters:
                  - name: envoy.filters.http.rate_limit
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.rate_limit.v3.RateLimit
                      domain: api_ratelimit
                      stage: 0
                      failure_mode_deny: true
                      rate_limit_service:
                        grpc_service:
                          envoy_grpc:
                            cluster_name: rate_limit_service
                  - name: envoy.filters.http.router

  clusters:
    - name: backend_service
      type: EDS
      eds_cluster_config:
        service_name: backend_service
      circuit_breakers:
        thresholds:
          - max_connections: 100
            max_pending_requests: 100
            max_requests: 1000
      health_checks:
        - timeout: 1s
          interval: 10s
          unhealthy_threshold: 3
          healthy_threshold: 2
          http_health_check:
            path: /health
      outlier_detection:
        consecutive_5xx: 5
        interval: 30s
        base_ejection_time: 30s

    - name: rate_limit_service
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      http2_protocol_options: {}
      load_assignment:
        cluster_name: rate_limit_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: rate-limiter
                      port_value: 8081

Envoy Rate Limiting

# rate-limit-config.yaml

domain: api_ratelimit
descriptors:
  - key: generic_key
    value: per_ip
    rate_limit:
      unit: minute
      requests_per_unit: 60

  - key: generic_key
    value: authenticated
    rate_limit:
      unit: minute
      requests_per_unit: 1000

  - key: header_match
    value: X-API-Key
    rate_limit:
      unit: second
      requests_per_unit: 100

Authentication and Authorization

OAuth 2.0 Integration

# Kong OAuth 2.0 Plugin Configuration

oauth2_config = {
    "name": "oauth2",
    "config": {
        "scopes": ["read", "write", "admin"],
        "mandatory_scope": True,
        "token_expiration": 3600,
        "refresh_token_expiration": 86400,
        "enable_authorization_code": True,
        "enable_client_credentials": True,
        "enable_password_grant": True,
        "enable_implicit_grant": False,
        "auth_header_name": "Authorization",
        "auth_value_prefix": "Bearer"
    }
}

# Create OAuth application
oauth_application = {
    "name": "Mobile App",
    "client_id": "mobile-app-client",
    "client_secret": "secure-secret-key",
    "redirect_uris": ["https://mobile-app.com/callback"],
    "grant_types": ["authorization_code", "refresh_token"],
    "scope": "read write"
}

JWT Validation

# JWT Validation in Kong
jwt_validation_config = {
    "name": "jwt",
    "config": {
        "claims_to_verify": ["exp", "iat", "nbf"],
        "maximum_expiration": 3600,
        "run_on_preflight": True,
        "uri_param_names": ["jwt"],
        "header_names": ["Authorization"],
        "cookie_names": ["jwt_token"],
        "issuer": "https://auth.example.com",
        "audiences": ["api-gateway"]
    }
}

API Key Authentication

# API Key authentication
api_key_config = {
    "name": "key-auth",
    "config": {
        "key_names": ["X-API-Key", "Authorization"],
        "key_in_header": True,
        "key_in_query": True,
        "key_in_body": False,
        "hide_credentials": False
    }
}

# Create consumer with API key
consumer_with_key = {
    "username": "api-consumer",
    "plugins": [
        {
            "name": "key-auth",
            "config": {
                "key": "my-secret-api-key-12345"
            }
        }
    ]
}

Rate Limiting Strategies

Implementation Patterns

class RateLimitingStrategies:
    @staticmethod
    def token_bucket():
        return {
            "name": "Token Bucket",
            "description": "Tokens added at fixed rate, each request consumes token",
            "pros": [
                "Smooth rate limiting",
                "Allows bursting",
                "Simple to implement"
            ],
            "algorithm": """
                bucket = { tokens: max_tokens, last_refill: now }
                
                def allow_request():
                    now = current_time()
                    elapsed = now - bucket.last_refill
                    bucket.tokens = min(max_tokens, bucket.tokens + elapsed * refill_rate)
                    
                    if bucket.tokens >= 1:
                        bucket.tokens -= 1
                        return True
                    return False
            """
        }
    
    @staticmethod
    def sliding_window():
        return {
            "name": "Sliding Window",
            "description": "Tracks requests in sliding time window",
            "pros": [
                "More accurate than fixed windows",
                "No boundary effects"
            ],
            "cons": [
                "More memory intensive",
                "Slightly more complex"
            ]
        }
    
    @staticmethod
    def leaky_bucket():
        return {
            "name": "Leaky Bucket",
            "description": "Requests added to bucket, processed at fixed rate",
            "pros": [
                "Smooth output rate",
                "Handles bursts well"
            ],
            "cons": [
                "No burst allowance",
                "Fixed processing rate"
            ]
        }

Distributed Rate Limiting with Redis

# Kong rate limiting with Redis
rate_limit_redis = {
    "name": "rate-limiting",
    "config": {
        "minute": 100,
        "hour": 10000,
        "policy": "redis",
        "redis_host": "redis-cluster",
        "redis_port": 6379,
        "redis_password": "",
        "redis_database": 0,
        "redis_timeout": 2000,
        "fault_tolerant": True,
        "hide_client_headers": False,
        "continue_on_error": False
    }
}

Service Mesh Integration

API Gateway + Service Mesh

# Combined architecture: API Gateway + Istio

# API Gateway handles:
# - External traffic management
# - TLS termination  
# - Authentication
# - Rate limiting at entry point

# Istio handles:
# - mTLS between services
# - Service-level traffic management
# - Distributed tracing
# - Policy enforcement

api_gateway_config = """
Static Resources:
  Listeners:
    - Port: 443
      TLS: 
        Certificate: wildcard.example.com
      Filters:
        - Rate Limiting
        - Authentication
        - Logging
        
  Routes:
    - Domain: api.example.com
      Destinations:
        - Service: user-service
          Subset: v1
        - Service: order-service
          Subset: v1
"""

istio_config = """
VirtualService:
  - Name: user-service
    Subsets:
      - Name: v1
        Labels:
          version: v1
      - Name: v2
        Labels:
          version: v2
    Traffic Policy:
      Connection Pool:
        TCP:
          MaxConnections: 100
        HTTP:
          H2UpgradePolicy: UPGRADE
          http1MaxPendingRequests: 100
          http2MaxRequests: 1000
"""

Monitoring and Observability

Metrics Collection

# Kong Prometheus Plugin
prometheus_config = {
    "name": "prometheus",
    "config": {
        "per_consumer": True,
        "access_logs": True,
        "metrics": [
            "request_count",
            "request_size",
            "response_size",
            "latency",
            "status_count",
            "unique_users"
        ]
    }
}

# Metrics to monitor
metrics_to_watch = {
    "request_rate": "Requests per second",
    "error_rate": "Percentage of 5xx responses",
    "latency_p50": "50th percentile latency",
    "latency_p99": "99th percentile latency",
    "active_connections": "Current active connections",
    "upstream_latency": "Backend service latency"
}

Distributed Tracing

# Jaeger Tracing Configuration
jaeger_config = {
    "name": "jaeger",
    "config": {
        "collector_endpoint": "http://jaeger-collector:14268/api/traces",
        "collector_auth_username": "",
        "collector_auth_password": "",
        "service_name": "api-gateway",
        "sample_rate": 10,
        "propagation": "w3c",
        "zipkin_collector_endpoint": ""
    }
}

Logging Configuration

# Kong Logging Configuration
logging_config = {
    "name": "http-log",
    "config": {
        "http_endpoint": "http://log-aggregator:8080/logs",
        "method": "POST",
        "content_type": "application/json",
        "timeout": 1000,
        "keepalive": 60000,
        "retry_count": 10,
        "queue_size": 1000
    }
}

# Log format
log_format = """
{
    "timestamp": "$timestamp_ms",
    "request_id": "$request_id",
    "remote_addr": "$remote_addr",
    "method": "$request_method",
    "path": "$request_uri",
    "status": "$status",
    "latency": "$latency_request",
    "upstream_latency": "$latency_response",
    "bytes_sent": "$bytes_sent",
    "consumer": "$consumer_username"
}
"""

Best Practices

Security

SECURITY_BEST_PRACTICES = {
    "tls_configuration": [
        "Use TLS 1.3 minimum",
        "Enable HTTP/2",
        "Configure strong cipher suites",
        "Implement certificate rotation",
        "Use mutual TLS for backend services"
    ],
    
    "authentication": [
        "Centralize authentication in gateway",
        "Use short-lived tokens",
        "Implement refresh token rotation",
        "Support multiple auth methods",
        "Validate tokens at gateway level"
    ],
    
    "input_validation": [
        "Validate all input data",
        "Sanitize user-generated content",
        "Limit request body sizes",
        "Implement schema validation",
        "Use allowlists for parameters"
    ],
    
    "rate_limiting": [
        "Rate limit by consumer, not just IP",
        "Implement tiered rate limits",
        "Use distributed rate limiting",
        "Set appropriate limits per endpoint",
        "Monitor for rate limit abuse"
    ]
}

Performance

PERFORMANCE_BEST_PRACTICES = {
    "connection_management": [
        "Enable HTTP/2 and keep-alive",
        "Configure appropriate timeouts",
        "Use connection pooling",
        "Enable request caching",
        "Compress responses"
    ],
    
    "caching": [
        "Cache at gateway level",
        "Configure appropriate TTLs",
        "Use stale-while-revalidate",
        "Cache authentication tokens",
        "Implement cache invalidation"
    ],
    
    "load_balancing": [
        "Use health checks",
        "Configure circuit breakers",
        "Implement retries with backoff",
        "Use weighted routing",
        "Monitor upstream health"
    ]
}

Traefik Configuration

Load Balancing with Traefik

Gateways distribute requests across healthy backend instances. Common algorithms include round-robin, least-connections, and IP-hash for session persistence. Health checks (active or passive) remove unhealthy targets from the pool.

# Traefik dynamic configuration with load balancing
http:
  routers:
    user-api:
      rule: "PathPrefix(`/api/users`)"
      service: user-service
      middlewares:
        - auth-jwt
        - rate-limit

  services:
    user-service:
      loadBalancer:
        servers:
          - url: "http://10.0.1.10:8080"
          - url: "http://10.0.1.11:8080"
          - url: "http://10.0.1.12:8080"
        healthCheck:
          path: "/health"
          interval: "10s"
          timeout: "3s"

Traefik Rate Limit Middleware

http:
  middlewares:
    api-rate-limit:
      rateLimit:
        average: 100
        burst: 50
        period: 1m
        sourceCriterion:
          ipStrategy:
            depth: 1

  routers:
    api:
      rule: "PathPrefix(`/api`)"
      middlewares:
        - api-rate-limit
      service: backend

Kong JWT Route Registration

# Register a service and protect it with JWT authentication
$ curl -s -X POST http://localhost:8001/services \
  --data name=user-service \
  --data url=http://user-service:8080

$ curl -s -X POST http://localhost:8001/services/user-service/routes \
  --data name=user-route \
  --data paths[]=/api/users

$ curl -s -X POST http://localhost:8001/services/user-service/plugins \
  --data name=jwt

# Create a consumer and issue a JWT credential
$ curl -s -X POST http://localhost:8001/consumers \
  --data username=alice

$ curl -s -X POST http://localhost:8001/consumers/alice/jwt \
  --data algorithm=HS256 \
  --data secret=my-secret-key

# Test the protected endpoint
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/users
# => 401

# Include a valid JWT
$ curl -s -H "Authorization: Bearer <jwt-token>" http://localhost:8000/api/users
# => 200

Kong Transformer Plugins

plugins:
  - name: request-transformer
    service: user-service
    config:
      add:
        headers:
          - "X-Gateway-Version: 1.0"
          - "X-Forwarded-Proto: https"
      rename:
        headers:
          - "Authorization: X-Upstream-Auth"
      append:
        querystring:
          - "source: gateway"

  - name: response-transformer
    service: user-service
    config:
      add:
        headers:
          - "X-Response-Time: ${latency}"
      remove:
        headers:
          - "X-Internal-Trace"
# Test header injection via curl
$ curl -s -D- http://localhost:8000/api/users/me \
  -H "Authorization: Bearer <token>" | head -n 20

Gateway Comparison

Feature Kong Traefik AWS API Gateway Envoy
Type Proxy (NGINX-based) Reverse proxy (Go) Managed (AWS) Sidecar/proxy (C++)
Deployment Standalone / DB-less Binary / K8s Ingress Fully managed Sidecar / Gateway
Routing Path, header, method, regex Path, host, header, query Path, method, stage Path, header, method, weight
Auth plugins JWT, OAuth2, OIDC, LDAP, HMAC JWT, OIDC, Basic, ForwardAuth Cognito, Lambda, IAM, JWT JWT, OAuth2, ext-authz
Rate limiting Token bucket, sliding window Token bucket Token bucket, burst Per-route, regional
Health checks Active + passive Active + passive Route53 + CloudWatch Active + passive + outlier
Performance ~5k req/s per core ~10k req/s per core Scales automatically ~15k req/s per core
License Apache 2.0 (OSS) MIT Proprietary Apache 2.0
Best for Enterprise API management Cloud-native / K8s Serverless / AWS stack High-performance mesh

Security

Request Validation Middleware

func validationMiddleware(maxBodyBytes int64) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.ContentLength > maxBodyBytes {
				http.Error(w, `{"error":"request too large"}`, http.StatusRequestEntityTooLarge)
				return
			}
			ct := r.Header.Get("Content-Type")
			if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" {
				if ct != "application/json" {
					http.Error(w, `{"error":"unsupported media type"}`, http.StatusUnsupportedMediaType)
					return
				}
			}
			next.ServeHTTP(w, r)
		})
	}
}

IP Restriction

# Kong IP restriction plugin
$ curl -s -X POST http://localhost:8001/services/admin-api/plugins \
  --data name=ip-restriction \
  --data config.allow[]="10.0.0.0/8" \
  --data config.allow[]="172.16.0.0/12"

Performance Tuning

# Kong proxy performance tuning
env:
  KONG_PROXY_LISTEN: "0.0.0.0:8000"
  KONG_UPSTREAM_KEEPALIVE_POOL_SIZE: "256"
  KONG_UPSTREAM_KEEPALIVE_MAX_REQUESTS: "1000"
  KONG_UPSTREAM_KEEPALIVE_IDLE_TIMEOUT: "60"
  KONG_NGINX_PROXY_CONNECT_TIMEOUT: "5s"
  KONG_NGINX_PROXY_READ_TIMEOUT: "30s"
  KONG_NGINX_PROXY_SEND_TIMEOUT: "30s"

Deployment Patterns

Per-Team Gateway

Each team deploys their own gateway instance for their microservices. Teams own their routing and auth. This scales well but duplicates infrastructure.

Shared Gateway (Centralized)

A single gateway instance routes to all backend services across the organization. The operations team owns the gateway. This centralizes control but creates a single point of failure and a deployment bottleneck.

Sidecar Gateway (Service Mesh)

Each service instance runs a gateway sidecar (Envoy) that handles inter-service communication. An external gateway (also Envoy) handles ingress. This is the Istio/Linkerd pattern — full control with fine-grained per-service policies.

Kong Ingress Controller on Kubernetes

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway
  annotations:
    kubernetes.io/ingress.class: kong
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /api/users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 8080
      - path: /api/orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 8080

Additional Kong Features

Circuit Breaker

# Kong circuit breaker
curl -X POST http://kong:8001/routes/payment-api/plugins \
  -d "name=circuit-breaker" \
  -d "config.basetimeout=60" \
  -d "config.limit=10" \
  -d "config.keepalive=60"

Envoy Local Rate Limiting

# Envoy rate limit
- name: envoy.filters.http.local_ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    stat_prefix: http_local_rate_limiter
    token_bucket:
      max_tokens: 10000
      tokens_per_period: 10000
      period: 1s
    filter_enabled:
      runtime_key: local_rate_limit_enabled
      default_value:
        numerator: 100
        denominator: HUNDRED

Defense in Depth

layers:
  - API Gateway: Rate limiting, auth
  - Service: Input validation
  - Database: Row-level security

Response Caching

# Kong response caching
curl -X POST http://kong:8001/routes/payment-api/plugins \
  -d "name=response-cache" \
  -d "config.cache_response_codes=[200]" \
  -d "config.request_cache_control_header=true" \
  -d "config.ttl=60"

Upstream Health Checks

# Kong upstream health checks
curl -X POST http://kong:8001/upstreams/payment-service/health \
  -d "healthchecks={\"active\":{\"http_path\":\"/health\",\"timeout\":1,\"healthy\":2}}"

Canary Deployments

# Traffic splitting
- name: traffic-split
  config:
    targets:
      - weight: 90
        target: payment-service-v1
      - weight: 10
        target: payment-service-v2

Request Validation

# Kong request validation
curl -X POST http://kong:8001/services/payment-service/plugins \
  -d "name=request-validator" \
  -d "config.body_schema={\"type\":\"object\",\"properties\":{\"amount\":{\"type\":\"number\"},\"currency\":{\"type\":\"string\"}}}"

GraphQL Support

# Kong GraphQL protection
curl -X POST http://kong:8001/routes/graphql-api/plugins \
  -d "name=graphql-rate-limiting" \
  -d "config-max-cost=1000"

Resources

Conclusion

API gateways are essential components in modern microservices architectures. Whether you choose Kong for its extensive plugin ecosystem or Envoy for its high-performance proxy capabilities, understanding API gateway patterns and best practices is crucial for building scalable, secure, and observable systems.

This guide covered API gateway architecture, Kong and Envoy configuration, authentication and authorization, rate limiting strategies, service mesh integration, and operational best practices. With this knowledge, you can make informed decisions about API gateway implementation in your organization.

Comments

👍 Was this article helpful?