Skip to main content
โšก Calmops

API Gateway Patterns: Kong, AWS, Nginx 2026

Introduction

API gateways are critical infrastructure for managing, securing, and scaling APIs. They provide a single entry point for client requests, handling cross-cutting concerns like authentication, rate limiting, and request routing. However, choosing and configuring the right API gateway requires understanding different patterns and trade-offs.

This comprehensive guide covers API gateway patterns, implementations, and real-world strategies.


Core Concepts

API Gateway

Single entry point for client requests that routes to backend services.

Routing

Directing requests to appropriate backend services based on path, host, or other criteria.

Rate Limiting

Restricting number of requests per time period.

Authentication

Verifying client identity.

Authorization

Determining what authenticated clients can access.

Request/Response Transformation

Modifying requests or responses in transit.

Load Balancing

Distributing requests across multiple backend instances.

Circuit Breaking

Preventing cascading failures by stopping requests to failing services.


API Gateway Comparison

Feature Kong AWS API Gateway Nginx
Type Self-hosted/Cloud Managed Self-hosted
Pricing Free/Enterprise Pay-per-request Free
Setup Moderate Easy Complex
Scalability Excellent Unlimited Good
Plugins 100+ Limited Via modules
Rate Limiting Yes Yes Yes
Authentication Yes Yes Yes
Best For Microservices AWS-native High-performance

Kong Implementation

# Kong configuration
_format_version: "3.0"
_transform: true

services:
  - name: user-service
    url: http://user-service:8080
    routes:
      - name: user-api
        paths:
          - /api/users
        methods:
          - GET
          - POST
        strip_path: true
  
  - name: order-service
    url: http://order-service:8080
    routes:
      - name: order-api
        paths:
          - /api/orders
        methods:
          - GET
          - POST
        strip_path: true

plugins:
  - name: rate-limiting
    service: user-service
    config:
      minute: 100
      hour: 1000
  
  - name: jwt
    service: user-service
    config:
      key_claim_name: sub
      secret_is_base64: false
  
  - name: cors
    config:
      origins:
        - "*"
      methods:
        - GET
        - POST
        - PUT
        - DELETE
      headers:
        - Content-Type
        - Authorization

AWS API Gateway Implementation

import boto3

client = boto3.client('apigateway')

# Create REST API
api = client.create_rest_api(
    name='MyAPI',
    description='My API Gateway',
    endpointConfiguration={'types': ['REGIONAL']}
)

api_id = api['id']

# Get root resource
resources = client.get_resources(restApiId=api_id)
root_id = resources['items'][0]['id']

# Create /users resource
users_resource = client.create_resource(
    restApiId=api_id,
    parentId=root_id,
    pathPart='users'
)

# Create GET method
client.put_method(
    restApiId=api_id,
    resourceId=users_resource['id'],
    httpMethod='GET',
    authorizationType='AWS_IAM'
)

# Create integration
client.put_integration(
    restApiId=api_id,
    resourceId=users_resource['id'],
    httpMethod='GET',
    type='HTTP',
    integrationHttpMethod='GET',
    uri='http://user-service:8080/users'
)

# Deploy API
deployment = client.create_deployment(
    restApiId=api_id,
    stageName='prod'
)

Nginx Implementation

# nginx.conf
upstream user_service {
    server user-service:8080;
    server user-service-2:8080;
}

upstream order_service {
    server order-service:8080;
    server order-service-2:8080;
}

# Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    listen 80;
    server_name api.example.com;

    # User service routes
    location /api/users {
        limit_req zone=api_limit burst=20 nodelay;
        
        # Authentication
        auth_request /auth;
        
        proxy_pass http://user_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Order service routes
    location /api/orders {
        limit_req zone=api_limit burst=20 nodelay;
        auth_request /auth;
        
        proxy_pass http://order_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Authentication endpoint
    location = /auth {
        internal;
        proxy_pass http://auth-service:8080/verify;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }
}

API Gateway Patterns

Request Routing

# Route based on path
/api/v1/users -> user-service
/api/v1/orders -> order-service
/api/v1/products -> product-service

# Route based on host
users.api.example.com -> user-service
orders.api.example.com -> order-service

# Route based on header
X-Service: users -> user-service
X-Service: orders -> order-service

Rate Limiting

# Token bucket algorithm
class RateLimiter:
    def __init__(self, rate, capacity):
        self.rate = rate  # tokens per second
        self.capacity = capacity
        self.tokens = capacity
        self.last_update = time.time()
    
    def allow_request(self):
        now = time.time()
        elapsed = now - self.last_update
        
        # Add tokens
        self.tokens = min(
            self.capacity,
            self.tokens + elapsed * self.rate
        )
        self.last_update = now
        
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False

# Usage
limiter = RateLimiter(rate=10, capacity=100)  # 10 req/sec, burst 100

if limiter.allow_request():
    # Process request
    pass
else:
    # Return 429 Too Many Requests
    pass

Circuit Breaker

from enum import Enum
import time

class CircuitState(Enum):
    CLOSED = 1
    OPEN = 2
    HALF_OPEN = 3

class CircuitBreaker:
    def __init__(self, failure_threshold=5, timeout=60):
        self.failure_threshold = failure_threshold
        self.timeout = timeout
        self.failure_count = 0
        self.last_failure_time = None
        self.state = CircuitState.CLOSED
    
    def call(self, func, *args, **kwargs):
        if self.state == CircuitState.OPEN:
            if time.time() - self.last_failure_time > self.timeout:
                self.state = CircuitState.HALF_OPEN
            else:
                raise Exception("Circuit breaker is OPEN")
        
        try:
            result = func(*args, **kwargs)
            self.on_success()
            return result
        except Exception as e:
            self.on_failure()
            raise e
    
    def on_success(self):
        self.failure_count = 0
        self.state = CircuitState.CLOSED
    
    def on_failure(self):
        self.failure_count += 1
        self.last_failure_time = time.time()
        
        if self.failure_count >= self.failure_threshold:
            self.state = CircuitState.OPEN

Best Practices

  1. Single Entry Point: Route all traffic through gateway
  2. Authentication: Centralize authentication
  3. Rate Limiting: Protect backend services
  4. Monitoring: Track gateway metrics
  5. Caching: Cache responses when possible
  6. Circuit Breaking: Prevent cascading failures
  7. Request Transformation: Normalize requests
  8. Error Handling: Consistent error responses
  9. Versioning: Support multiple API versions
  10. Documentation: Document all routes

External Resources

Kong

AWS API Gateway

Nginx


Conclusion

API gateways are essential infrastructure for managing APIs at scale. Choose based on your requirements: Kong for flexibility, AWS API Gateway for AWS-native deployments, Nginx for high performance.

Implement proper rate limiting, authentication, and monitoring to ensure reliable API operations.

API gateways are the foundation of scalable API infrastructure.

Comments