A complete API gateway configuration with versioned APIs, authentication, rate limiting, and proper error handling. This example shows how to build a production-ready API gateway.
Use Case
- Route multiple API versions to different backends
- Authenticate requests with JWT or API keys
- Apply rate limiting per client
- Return JSON error responses
- Add security headers
Architecture
┌─────────────────┐
│ Sentinel │
│ API Gateway │
└────────┬────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ API v2 │ │ API v1 │ │ Auth │
│ :3000 │ │ :3001 │ │ :3002 │
└─────────┘ └─────────┘ └─────────┘
Configuration
Create sentinel.kdl:
// API Gateway Configuration
// Production-ready API management
server {
worker-threads 0
graceful-shutdown-timeout-secs 30
}
listeners {
listener "https" {
address "0.0.0.0:8443"
protocol "https"
tls {
cert-file "/etc/sentinel/certs/api.crt"
key-file "/etc/sentinel/certs/api.key"
}
}
// HTTP redirect to HTTPS
listener "http" {
address "0.0.0.0:8080"
protocol "http"
redirect-https true
}
}
routes {
// Health check - no auth required
route "health" {
priority 1000
matches {
path "/health"
}
service-type "builtin"
builtin-handler "health"
}
// API v2 - current version
route "api-v2" {
priority 200
matches {
path-prefix "/api/v2/"
method "GET" "POST" "PUT" "DELETE" "PATCH"
}
upstream "api-v2"
agents ["auth" "ratelimit"]
service-type "api"
retry-policy {
max-attempts 3
retryable-status-codes 502 503 504
}
policies {
timeout-secs 30
max-body-size "10MB"
request-headers {
set {
"X-Api-Version" "2"
}
}
response-headers {
set {
"X-Content-Type-Options" "nosniff"
"X-Frame-Options" "DENY"
"X-XSS-Protection" "1; mode=block"
}
remove "Server" "X-Powered-By"
}
}
error-pages {
default-format "json"
}
}
// API v1 - legacy, deprecated
route "api-v1" {
priority 100
matches {
path-prefix "/api/v1/"
}
upstream "api-v1"
agents ["auth"]
service-type "api"
policies {
timeout-secs 60
response-headers {
set {
"X-Deprecation-Warning" "API v1 is deprecated. Migrate to /api/v2/"
"Sunset" "2025-12-31"
}
}
}
error-pages {
default-format "json"
}
}
// OpenAPI documentation - public
route "docs" {
priority 50
matches {
path-prefix "/docs/"
}
service-type "static"
static-files {
root "/var/www/api-docs"
index "index.html"
}
}
}
upstreams {
upstream "api-v2" {
targets {
target { address "127.0.0.1:3000" weight 100 }
target { address "127.0.0.1:3001" weight 100 }
}
load-balancing "round-robin"
health-check {
type "http" {
path "/health"
expected-status 200
}
interval-secs 5
unhealthy-threshold 3
}
}
upstream "api-v1" {
targets {
target { address "127.0.0.1:3010" }
}
health-check {
type "http" {
path "/health"
}
interval-secs 10
}
}
}
agents {
agent "auth" {
transport "unix_socket" {
path "/var/run/sentinel/auth.sock"
}
events ["request_headers"]
timeout-ms 100
failure-mode "closed"
}
agent "ratelimit" {
transport "unix_socket" {
path "/var/run/sentinel/ratelimit.sock"
}
events ["request_headers"]
timeout-ms 50
failure-mode "open"
}
}
observability {
metrics {
enabled true
address "0.0.0.0:9090"
}
logging {
level "info"
format "json"
}
tracing {
enabled true
service-name "api-gateway"
endpoint "http://localhost:4317"
}
}
Setup
1. Install Agents
2. Start Agents
# Auth agent with JWT validation
&
# Rate limit agent
&
3. Start Backend Services
# Start API v2 instances
&
&
# Start API v1 instance
&
4. Run Sentinel
Testing
Health Check
API v2 with Authentication
# Get a token (from your auth service)
TOKEN="eyJhbGciOiJIUzI1NiIs..."
# Make authenticated request
Rate Limiting
# Send 150 requests rapidly
for; do
done | |
Expected output shows 429 responses after limit exceeded.
API v1 Deprecation Headers
Response includes:
X-Deprecation-Warning: API v1 is deprecated. Migrate to /api/v2/
Sunset: 2025-12-31
Customizations
API Key Authentication
# Run auth agent with API keys
Per-Route Rate Limits
Create separate rate limit agents for different routes:
agents {
agent "ratelimit-standard" {
transport "unix_socket" {
path "/var/run/sentinel/ratelimit-standard.sock"
}
events ["request_headers"]
timeout-ms 50
}
agent "ratelimit-premium" {
transport "unix_socket" {
path "/var/run/sentinel/ratelimit-premium.sock"
}
events ["request_headers"]
timeout-ms 50
}
}
CORS Configuration
route "api-v2" {
policies {
response-headers {
set {
"Access-Control-Allow-Origin" "https://app.example.com"
"Access-Control-Allow-Methods" "GET, POST, PUT, DELETE"
"Access-Control-Allow-Headers" "Authorization, Content-Type"
"Access-Control-Max-Age" "86400"
}
}
}
}
Next Steps
- Security - Add WAF protection
- Observability - Complete monitoring setup
- Load Balancer - Advanced load balancing