Skip to main content

Overview

KrakenD’s Flexible Configuration system allows you to use templates instead of a monolithic JSON file. This enables:
  • Variables - Environment-specific settings
  • Partials - Reusable configuration snippets
  • Logic - Loops and conditionals
  • Maintainability - Organized, DRY configurations

Example Template

The playground includes krakend-flexible-config.tmpl as a demonstration.

Template File

From config/krakend/krakend-flexible-config.tmpl:
{
    "$schema": "https://www.krakend.io/schema/v3.json",
    "version": 3,
    "name": "Sample Gateway",
    "port": {{ .env.port }},
    "timeout": "30s",
    "cache_ttl": "300s",
    "extra_config": {{ include "extra_config.tmpl" }},
    "endpoints": [
      {{ template "sample_template.tmpl" . }},

      {{ range $idx, $endpoint := .loop_example.dummy }}
        {{ if $idx }},{{ end }}
        {
            "endpoint": "{{ $endpoint }}",
            "backend": [
              {
                "host": [ "http://localhost:8080" ],
                "url_pattern": "/__debug{{ $endpoint }}"
              }
            ]
        }
      {{ end }}
   ]
}

Environment Variables

From config/krakend/settings/dev/env.json:
{
	"port": 8080,
	"host_member": "http://member",
	"host_logistics": "http://logistics",
	"host_payment": "http://payment",
	"host_order": "http://order",
	"host_case": "http://case",
	"host_channel": "http://channel",
	"host_ticket": "http://ticket",
	"security": "https://keycloak/auth/realms/default/protocol/openid-connect/certs",
	"name": "DEV"
}

Compiling the Configuration

Using Make

From the Makefile:
compile-flexible-config:
	docker run \
        -v $(PWD)/config/krakend/:/etc/krakend/ \
        -e FC_ENABLE=1 \
        -e FC_SETTINGS=/etc/krakend/settings/dev \
        -e FC_PARTIALS=/etc/krakend/partials \
        -e FC_TEMPLATES=/etc/krakend/templates \
        -e FC_OUT=/etc/krakend/krakend-flexible-config.compiled.json \
        krakend \
        check -c krakend-flexible-config.tmpl

Run the Command

make compile-flexible-config
This generates krakend-flexible-config.compiled.json with all variables resolved and templates included.

Template Syntax

KrakenD uses Go template syntax.

1. Variables

Access environment variables with .env:
{
  "port": {{ .env.port }},
  "name": "{{ .env.name }}"
}
Compiled Output:
{
  "port": 8080,
  "name": "DEV"
}

2. Including Partials

Reuse configuration snippets:
{
  "extra_config": {{ include "extra_config.tmpl" }}
}
The include function inserts the content of partials/extra_config.tmpl.

3. Templates

Use named templates:
{
  "endpoints": [
    {{ template "sample_template.tmpl" . }}
  ]
}
The template function renders templates/sample_template.tmpl with the current context (.).

4. Loops

Iterate over arrays:
{{ range $idx, $endpoint := .loop_example.dummy }}
  {{ if $idx }},{{ end }}
  {
    "endpoint": "{{ $endpoint }}",
    "backend": [
      {
        "host": [ "http://localhost:8080" ],
        "url_pattern": "/__debug{{ $endpoint }}"
      }
    ]
  }
{{ end }}
If env.json contains:
{
  "loop_example": {
    "dummy": ["/foo", "/bar", "/baz"]
  }
}
Compiled Output:
{
  "endpoint": "/foo",
  "backend": [{"host": ["http://localhost:8080"], "url_pattern": "/__debug/foo"}]
},
{
  "endpoint": "/bar",
  "backend": [{"host": ["http://localhost:8080"], "url_pattern": "/__debug/bar"}]
},
{
  "endpoint": "/baz",
  "backend": [{"host": ["http://localhost:8080"], "url_pattern": "/__debug/baz"}]
}

5. Conditionals

{{ if eq .env.environment "production" }}
  "cache_ttl": "1h"
{{ else }}
  "cache_ttl": "10s"
{{ end }}

Directory Structure

Organize templates and settings:
config/krakend/
├── krakend-flexible-config.tmpl    # Main template
├── settings/
│   ├── dev/
│   │   └── env.json                # Dev environment variables
│   ├── staging/
│   │   └── env.json                # Staging variables
│   └── prod/
│       └── env.json                # Production variables
├── partials/
│   ├── extra_config.tmpl           # Reusable snippets
│   ├── security.tmpl
│   └── telemetry.tmpl
└── templates/
    ├── endpoints/
    │   ├── public.tmpl
    │   └── private.tmpl
    └── backends/
        └── api.tmpl

Environment Variables

Configure the flexible configuration system:
VariableDescriptionExample
FC_ENABLEEnable flexible configuration1
FC_SETTINGSPath to settings directory/etc/krakend/settings/dev
FC_PARTIALSPath to partials directory/etc/krakend/partials
FC_TEMPLATESPath to templates directory/etc/krakend/templates
FC_OUTOutput file for compiled config/etc/krakend/compiled.json

Use Cases

1. Environment-Specific Configuration

Template:
{
  "host": ["{{ .env.host_payment }}"],
  "extra_config": {
    "auth/validator": {
      "jwk_url": "{{ .env.security }}"
    }
  }
}
Dev Environment (settings/dev/env.json):
{
  "host_payment": "http://payment-dev:8080",
  "security": "http://keycloak-dev/certs"
}
Production Environment (settings/prod/env.json):
{
  "host_payment": "https://payment.company.com",
  "security": "https://auth.company.com/certs"
}

