Introduction
API gateways are the single entry point for microservices. They handle cross-cutting concerns like routing, authentication, and rate limiting. This guide covers API gateway patterns and implementation.
What Is an API Gateway
Purpose
- Single entry point
- Cross-cutting concerns
- Protocol translation
- Client simplification
vs Backend-for-Frontend
| API Gateway | BFF |
|---|---|
| Single API for all clients | Separate API per client type |
| Shared logic | Client-specific logic |
Core Functions
Routing
routes:
- path: /api/users
service: user-service
port: 3001
- path: /api/orders
service: order-service
port: 3002
- path: /api/products
service: product-service
port: 3003
Authentication
// JWT validation middleware
app.use('/api', async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ error: 'Invalid token' });
}
});
Rate Limiting
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP
message: { error: 'Too many requests' }
});
app.use('/api', limiter);
Gateway Solutions
Open Source
- Kong: Plugin ecosystem
- Traefik: Kubernetes-native
- NGINX: Web server + gateway
- Envoy: Service proxy
Cloud
- AWS API Gateway
- Azure API Management
- Google Cloud Endpoints
Architecture
Basic Setup
Client โ API Gateway โ Services
โ
Cache
โ
Database
With Service Mesh
Client โ API Gateway โ Sidecar Proxy โ Service
โ
Sidecar Proxy โ Service
Implementation
Kong Example
# docker-compose.yml
services:
kong:
image: kong:latest
environment:
DATABASE: postgres
POSTGRES_HOST: db
KONG_DECLARATIVE_CONFIG: /usr/local/kong/kong.yml
ports:
- "8000:8000"
- "8443:8443"
# kong.yml
services:
- name: user-service
url: http://user-service:3001
routes:
- name: user-route
paths: ["/users"]
plugins:
- name: jwt
- name: rate-limiting
config:
minute: 100
Express Gateway
// gateway/index.js
const express = require('express');
const app = express();
app.use(express.json());
// Routes
app.use('/users', require('./routes/users'));
app.use('/orders', require('./routes/orders'));
app.listen(8000, () => {
console.log('Gateway running on port 8000');
});
Advanced Patterns
Circuit Breaker
const circuitBreaker = require('opossum');
const options = {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
};
const breaker = circuitBreaker(userServiceCall, options);
breaker.fallback(() => {
return { error: 'Service temporarily unavailable' };
});
app.get('/api/users', async (req, res) => {
const users = await breaker.fire();
res.json(users);
});
Caching
const cache = require('memory-cache');
app.get('/api/products', async (req, res) => {
const cacheKey = 'products';
let products = cache.get(cacheKey);
if (!products) {
products = await productService.getAll();
cache.put(cacheKey, products, 60000); // 1 minute
}
res.json(products);
});
Request Transformation
// Request transformation
app.use('/api/external', (req, res, next) => {
// Transform external API format to internal
req.body.internalFormat = {
userId: req.body.user_id,
orderTotal: parseFloat(req.body.total),
timestamp: new Date(req.body.created_at)
};
next();
});
Response Aggregation
app.get('/api/dashboard', async (req, res) => {
const [users, orders, products] = await Promise.all([
userService.getCount(),
orderService.getRecent(),
productService.getFeatured()
]);
res.json({
users: users.count,
orders: orders,
products: products
});
});
Security
Authentication Types
- API Keys: Simple, per-client
- JWT: Stateless, scalable
- OAuth 2.0: Delegated, complex
- Mutual TLS: High security
Protection
- DDoS protection
- SQL injection prevention
- Request validation
- Response validation
Monitoring
Metrics
- Request rate
- Error rate
- Latency
- Status codes
Tools
- Prometheus: Metrics
- Grafana: Visualization
- Jaeger: Tracing
Conclusion
API gateways centralize cross-cutting concerns. Choose based on needs: Kong for plugins, Traefik for Kubernetes, cloud for managed. Start simple, add complexity as needed.
Comments