API Gateways — Kong, Traefik, and AWS API Gateway Compared
Every request to your microservices needs authentication, rate limiting, logging, and routing — but implementing these in every service creates massive duplication and inconsistency. An API gateway centralizes these cross-cutting concerns into a single entry point, letting your services focus on business logic.
What Is an API Gateway?
An API gateway sits between clients and your backend services. It handles the "boring but critical" stuff so your services don't have to:
┌──────────────────────────────┐
Mobile App ──────►│ │──► User Service
Web App ─────────►│ API Gateway │──► Order Service
Third Party ─────►│ │──► Payment Service
IoT Device ──────►│ • Authentication │──► Inventory Service
│ • Rate Limiting │──► Notification Service
│ • Request/Response Transform │
│ • Load Balancing │
│ • Circuit Breaking │
│ • Logging & Metrics │
│ • SSL Termination │
└──────────────────────────────┘
Without a gateway, every service must implement auth, rate limiting, CORS, and logging independently. With a gateway, you configure these once.
API Gateway vs Load Balancer vs Reverse Proxy
These terms overlap but serve different primary purposes:
| Feature | Reverse Proxy | Load Balancer | API Gateway |
|---|---|---|---|
| Primary purpose | Forward requests, hide backends | Distribute traffic | Manage API lifecycle |
| SSL termination | Yes | Sometimes | Yes |
| Load balancing | Basic | Advanced (algorithms) | Yes |
| Authentication | Basic (mTLS) | No | Yes (JWT, OAuth, API keys) |
| Rate limiting | Basic | No | Yes (per user, per endpoint) |
| Request transformation | Limited | No | Yes (headers, body, path) |
| API versioning | No | No | Yes |
| Developer portal | No | No | Yes |
| Analytics | Basic access logs | Connection metrics | Full API analytics |
| Example | NGINX, HAProxy | ALB, NLB | Kong, Traefik, AWS APIGW |
In practice, modern API gateways include reverse proxy and load balancing capabilities, making the lines blurry.
Kong: The Plugin Ecosystem Powerhouse
Kong is the most feature-rich open-source API gateway, built on NGINX and OpenResty:
# kong-declarative-config.yaml
_format_version: "3.0"
services:
- name: user-service
url: http://user-service.internal:8080
routes:
- name: user-routes
paths:
- /api/v1/users
methods:
- GET
- POST
- PUT
strip_path: false
plugins:
- name: rate-limiting
config:
minute: 100
hour: 5000
policy: redis
redis_host: redis.internal
- name: jwt
config:
claims_to_verify:
- exp
- name: correlation-id
config:
header_name: X-Request-ID
generator: uuid
- name: prometheus
config:
per_consumer: true
- name: order-service
url: http://order-service.internal:8080
routes:
- name: order-routes
paths:
- /api/v1/orders
plugins:
- name: rate-limiting
config:
minute: 50
policy: redis
redis_host: redis.internal
- name: request-transformer
config:
add:
headers:
- "X-Gateway-Version:kong-3.6"
Deploy Kong on Kubernetes with the Ingress Controller:
# kong-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-routes
annotations:
konghq.com/strip-path: "false"
konghq.com/plugins: rate-limit-global,jwt-auth
spec:
ingressClassName: kong
rules:
- host: api.example.com
http:
paths:
- path: /api/v1/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
tls:
- hosts:
- api.example.com
secretName: api-tls-cert
Kong has 100+ plugins for authentication, traffic control, logging, transformations, and security.
Traefik: Auto-Discovery and Let's Encrypt
Traefik shines in dynamic environments — it automatically discovers services from Docker, Kubernetes, and Consul without configuration reloads:
# traefik-values.yaml (Helm chart)
# Traefik auto-discovers Kubernetes services via IngressRoute CRDs
# traefik-config.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-routes
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/api/v1/users`)
kind: Rule
services:
- name: user-service
port: 8080
middlewares:
- name: rate-limit
- name: auth-headers
- match: Host(`api.example.com`) && PathPrefix(`/api/v1/orders`)
kind: Rule
services:
- name: order-service
port: 8080
weight: 80
- name: order-service-canary
port: 8080
weight: 20 # 20% canary traffic
middlewares:
- name: rate-limit
- name: circuit-breaker
---
# Rate limiting middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 100
burst: 50
period: 1m
---
# Circuit breaker middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: circuit-breaker
spec:
circuitBreaker:
expression: LatencyAtQuantileMS(50.0) > 1000 || ResponseCodeRatio(500, 600, 0, 600) > 0.3
Traefik's killer feature is automatic Let's Encrypt certificate management:
# traefik static config
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /data/acme.json
httpChallenge:
entryPoint: web
No manual certificate management — Traefik handles issuance, renewal, and rotation automatically.
AWS API Gateway: Serverless Native
AWS API Gateway is fully managed — no servers to run, scales automatically, and integrates natively with Lambda, IAM, and Cognito:
# serverless.yml (Serverless Framework)
service: payment-api
provider:
name: aws
runtime: nodejs20.x
stage: ${opt:stage, 'dev'}
apiGateway:
shouldStartNameWithService: true
usagePlan:
quota:
limit: 10000
period: DAY
throttle:
burstLimit: 200
rateLimit: 100
functions:
getOrders:
handler: handlers/orders.list
events:
- http:
path: /orders
method: get
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer
createOrder:
handler: handlers/orders.create
events:
- http:
path: /orders
method: post
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer
request:
schemas:
application/json: ${file(schemas/create-order.json)}
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoAuthorizer
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
ProviderARNs:
- arn:aws:cognito-idp:us-east-1:123456789:userpool/us-east-1_ABC123
AWS API Gateway types:
- REST API: Full-featured, request/response transforms, usage plans, API keys
- HTTP API: Simpler, cheaper, faster — best for Lambda proxying
- WebSocket API: For real-time bidirectional communication
Feature Comparison
| Feature | Kong OSS | Kong Enterprise | Traefik | AWS API Gateway |
|---|---|---|---|---|
| Pricing | Free | $$$$ | Free / Enterprise | Pay per request |
| Deployment | Self-hosted | Self-hosted / SaaS | Self-hosted | Fully managed |
| K8s Ingress | Yes | Yes | Yes (native) | No (use ALB) |
| Auto-discovery | Limited | Yes | Excellent | N/A |
| Let's Encrypt | Plugin | Plugin | Built-in | ACM integrated |
| Rate Limiting | Plugin | Plugin (advanced) | Middleware | Built-in |
| Authentication | JWT, OAuth, OIDC | + LDAP, SAML | ForwardAuth | IAM, Cognito, Lambda |
| Circuit Breaking | Plugin | Plugin | Built-in | N/A |
| Developer Portal | No | Yes | No | Yes |
| gRPC Support | Yes | Yes | Yes | Yes |
| WebSocket | Yes | Yes | Yes | Yes (dedicated) |
| Observability | Prometheus plugin | Full analytics | Prometheus, Datadog | CloudWatch |
Rate Limiting Patterns
Rate limiting protects your services from abuse and ensures fair usage:
Rate Limiting Strategies:
1. Fixed Window: 100 requests per minute (resets at minute boundary)
Simple but allows bursts at window edges
2. Sliding Window: 100 requests per rolling 60 seconds
Smoother, prevents boundary bursts
3. Token Bucket: Bucket holds 100 tokens, refills at 10/second
Allows bursts up to bucket size
4. Per-User: Each authenticated user gets 1000 req/hour
Fair usage across users
5. Per-Endpoint: /search gets 50 req/min, /orders gets 200 req/min
Protect expensive endpoints
# Kong rate limiting with Redis (distributed)
plugins:
- name: rate-limiting
config:
minute: 100
hour: 5000
policy: redis
redis_host: redis.internal
redis_port: 6379
redis_timeout: 2000
fault_tolerant: true # If Redis is down, allow traffic
hide_client_headers: false # Send X-RateLimit-* headers
Circuit Breaking
When a backend service is failing, a circuit breaker prevents cascading failures by short-circuiting requests:
Circuit Breaker States:
CLOSED (normal) ──── error threshold exceeded ────► OPEN (failing)
▲ │
│ │
└── success threshold met ◄── HALF-OPEN ◄── timeout expires
(test requests)
# Traefik circuit breaker
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: payment-circuit-breaker
spec:
circuitBreaker:
expression: >-
ResponseCodeRatio(500, 600, 0, 600) > 0.30
|| LatencyAtQuantileMS(99.0) > 3000
checkPeriod: 10s
fallbackDuration: 30s
recoveryDuration: 60s
# Opens circuit if:
# - More than 30% of responses are 5xx, OR
# - p99 latency exceeds 3 seconds
# Stays open for 30s, then enters half-open for 60s
API Versioning Strategies
APIs evolve, and you need a strategy for backward compatibility:
| Strategy | Example | Pros | Cons |
|---|---|---|---|
| URL Path | /api/v1/users | Simple, explicit | URL pollution |
| Query Parameter | /api/users?version=1 | Easy to add | Easy to miss |
| Header | Accept: application/vnd.api.v1+json | Clean URLs | Less discoverable |
| Content Negotiation | Accept: application/json; version=1 | HTTP standard | Complex |
# Kong route-based API versioning
services:
- name: user-service-v1
url: http://user-service-v1.internal:8080
routes:
- paths: ["/api/v1/users"]
- name: user-service-v2
url: http://user-service-v2.internal:8080
routes:
- paths: ["/api/v2/users"]
# Header-based versioning (same path, different backends)
- name: user-service-v2-header
url: http://user-service-v2.internal:8080
routes:
- paths: ["/api/users"]
headers:
X-API-Version: ["2"]
Choosing the Right Gateway
Decision Tree:
Is your architecture serverless on AWS?
└── YES → AWS API Gateway (HTTP API for simple, REST API for complex)
└── NO ↓
Do you need auto-discovery in Kubernetes?
└── YES → Traefik (native K8s, auto-discovery, Let's Encrypt)
└── NO ↓
Do you need extensive plugin ecosystem?
└── YES → Kong (100+ plugins, declarative config)
└── NO ↓
Do you need simplicity with high performance?
└── YES → NGINX (proven, battle-tested, minimal features)
Closing Note
An API gateway is the front door to your microservices architecture. Choose based on your infrastructure (managed vs self-hosted), deployment model (Kubernetes vs serverless), and feature requirements. In the next post, we'll tackle Software Supply Chain Security — protecting your build pipeline from the SolarWinds-style attacks that have become the top concern for engineering teams.