2. DRY Backend Configurations

Partial: partials/auth_backend.tmpl
{
  "extra_config": {
    "auth/validator": {
      "alg": "RS256",
      "audience": ["{{ .env.jwt_audience }}"],
      "jwk_url": "{{ .env.security }}"
    }
  }
}
Use in endpoints:
{
  "endpoint": "/private/user",
  "backend": [{"url_pattern": "/user"}],
  {{ include "auth_backend.tmpl" }}
},
{
  "endpoint": "/private/orders",
  "backend": [{"url_pattern": "/orders"}],
  {{ include "auth_backend.tmpl" }}
}

3. Dynamic Endpoint Generation

{{ range $service := .services }}
  {
    "endpoint": "/{{ $service.name }}",
    "backend": [
      {
        "host": ["{{ $service.host }}"],
        "url_pattern": "{{ $service.path }}"
      }
    ]
  }{{ if not (last $service) }},{{ end }}
{{ end }}
Environment:
{
  "services": [
    {"name": "users", "host": "http://user-service", "path": "/api/users"},
    {"name": "orders", "host": "http://order-service", "path": "/api/orders"},
    {"name": "products", "host": "http://product-service", "path": "/api/products"}
  ]
}

Benefits

Maintainability

Before (monolithic):
  • 5,000+ line JSON file
  • Duplicated configuration
  • Hard to find specific settings
  • Difficult to change
After (flexible):
  • Main template: 200 lines
  • Partials: 10-50 lines each
  • Organized by feature
  • Change once, apply everywhere

Environment Management

# Development
FC_SETTINGS=/etc/krakend/settings/dev krakend run -c krakend.tmpl

# Staging
FC_SETTINGS=/etc/krakend/settings/staging krakend run -c krakend.tmpl

# Production
FC_SETTINGS=/etc/krakend/settings/prod krakend run -c krakend.tmpl
Same template, different environments.

Team Collaboration

/endpoints/
  ├── auth-team/
  │   ├── login.tmpl
  │   └── register.tmpl
  ├── payment-team/
  │   ├── checkout.tmpl
  │   └── refund.tmpl
  └── user-team/
      ├── profile.tmpl
      └── settings.tmpl
Teams can work on separate template files without conflicts.

Testing

Validate template compilation:
# Check syntax
make compile-flexible-config

# Validate configuration
docker run -v $(PWD)/config/krakend:/etc/krakend krakend check -c krakend-flexible-config.compiled.json

Advanced Features

Custom Functions

KrakenD provides template functions:
// Math
{{ add 1 2 }}              // 3
{{ sub 5 2 }}              // 3
{{ mul 3 4 }}              // 12
{{ div 10 2 }}             // 5

// Strings
{{ upper "hello" }}        // "HELLO"
{{ lower "HELLO" }}        // "hello"
{{ replace "foo" "bar" "foo-baz" }}  // "bar-baz"

// Logic
{{ eq .env.environment "prod" }}    // true/false
{{ ne .env.environment "dev" }}     // true/false
{{ and true true }}                 // true
{{ or false true }}                 // true

Environment Variables from OS

Access OS environment variables:
{
  "version": "{{ env "APP_VERSION" }}",
  "build": "{{ env "BUILD_NUMBER" }}"
}

Best Practices

1. Keep Templates Simple

Good:
{
  "port": {{ .env.port }},
  {{ include "telemetry.tmpl" }}
}
Bad:
{{ range $i := until 100 }}
  {{ if and (gt $i 10) (lt $i 50) (ne $i 25) }}
    // Complex nested logic
  {{ end }}
{{ end }}

2. Use Descriptive Variable Names

Good:
{
  "host_payment_service": "http://payment",
  "jwt_issuer": "https://auth.company.com"
}
Bad:
{
  "h1": "http://payment",
  "s1": "https://auth.company.com"
}

3. Document Template Variables

Add comments to env.json:
{
  "_comment": "Port for KrakenD to listen on",
  "port": 8080,
  
  "_comment": "Backend service hosts",
  "host_payment": "http://payment",
  "host_user": "http://user"
}

4. Version Control Settings

git add config/krakend/settings/dev/env.json
git add config/krakend/settings/staging/env.json
# Production settings in secrets management

Comparison: Regular vs Flexible

AspectRegular JSONFlexible Config
FileSingle JSONMultiple templates
VariablesHard-codedEnvironment-specific
ReusabilityCopy-pastePartials/templates
EnvironmentsSeparate filesSame template, different settings
ComplexitySimple for small configsBetter for large configs
Learning CurveJSON onlyGo templates

Migration Path

Step 1: Start with Variables

{
  "port": {{ .env.port }},
  "name": "{{ .env.environment }}"
}

Step 2: Extract Repeated Config

{{ include "security.tmpl" }}
{{ include "telemetry.tmpl" }}

Step 3: Organize by Feature

partials/
├── auth.tmpl
├── caching.tmpl
├── cors.tmpl
└── rate-limiting.tmpl

Step 4: Add Logic

{{ range .endpoints }}
  {{ template "endpoint.tmpl" . }}
{{ end }}

Learn More

Build docs developers (and LLMs) love