Implementing API Gateway Pattern for Microservices
An API Gateway is a single entry point for all clients in the system. Instead of frontend or mobile applications communicating directly with dozens of microservices, they interact with one gateway that routes requests, aggregates data, applies authentication, and enforces rate limiting.
API Gateway Functions
-
Routing —
/api/orders→ Order Service,/api/users→ User Service - Authentication and Authorization — JWT/OAuth2 is verified once at the gateway
- Rate Limiting — protection against abuse
- SSL Termination — TLS terminates at the gateway, microservices communicate via HTTP internally
- Request/Response Transformation — modifying formats, adding headers
- Request Aggregation — one client request → multiple service requests
- Circuit Breaker — protection against cascading failures
- Logging and Tracing — single point for collecting access logs
Implementation Options
| Tool | Type | Features |
|---|---|---|
| Kong | Self-hosted / Cloud | Lua/Go plugins, Kubernetes Ingress |
| Traefik | Self-hosted | Auto-discovery in Docker/K8s |
| AWS API Gateway | Managed | Lambda integration, IAM |
| NGINX + Lua | Self-hosted | Maximum control |
| Envoy | Proxy | gRPC, complex scenarios |
| Express Gateway | Node.js | Simple cases |
Kong Configuration
Kong is the most popular self-hosted gateway:
# kong.yaml (declarative configuration)
_format_version: "3.0"
services:
- name: order-service
url: http://order-service:3000
routes:
- name: orders-route
paths: ["/api/orders"]
methods: ["GET", "POST", "PUT", "DELETE"]
- name: user-service
url: http://user-service:3001
routes:
- name: users-route
paths: ["/api/users"]
methods: ["GET", "PUT"]
plugins:
- name: jwt
config:
claims_to_verify: ["exp"]
- name: rate-limiting
config:
minute: 100
hour: 5000
policy: local
- name: request-transformer
config:
add:
headers: ["X-Service-Version:1.0"]
Gateway-Level Authentication
JWT is verified at the gateway, and microservices receive already-validated headers with user data:
// Custom middleware on Express Gateway
async function jwtMiddleware(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'No token' });
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
// Pass user data in headers
req.headers['X-User-Id'] = payload.sub;
req.headers['X-User-Role'] = payload.role;
req.headers['X-User-Email'] = payload.email;
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
}
Request Aggregation (BFF Pattern in Gateway)
A mobile client retrieves data from multiple services in a single request:
// Gateway aggregates data from multiple services
app.get('/api/dashboard/:userId', jwtMiddleware, async (req, res) => {
const { userId } = req.params;
const [user, orders, notifications] = await Promise.allSettled([
userService.get(`/users/${userId}`),
orderService.get(`/orders?customerId=${userId}&limit=5`),
notificationService.get(`/notifications/${userId}/unread`)
]);
res.json({
user: user.status === 'fulfilled' ? user.value.data : null,
recentOrders: orders.status === 'fulfilled' ? orders.value.data : [],
unreadCount: notifications.status === 'fulfilled'
? notifications.value.data.count : 0
});
});
Traefik Configuration in Kubernetes
# Traefik IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: api-gateway
spec:
entryPoints:
- websecure
routes:
- match: PathPrefix(`/api/orders`)
kind: Rule
services:
- name: order-service
port: 3000
middlewares:
- name: jwt-auth
- name: rate-limit
- match: PathPrefix(`/api/users`)
kind: Rule
services:
- name: user-service
port: 3001
middlewares:
- name: jwt-auth
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 100
burst: 50
period: 1m
Versioning via Gateway
// Header-based versioning
app.use((req, res, next) => {
const version = req.headers['api-version'] || 'v1';
if (version === 'v2') {
req.url = req.url.replace('/api/', '/api/v2/');
}
next();
});
Implementation Timeline
- Basic Kong or Traefik setup with routing and JWT — 3–5 days
- Rate limiting, circuit breaker, logging configuration — 2–3 days
- Aggregating gateway with custom business logic — 1–2 weeks







