What is KrakenD?
KrakenD is a high-performance, stateless API Gateway written in Go that sits between your backend microservices and client applications. Unlike traditional gateways that rely on configuration databases and persistent storage, KrakenD operates entirely from a single declarative configuration file. It aggregates, transforms, and orchestrates multiple backend responses into unified, optimized client-facing endpoints while handling cross-cutting concerns like authentication, rate limiting, and caching with minimal latency.
At its core, KrakenD functions as a backend-for-frontend (BFF) layer, allowing you to compose multiple microservice calls into a single request, reducing network round trips and offloading orchestration logic from client applications. It supports REST, GraphQL, gRPC, and even static content serving through a unified configuration model.
Key Architectural Concepts
- Stateless design – No database dependency; the entire configuration lives in a JSON file, making horizontal scaling trivial
- Declarative configuration – All routing, aggregation, and middleware behavior is defined in one or more configuration files
- Request aggregation and merging – Combine multiple backend responses into a single JSON response using templates or composition strategies
- Pipeline-based middleware – Request/response processing flows through an ordered chain of handlers (rate limiting, JWT validation, circuit breaker, etc.)
- Partial failures and graceful degradation – If one backend fails, KrakenD can still return partial data to the client with appropriate error signaling
Why KrakenD Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →In modern distributed architectures, clients often need data from multiple services. Without a gateway, each client must make separate network calls, handle authentication individually, and implement retry logic — resulting in bloated client code and poor performance on mobile networks. KrakenD solves this by:
- Reducing chattiness – A single client request fans out to multiple backends and returns a coalesced response
- Offloading cross-cutting concerns – Authentication, authorization, rate limiting, and logging are handled at the gateway level, keeping services focused on business logic
- Protocol translation – Expose a REST API while internally communicating via gRPC or consuming GraphQL backends
- Protecting fragile backends – Circuit breakers, timeouts, and concurrency limits prevent cascading failures from overwhelming downstream services
- Simplifying client evolution – Mobile, web, and third-party clients can consume tailored endpoints without modifying backend services
Installation and First Run
KrakenD ships as a single binary. The quickest way to get started is using Docker, but you can also install it directly on Linux, macOS, or Windows.
Option 1: Docker
# Pull the official image
docker pull devopsfaith/krakend:latest
# Run with a basic configuration
docker run -d --name krakend -p 8080:8080 \
-v $(pwd)/krakend.json:/etc/krakend/krakend.json \
devopsfaith/krakend:latest
Option 2: Direct Binary Download
# On Linux (amd64)
curl -L https://github.com/krakend/krakend-ce/releases/download/v2.6.0/krakend_2.6.0_linux_amd64.tar.gz \
| tar xz
sudo mv krakend /usr/local/bin/
# Verify installation
krakend version
Option 3: Package Manager (APT)
# Add the KrakenD repository
wget -qO - https://repo.krakend.io/krakend-ce/krakend-ce-pubkey.gpg | sudo apt-key add -
echo "deb https://repo.krakend.io/krakend-ce/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/krakend.list
sudo apt update && sudo apt install krakend
Core Configuration Structure
Every KrakenD instance is driven by a JSON configuration file (typically krakend.json). The structure defines endpoints, their backends, and the middleware chain applied to each. Here is the anatomy of the configuration:
{
"version": 3,
"name": "My API Gateway",
"port": 8080,
"timeout": "3000ms",
"cache_ttl": "3600s",
"output_encoding": "json",
"endpoints": [],
"extra_config": {}
}
The version field indicates the configuration schema version (3 is current for KrakenD CE 2.x). timeout sets a global default for backend calls, output_encoding controls response format negotiation, and endpoints is where you define your API surface.
Defining Your First Endpoint
Let's create a simple proxy endpoint that forwards requests to a backend service without aggregation — a classic API Gateway pattern.
{
"version": 3,
"name": "Simple Gateway",
"port": 8080,
"timeout": "3000ms",
"endpoints": [
{
"endpoint": "/api/users/{id}",
"method": "GET",
"output_encoding": "json",
"backend": [
{
"url_pattern": "/v1/users/{id}",
"encoding": "json",
"host": ["http://user-service:9001"],
"method": "GET",
"extra_config": {}
}
]
}
]
}
In this example, a client request to /api/users/42 is proxied to http://user-service:9001/v1/users/42. The {id} placeholder is automatically extracted from the incoming request path and forwarded to the backend. The host array supports multiple backends for load balancing.
Running the Configuration
# Check configuration syntax
krakend check -c krakend.json
# Start the gateway
krakend run -c krakend.json
# In production, use the check command with your CI/CD pipeline
krakend check --config krakend.json --debug
Aggregation: Merging Multiple Backends
KrakenD's most powerful feature is response aggregation — combining data from multiple backend services into a single JSON response. This eliminates the need for client-side orchestration.
Non-merge Aggregation (Sequential Calls)
When you list multiple backends under one endpoint, KrakenD fires them concurrently. By default, it returns a JSON object with keys matching each backend's response. You can control grouping, filtering, and renaming.
{
"endpoint": "/api/user-profile/{userId}",
"method": "GET",
"output_encoding": "json",
"backend": [
{
"url_pattern": "/users/{userId}",
"host": ["http://user-service:9001"],
"encoding": "json",
"group": "user"
},
{
"url_pattern": "/orders?user_id={userId}",
"host": ["http://order-service:9002"],
"encoding": "json",
"group": "orders"
}
]
}
The client receives a combined response:
{
"user": {
"id": 42,
"name": "Alice",
"email": "alice@example.com"
},
"orders": [
{ "id": 101, "total": 29.99 },
{ "id": 102, "total": 54.50 }
]
}
Response Manipulation with Lua or CEL
For complex transformations, KrakenD supports inline Lua scripting and Google Common Expression Language (CEL) to reshape aggregated data. Here's an example using Lua to flatten the response structure:
{
"endpoint": "/api/user-profile/{userId}",
"method": "GET",
"output_encoding": "json",
"backend": [
{
"url_pattern": "/users/{userId}",
"host": ["http://user-service:9001"],
"encoding": "json"
},
{
"url_pattern": "/orders?user_id={userId}",
"host": ["http://order-service:9002"],
"encoding": "json"
}
],
"extra_config": {
"modifier/lua-backend": {
"sources": ["user", "orders"],
"pre": "local cjson = require('cjson');",
"post": "local merged = {}; merged.user_name = user.name; merged.order_count = #orders; return cjson.encode(merged);"
}
}
}
The modifier/lua-backend middleware executes the Lua script after all backends respond. The pre block loads dependencies, and post performs the transformation. The client now receives:
{
"user_name": "Alice",
"order_count": 2
}
Authentication and Authorization
KrakenD supports multiple authentication mechanisms that validate credentials at the gateway before requests reach your backend services.
JWT Validation
Enable JWT validation using the auth/validator middleware. KrakenD verifies tokens against signing keys, checks claims, and can pass validated claims to backends via headers or query parameters.
{
"version": 3,
"name": "Secure Gateway",
"port": 8080,
"endpoints": [
{
"endpoint": "/api/secure/**",
"method": "GET",
"backend": [
{
"url_pattern": "/secure-data",
"host": ["http://backend:9001"]
}
],
"extra_config": {
"auth/validator": {
"alg": "RS256",
"jwk_url": "https://auth.example.com/.well-known/jwks.json",
"cache": true,
"cache_duration": 3600,
"roles": ["admin", "user"],
"operation_debug": false
}
}
}
]
}
The /** wildcard matches any path under /api/secure/. The JWK URL is cached to avoid repeated fetches. The roles field validates the roles claim in the JWT payload.
Propagating JWT Claims to Backends
Often you need to pass the authenticated user's identity to downstream services. Use the auth/creds directive to inject claims into headers:
{
"endpoint": "/api/secure/**",
"extra_config": {
"auth/validator": {
"alg": "RS256",
"jwk_url": "https://auth.example.com/.well-known/jwks.json"
},
"modifier/request-headers": {
"headers": [
{
"source": "X-User-Id",
"target": "X-Authenticated-User",
"strategy": "claim"
}
]
}
}
}
This extracts the X-User-Id claim from the validated token and forwards it as the X-Authenticated-User header to all backends for that endpoint.
API Key Authentication
For machine-to-machine communication, KrakenD supports API key validation against a static list or an external validator service:
{
"extra_config": {
"auth/api-key": {
"strategy": "header",
"key": "X-API-Key",
"keys": [
{
"key": "secret-key-12345",
"roles": ["service-account"]
}
]
}
}
}
Rate Limiting and Traffic Control
KrakenD offers token-bucket-based rate limiting that works across endpoints and clients. It's entirely in-memory and stateless by default, but can be backed by Redis for clustered deployments.
Endpoint-Level Rate Limiting
{
"endpoint": "/api/limited",
"extra_config": {
"qos/ratelimit": {
"strategy": "ip",
"max_tokens": 100,
"interval": "1m",
"capacity": 100,
"client_max_tokens": 5,
"client_capacity": 5
}
}
}
This configuration limits the endpoint to 100 total requests per minute across all clients, with each IP address capped at 5 requests per minute. The token bucket refills gradually; capacity defines the burst allowance.
Cluster-Wide Rate Limiting with Redis
{
"extra_config": {
"qos/ratelimit": {
"strategy": "ip",
"max_tokens": 1000,
"interval": "1m",
"capacity": 1000,
"client_max_tokens": 10,
"client_capacity": 10,
"backend": "redis",
"host": "redis-cluster:6379",
"database": 0,
"key_prefix": "krakend_ratelimit_"
}
}
}
With the Redis backend, all KrakenD instances in a cluster share the same token counter, ensuring accurate global rate limiting.
Circuit Breaker and Resilience
Protect your backends from cascading failures with the circuit breaker middleware. When a backend exceeds the failure threshold, the circuit opens and KrakenD immediately returns an error without forwarding the request, giving the backend time to recover.
{
"backend": [
{
"url_pattern": "/fragile-endpoint",
"host": ["http://fragile-service:9001"],
"extra_config": {
"qos/circuit-breaker": {
"interval": "60s",
"timeout": "30s",
"max_errors": 5,
"log_status": true,
"half_open_max_errors": 2,
"open_until": "30s"
}
}
}
]
}
Parameters explained:
interval– Window size for error counting (e.g., 60 seconds)timeout– Maximum duration for backend callsmax_errors– Consecutive failures before opening the circuithalf_open_max_errors– Allowed test requests during half-open recovery stateopen_until– How long the circuit stays fully open before attempting half-open
Caching Strategies
KrakenD includes a transparent HTTP cache that stores backend responses in-memory (or via Redis) and serves subsequent identical requests without hitting your services.
Global Cache Configuration
{
"version": 3,
"cache_ttl": "3600s",
"cache": {
"enabled": true,
"size": 1000,
"ttl": "3600s"
}
}
Per-Endpoint Cache Override
{
"endpoint": "/api/slow-changing-data",
"extra_config": {
"qos/cache": {
"enabled": true,
"ttl": "1800s",
"size": 500,
"cache_key": ["header:X-User-Region", "querystring:version"]
}
}
}
The cache_key array defines which request attributes form the cache key. In this example, different user regions and API versions get separate cache entries, preventing stale data from being served to the wrong audience.
Working with gRPC Backends
KrakenD can translate RESTful HTTP requests into gRPC calls, allowing you to expose gRPC microservices to web and mobile clients that don't speak gRPC natively.
{
"endpoint": "/api/users/{id}",
"method": "GET",
"backend": [
{
"url_pattern": "/users.v1.UserService/GetUser",
"encoding": "proto",
"host": ["grpc://user-grpc-service:50051"],
"method": "POST",
"extra_config": {
"backend/grpc": {
"authority": "user-grpc-service:50051",
"headers_to_pass": ["x-request-id"]
}
}
}
]
}
The url_pattern uses the gRPC service path notation. The encoding is set to "proto" and the host prefix uses grpc:// instead of http://. KrakenD automatically marshals the incoming JSON query parameters or path variables into the protobuf request.
Mapping Request Body to Protobuf Fields
For POST requests with JSON bodies, you need to define the mapping between JSON fields and protobuf message fields:
{
"endpoint": "/api/users",
"method": "POST",
"backend": [
{
"url_pattern": "/users.v1.UserService/CreateUser",
"encoding": "proto",
"host": ["grpc://user-grpc-service:50051"],
"extra_config": {
"backend/grpc": {
"authority": "user-grpc-service:50051",
"mapping": {
"name": "user_name",
"email_address": "email"
}
}
}
}
]
}
Here, the JSON field "name" maps to the protobuf field "user_name", and "email_address" maps to "email".
Monitoring and Observability
KrakenD exposes metrics and structured logging that integrate with modern observability stacks.
Prometheus Metrics
Enable the Prometheus exporter to scrape gateway performance data:
{
"version": 3,
"extra_config": {
"telemetry/metrics": {
"enabled": true,
"listen_address": "0.0.0.0:9090",
"endpoint": "/metrics"
}
}
}
This exposes standard HTTP metrics (request count, duration, in-flight requests) at /metrics on port 9090. Configure Prometheus to scrape this endpoint.
Structured Logging
{
"extra_config": {
"telemetry/logging": {
"enabled": true,
"format": "json",
"level": "INFO",
"stdout": true,
"fields": {
"service": "krakend-gateway",
"environment": "production"
}
}
}
}
JSON-formatted logs include timestamps, request IDs, latencies, backend statuses, and the custom fields you define. This format is directly consumable by Elasticsearch, Loki, or Datadog.
Tracing Integration
KrakenD supports OpenTelemetry for distributed tracing:
{
"extra_config": {
"telemetry/opentelemetry": {
"enabled": true,
"exporter": "jaeger",
"endpoint": "http://jaeger-collector:14268/api/traces",
"service_name": "krakend-gateway",
"sample_rate": 0.1
}
}
}
This sends trace spans to a Jaeger collector, allowing you to visualize the entire request flow from client through gateway to backend services.
Environment Variables and Dynamic Configuration
KrakenD supports flexible configuration templating using Go templates and environment variable injection, enabling you to maintain a single configuration file across environments.
Using env Var Placeholders
{
"port": {{.Env.PORT | default 8080}},
"endpoints": [
{
"endpoint": "/api/data",
"backend": [
{
"host": ["{{.Env.BACKEND_URL | default "http://localhost:9001"}}"]
}
],
"extra_config": {
"auth/validator": {
"jwk_url": "{{.Env.JWK_URL}}"
}
}
}
]
}
Run the gateway with environment variables:
PORT=9090 BACKEND_URL=http://prod-backend:9001 JWK_URL=https://auth.example.com/jwks.json \
krakend run -c krakend.json
Conditional Blocks with Go Templates
You can use full Go template syntax for advanced conditional logic:
{{ if .Env.ENABLE_CACHE }}
"cache_ttl": "3600s",
"cache": {
"enabled": true
},
{{ end }}
KrakenD processes these templates at startup, making environment-specific configuration straightforward without maintaining multiple files.
Best Practices
1. Keep Configurations Declarative and Versioned
Store your krakend.json in version control alongside your service code. Use the krakend check command in CI pipelines to validate configuration before deployment. Treat configuration changes with the same rigor as code changes — review, test, and roll back if needed.
2. Design Endpoints for Client Needs
Don't expose every backend service verbatim through the gateway. Instead, design endpoints that match specific client use cases (mobile vs. web vs. third-party). Aggregation should reduce the number of client requests, not simply mirror backend APIs. A mobile client might need a condensed /api/dashboard-summary endpoint that aggregates 4 backends, while a web admin panel uses separate detailed endpoints.
3. Set Appropriate Timeouts at Every Level
Configure timeouts at the global level, the endpoint level, and individual backend level. A sensible pattern: global timeout of 2 seconds, endpoint timeout of 1.5 seconds for aggregations, and backend timeouts of 800ms each. This ensures slow backends don't hold up the entire response and the gateway can return partial results gracefully.
{
"timeout": "2000ms",
"endpoints": [
{
"endpoint": "/api/aggregated",
"timeout": "1500ms",
"backend": [
{
"url_pattern": "/fast-data",
"timeout": "800ms"
}
]
}
]
}
4. Implement Graceful Degradation
Configure the qos/ignore-failures flag on non-critical backends so that a single backend failure doesn't break the entire endpoint. Combine this with default values or empty arrays in your response templates.
{
"backend": [
{
"url_pattern": "/critical-user-data",
"host": ["http://user-service:9001"]
},
{
"url_pattern": "/recommendations?user_id={userId}",
"host": ["http://recommendation-service:9002"],
"extra_config": {
"qos/ignore-failures": true
}
}
]
}
5. Use Output Encoding Wisely
KrakenD supports multiple output encodings per endpoint. Configure "output_encoding": "json" for standard REST APIs, but consider "output_encoding": "negotiate" to let clients choose between JSON, XML, or other formats via Accept headers. For high-throughput internal services, consider "encoding": "no-op" for pass-through scenarios where transformation isn't needed.
6. Secure the Gateway Itself
Never expose the KrakenD management endpoints (/__stats, /__debug) to the public internet. Use network policies or reverse proxy rules to restrict access. Enable TLS termination at the gateway level or use a load balancer for SSL offloading. Always run krakend check before deploying — it catches misconfigurations that could expose vulnerabilities.
7. Monitor and Alert on Gateway Metrics
Treat the gateway as critical infrastructure. Set up alerts on high error rates, circuit breaker trips, and abnormal latency spikes. The Prometheus metrics endpoint provides detailed per-endpoint and per-backend data. A sudden increase in circuit breaker opens indicates backend trouble; a spike in gateway 5xx errors might indicate configuration issues.
8. Leverage the Community Plugins Ecosystem
KrakenD's Enterprise Edition offers additional plugins, but the Community Edition already supports a rich set of middleware. Explore the official plugin repository for rate limiting variants, advanced auth methods, and custom modifiers. When standard middleware doesn't fit, write a custom plugin in Go using the plugin SDK — it's compiled as a shared library and loaded dynamically.
Conclusion
KrakenD represents a modern approach to API gateway architecture — stateless, high-performance, and driven entirely by declarative configuration. Its ability to aggregate multiple backends into cohesive client endpoints, combined with robust middleware for authentication, rate limiting, circuit breaking, and caching, makes it an excellent choice for microservice deployments where reducing client complexity and improving resilience are priorities. By following the configuration patterns and best practices outlined in this guide, you can deploy a production-ready gateway that protects your backend services, simplifies client development, and provides comprehensive observability into your API traffic. Start with a simple proxy configuration, gradually introduce aggregation where it benefits your clients, and always validate your configuration with krakend check before deploying to production.