Zuplo
API Gateway

Migrating from KrakenD to Zuplo: Configuration Mapping and Architecture Translation

Nate TottenNate Totten
May 14, 2026
15 min read

A practical guide to migrating from KrakenD to Zuplo — covering krakend.json translation, plugin-to-policy mapping, and a phased migration plan.

KrakenD is a strong choice for teams that want a stateless, high-performance API gateway with a declarative configuration model. But as API programs grow, teams hit a ceiling: custom logic requires Go plugins or Lua scripts, Enterprise Edition feature gates lock critical capabilities behind paid licensing, and self-hosting means your platform team owns deployment, scaling, and patching.

If your team has outgrown KrakenD’s declarative-only model and is looking for a managed, programmable API gateway, this guide walks you through every step of migrating from KrakenD to Zuplo.

Table of Contents

  1. Why Teams Migrate from KrakenD
  2. Architecture Comparison
  3. Configuration Translation
  4. Plugin and Middleware Mapping
  5. Authentication Migration
  6. Rate Limiting and Caching Migration
  7. Custom Plugin Migration
  8. Developer Portal Migration
  9. CI/CD and GitOps
  10. Step-by-Step Migration Playbook
  11. Enterprise Edition Feature Parity
  12. Frequently Asked Questions
  13. Next Steps

Why Teams Migrate from KrakenD

KrakenD’s audience is config-as-code engineers who value a stateless, declarative gateway. That philosophy works well until it doesn’t. Here are the pain points that drive teams to explore alternatives:

  • The declarative-only ceiling — KrakenD processes all configuration from a single JSON file loaded at startup. When you need imperative logic — conditional routing, dynamic header injection based on request bodies, or custom response composition — you’re pushed into Go plugins, Lua scripts, or CEL expressions. Each has capability trade-offs, and none offers the developer experience of a modern language with full IDE support.
  • Self-hosting burden — KrakenD has no managed cloud offering. Your team owns deployment, scaling, patching, and capacity planning. Running KrakenD in production means maintaining Docker or Kubernetes infrastructure, handling rolling upgrades, and managing TLS certificates — operational work that doesn’t ship API features.
  • Enterprise Edition feature gates — API key authentication, OpenAPI import/export, tiered rate limiting, basic auth, gRPC support, WebSockets, and the AI Gateway are all Enterprise-only features. Teams running production APIs face Enterprise licensing decisions for capabilities that most managed platforms include by default.
  • Plugin compatibility constraints — Custom Go plugins must be compiled against the exact same build arguments and module version as the target KrakenD binary. A KrakenD upgrade can break every custom plugin, forcing recompilation and testing across your entire plugin library.
  • No built-in developer portal — KrakenD does not include a hosted developer portal with self-serve API key management. Teams building API products need to build or integrate a separate documentation and key management solution using tools like Swagger UI or Redoc, adding another system to maintain.

Architecture Comparison

Understanding the architectural differences helps you plan a clean migration.

KrakenD’s Architecture

KrakenD is a stateless API gateway written in Go, built on the Lura framework (a Linux Foundation project). A typical deployment involves:

  • A single declarative JSON configuration (krakend.json) loaded at startup that defines all endpoints, backends, and middleware
  • Stateless instances deployed on Docker or Kubernetes — no database, no control plane
  • Endpoints that expose paths to clients, each mapping to one or more backends (your upstream services)
  • Extra config blocks for middleware (rate limiting, JWT validation, caching, CORS) attached to endpoints or backends
  • Go plugins, Lua scripts, or CEL expressions for custom logic beyond what the declarative config supports
  • flexible_config for templating and splitting configuration using Go templates

Zuplo’s Architecture

Zuplo takes a fundamentally different approach:

  • Edge-native deployment — Your gateway runs across 300+ data centers worldwide automatically. There is no single-region deployment to manage or scale.
  • OpenAPI-native routing — Routes are defined in a standard routes.oas.json file using the OpenAPI specification format, extended with x-zuplo-route for gateway behavior.
  • TypeScript policies — Instead of Go plugins or Lua scripts, you write policies in TypeScript with full IDE support, type safety, and access to npm packages.
  • Git-native CI/CD — Every configuration change is version-controlled. Push to GitHub, and your gateway deploys to the edge automatically. Every branch gets its own isolated preview environment.
  • Fully managed — No Docker containers, no Kubernetes clusters, no capacity planning. Zuplo handles all infrastructure, scaling, and updates.
  • Built-in developer portalAuto-generated from your OpenAPI spec, with API key management and API explorer included.

Configuration Translation

The most important step in migration is translating your krakend.json into Zuplo’s route and policy model.

KrakenD Endpoints → Zuplo Routes

In KrakenD, you define endpoints and backends in krakend.json:

JSONjson
{
  "$schema": "https://www.krakend.io/schema/krakend.json",
  "version": 3,
  "endpoints": [
    {
      "endpoint": "/api/users/{id}",
      "method": "GET",
      "backend": [
        {
          "url_pattern": "/users/{id}",
          "host": ["http://user-service:8080"]
        }
      ],
      "extra_config": {
        "auth/validator": {
          "alg": "RS256",
          "jwk_url": "https://auth.example.com/.well-known/jwks.json",
          "issuer": "https://auth.example.com/"
        },
        "qos/ratelimit/router": {
          "max_rate": 60,
          "client_max_rate": 10,
          "strategy": "ip"
        }
      }
    }
  ]
}

In Zuplo, the same endpoint is defined in routes.oas.json — a standard OpenAPI file extended with Zuplo configuration:

JSONjson
{
  "paths": {
    "/api/users/{id}": {
      "get": {
        "summary": "Get User by ID",
        "x-zuplo-route": {
          "corsPolicy": "none",
          "handler": {
            "export": "urlRewriteHandler",
            "module": "$import(@zuplo/runtime)",
            "options": {
              "rewritePattern": "http://user-service:8080/users/${params.id}"
            }
          },
          "policies": {
            "inbound": ["jwt-auth", "rate-limit"]
          }
        }
      }
    }
  }
}

The corresponding policies are defined in policies.json:

JSONjson
{
  "policies": [
    {
      "name": "jwt-auth",
      "policyType": "open-id-jwt-auth-inbound",
      "handler": {
        "export": "OpenIdJwtInboundPolicy",
        "module": "$import(@zuplo/runtime)",
        "options": {
          "issuer": "https://auth.example.com/",
          "jwkUrl": "https://auth.example.com/.well-known/jwks.json"
        }
      }
    },
    {
      "name": "rate-limit",
      "policyType": "rate-limit-inbound",
      "handler": {
        "export": "RateLimitInboundPolicy",
        "module": "$import(@zuplo/runtime)",
        "options": {
          "rateLimitBy": "ip",
          "requestsAllowed": 10,
          "timeWindowMinutes": 1
        }
      }
    }
  ]
}

Key differences to note:

  • OpenAPI-native — Zuplo routes are standard OpenAPI paths. You can import an existing OpenAPI spec and add x-zuplo-route extensions.
  • Policies replace extra_config — Instead of attaching middleware via extra_config blocks, you reference named policies in your route config.
  • Everything in Git — Both routes.oas.json and policies.json are files in your repository. There is no startup config reload — push to Git and Zuplo deploys automatically.

KrakenD Backends → Zuplo Handlers

KrakenD’s backend array defines where requests are forwarded. Each backend can specify response manipulation (allow/deny lists, field mapping, group names).

In Zuplo, backend routing uses handlers:

  • URL Rewrite Handler — Rewrites the incoming URL using template interpolation with path parameters, query strings, and environment variables.
  • URL Forward Handler — Forwards the request to a backend, preserving the request path.

For KrakenD’s response manipulation features (allow lists, field mapping, grouping), use Zuplo’s Custom Code Outbound Policy to transform responses in TypeScript.

KrakenD flexible_config → Git + Environment Variables

KrakenD’s flexible_config lets you split krakend.json into templates and partials using Go template syntax. In Zuplo, this is handled natively:

  • Configuration is already split — Routes live in routes.oas.json, policies live in policies.json, and custom code lives in modules/.
  • Environment variables — Referenced as $env(VARIABLE_NAME) in configuration files or imported from @zuplo/runtime in TypeScript.
  • Git branching — Each branch gets its own isolated environment, replacing the need for environment-specific config templates.

Plugin and Middleware Mapping

One of the biggest questions during migration is: “What replaces my KrakenD middleware?” Below is a mapping of KrakenD’s most common features to their Zuplo equivalents.

Authentication

  • auth/validator (JWT)JWT Auth Policy (OpenID) — Validates JWT tokens from any OpenID-compliant provider. Works with Auth0, Okta, Azure AD, and others out of the box.
  • auth/api-keys (Enterprise) → API Key Authentication — Zuplo’s built-in API key policy includes a managed key service with self-service key management through the developer portal. Available on all plans — no Enterprise gate.
  • auth/basic (Enterprise) → Basic Auth Policy — Built-in support for HTTP Basic authentication.
  • auth/signer (JWT signing)Custom Code Policy — Write token signing logic in TypeScript using standard crypto libraries.

Traffic Control

  • qos/ratelimit/routerRate Limiting Policy — Supports per-user, per-IP, per-API-key, or custom attribute-based rate limits. No Redis or separate database needed.
  • qos/ratelimit/proxyRate Limiting Policy — Apply rate limits at the route level to control traffic to specific backends.
  • qos/circuit-breakerCustom Code Policy — Implement circuit breaker patterns in TypeScript with full control over failure thresholds and recovery logic.

Request and Response Transformation

  • modifier/martian (DSL)Set Headers Policy + Custom Code Policy — Combine built-in header policies with custom TypeScript transformation.
  • modifier/body-generator (Enterprise) → Custom Code Policy — Transform request bodies in TypeScript with full type safety.
  • modifier/response-body-generator (Enterprise) → Custom Code Outbound Policy — Transform response bodies before they reach the client.
  • modifier/luaCustom Code Policy — Replace Lua scripts with TypeScript policies. TypeScript gives you IDE autocomplete, type checking, and access to the npm ecosystem.

Validation

  • validation/json-schemaRequest Validation Policy — Validates request bodies, query parameters, path parameters, and headers against your OpenAPI schema definitions automatically.

Security

  • security/corsCustom CORS Policy — Configure allowed origins, methods, and headers per route.
  • security/bot-detectorBot Detection Policy (Enterprise add-on) — Bot scoring and detection for identifying automated traffic.

Caching

  • qos/http-cache → Zuplo runs on a global edge network with built-in caching support. Configure cache headers on your responses, and Zuplo’s edge network handles caching automatically.

Authentication Migration

Authentication is typically the most critical part of any gateway migration. Here is how to translate each KrakenD auth mechanism.

JWT Authentication

KrakenD’s auth/validator validates JWT tokens using JWKS endpoints. Zuplo’s JWT Auth Policy provides the same functionality with a simpler configuration model.

KrakenD (krakend.json extra_config):

JSONjson
{
  "extra_config": {
    "auth/validator": {
      "alg": "RS256",
      "jwk_url": "https://your-tenant.auth0.com/.well-known/jwks.json",
      "issuer": "https://your-tenant.auth0.com/",
      "audience": ["https://api.example.com"]
    }
  }
}

Zuplo (policies.json):

JSONjson
{
  "name": "jwt-auth",
  "policyType": "open-id-jwt-auth-inbound",
  "handler": {
    "export": "OpenIdJwtInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "issuer": "https://your-tenant.auth0.com/",
      "audience": "https://api.example.com",
      "jwkUrl": "https://your-tenant.auth0.com/.well-known/jwks.json"
    }
  }
}

If you use provider-specific JWT configurations, Zuplo offers dedicated policies for Auth0, Clerk, Okta, Firebase, AWS Cognito, and Supabase.

API Key Authentication

KrakenD’s API key authentication is an Enterprise-only feature. Zuplo’s API Key Authentication policy is available on every plan and includes a complete managed key service:

  1. Create consumers with metadata (plan tier, organization, custom attributes)
  2. Issue API keys that are automatically validated at the edge
  3. Let developers self-manage their keys through the developer portal
  4. Access consumer metadata in your policies via request.user

To migrate API key consumers, use Zuplo’s API Key Management API to programmatically create consumers and import keys.

Identity Provider SSO

KrakenD Enterprise supports multiple identity providers per endpoint. Zuplo supports multiple auth methods per route through composite policies or multiple auth policies with the allowUnauthenticatedRequests option. See the multiple authentication policies guide for configuration details.

Rate Limiting and Caching Migration

Rate Limiting

KrakenD offers endpoint-level (qos/ratelimit/router) and backend-level (qos/ratelimit/proxy) rate limiting. The Community Edition supports basic rate limiting, while tiered and Redis-backed rate limiting are Enterprise-only.

Zuplo’s Rate Limiting Policy provides:

  • Per-user, per-IP, or per-key limiting — Choose what attribute to rate limit by.
  • Custom bucket functions — Write a TypeScript function to define custom rate limit grouping logic (e.g., rate limit by customer tier stored in API key metadata).
  • No external dependencies — Unlike KrakenD’s Redis-backed strategy, Zuplo’s rate limiter works out of the box across all edge locations.
  • Standard 429 responses — Automatically returns 429 Too Many Requests with appropriate Retry-After headers.

Dynamic Rate Limiting by Customer Tier

In KrakenD Enterprise, tiered rate limiting requires Enterprise licensing. In Zuplo, you write a short TypeScript function:

TypeScripttypescript
import {
  CustomRateLimitDetails,
  ZuploContext,
  ZuploRequest,
} from "@zuplo/runtime";

export function rateLimit(
  request: ZuploRequest,
  context: ZuploContext,
  policyName: string,
): CustomRateLimitDetails | undefined {
  const user = request.user;

  if (user.data.customerType === "premium") {
    return {
      key: user.sub,
      requestsAllowed: 1000,
      timeWindowMinutes: 1,
    };
  }

  return {
    key: user.sub,
    requestsAllowed: 50,
    timeWindowMinutes: 1,
  };
}

This runs at the edge with no separate infrastructure required.

Caching

KrakenD’s qos/http-cache provides proxy-level response caching. Zuplo runs on a global edge network where caching is handled at the network layer. Set appropriate Cache-Control headers on your backend responses, and Zuplo’s edge infrastructure caches responses automatically across 300+ locations.

For more granular caching control, use a Custom Code Outbound Policy to set or modify cache headers before responses reach the client.

Custom Plugin Migration

If your team has built custom KrakenD plugins in Go or Lua scripts, migrating them to Zuplo TypeScript policies is usually more straightforward than you might expect. Zuplo’s Custom Code Inbound Policy lets you write arbitrary request processing logic in TypeScript.

KrakenD Lua Script vs. Zuplo TypeScript Policy

Here is a side-by-side comparison of a simple header-injection middleware:

KrakenD (Lua script):

lua
function pre_proxy(request)
  request:headers("X-Custom-Header", "my-value")
  request:headers("X-Request-Timestamp", os.time())
end

Zuplo (TypeScript):

TypeScripttypescript
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function (
  request: ZuploRequest,
  context: ZuploContext,
  options: { headerValue: string },
  policyName: string,
) {
  const newRequest = new ZuploRequest(request);
  newRequest.headers.set("X-Custom-Header", options.headerValue);
  newRequest.headers.set("X-Request-Timestamp", Date.now().toString());
  return newRequest;
}

KrakenD Go Plugin vs. Zuplo TypeScript Policy

Go plugins are KrakenD’s most powerful extension mechanism, but they come with significant constraints: plugins must be compiled against the exact KrakenD binary version, they require a Go development environment, and debugging is difficult. A KrakenD upgrade can break every custom plugin.

In Zuplo, the same logic is a TypeScript function with:

  • Full IDE support — Autocomplete, type checking, and inline documentation in VS Code or any TypeScript editor.
  • Standard Web APIs — Zuplo uses standard Request, Response, and Headers objects. If you know the Fetch API, you know how to write Zuplo policies.
  • No binary coupling — TypeScript policies don’t need to be recompiled when the platform updates.
  • Easier testing — Unit test your policies like any TypeScript function.

Developer Portal Migration

KrakenD does not include a built-in hosted developer portal with self-serve API key management. Teams using KrakenD typically rely on external tools like Swagger UI, Redoc, or custom-built documentation portals. This means maintaining a separate system for API documentation, key distribution, and developer onboarding.

Zuplo’s developer portal is built into the platform and auto-generated from your OpenAPI spec. When you update your routes in routes.oas.json, the portal updates automatically. Features include:

  • Automatic API documentation — Generated directly from your OpenAPI specification.
  • API Explorer — Developers can test your API directly from the docs.
  • Self-serve API key management — Consumers sign up, get keys, and manage them without your intervention.
  • Custom branding and pages — Add custom Markdown, MDX, or React pages to your portal.
  • Built-in analytics — Consumers can see their own usage data.

For teams migrating from KrakenD, the developer portal is often the single biggest capability gain — it replaces a system you would have had to build and maintain separately.

CI/CD and GitOps

KrakenD’s Workflow

KrakenD’s configuration-as-code approach works well with CI/CD, but teams are responsible for the full deployment pipeline:

  1. Edit krakend.json (or templates if using flexible_config)
  2. Run krakend check to validate syntax
  3. Build a Docker image or deploy to Kubernetes
  4. Roll out new instances with the updated configuration
  5. Handle rolling restarts to avoid downtime
  6. Manage configuration across multiple environments manually

Zuplo’s Workflow

Zuplo’s deployment model is Git-native:

  1. Your gateway configuration (routes.oas.json, policies.json, and custom TypeScript modules) lives in a GitHub repository
  2. Push to a branch, and Zuplo automatically creates a preview deployment
  3. Merge to main, and the production gateway updates across all 300+ edge locations
  4. Every deployment is immutable and versioned — rollback by reverting a commit
  5. Environment variables handle per-environment differences (staging vs. production)

There is no Docker image to build, no Kubernetes rollout to manage, and no configuration reload to coordinate.

Step-by-Step Migration Playbook

A typical KrakenD-to-Zuplo migration follows three phases.

Phase 1: Audit and Setup (Week 1)

Inventory your KrakenD setup:

  • Export or catalog your krakend.json (or assembled config if using flexible_config)
  • List all endpoints, backends, and their extra_config middleware
  • Identify any Go plugins or Lua scripts that need translation
  • Document rate limiting, JWT validation, and caching configurations
  • Note any Enterprise-only features you depend on

Set up Zuplo:

  • Create a Zuplo account at portal.zuplo.com
  • Connect your GitHub repository
  • Translate KrakenD endpoints to routes.oas.json routes
  • Configure authentication policies to match your KrakenD auth middleware
  • Set up rate limiting policies
  • Add environment variables for backend URLs and secrets

Phase 2: Policy Translation and Testing (Week 2–3)

  • Translate Go plugins and Lua scripts to TypeScript policies
  • Migrate request/response transformations to Zuplo custom code policies
  • Configure the developer portal with your OpenAPI spec
  • Test all routes against your backend services
  • Validate authentication flows end-to-end
  • Run load tests to verify rate limiting behavior
  • Review logging and observability configuration

Phase 3: Parallel Running and Cutover (Week 3–4)

Run Zuplo alongside KrakenD to validate behavior:

  1. Deploy your Zuplo project by pushing to your Git repository
  2. Set up a custom domain for your Zuplo gateway
  3. Route a subset of traffic to Zuplo using DNS-based routing
  4. Compare response behavior between KrakenD and Zuplo
  5. Gradually increase traffic to Zuplo as you validate correctness
  6. Complete the full cutover once you’re confident

Rollback strategy:

  • Configuration rollback — Revert the Git commit and push. The previous gateway configuration deploys automatically.
  • DNS rollback — If you kept KrakenD running during the parallel phase, switch DNS back to KrakenD’s endpoints.

Enterprise Edition Feature Parity

Many KrakenD Enterprise-only features are available on every Zuplo plan. Here is how they map:

Features Gated Behind KrakenD Enterprise

  • API key authentication — Available on every Zuplo plan via the API Key Authentication Policy.
  • OpenAPI import/export — Zuplo is OpenAPI-native. Routes are defined in OpenAPI format, and the developer portal auto-generates from your spec.
  • Tiered rate limiting — Zuplo supports custom rate limit functions that let you implement tiered limits based on consumer metadata.
  • gRPC support (Enterprise) — Not directly equivalent in Zuplo, which focuses on HTTP/REST APIs. If gRPC is a primary requirement, evaluate whether Zuplo’s HTTP-based approach meets your needs.
  • WebSockets (Enterprise) — Zuplo supports WebSocket proxying for real-time communication use cases via the WebSocket Handler (Enterprise).
  • AI Gateway and MCP (Enterprise) — Zuplo includes an integrated AI Gateway with multi-provider model routing, semantic caching, and prompt injection protection. The MCP Gateway lets you turn any API into a remote MCP server or govern third-party MCP servers.

Managed Deployment

KrakenD is self-hosted only — there is no managed cloud offering. Zuplo provides managed dedicated deployment on AWS, Azure, GCP, Akamai, and other providers with single-tenant isolation, private networking, and data residency controls. Your team gets production-grade infrastructure without the operational burden.

Observability

KrakenD offers OpenTelemetry, Prometheus, Datadog, and other integrations. Zuplo includes built-in request analytics and supports integrations with Datadog, Dynatrace, and other providers via log plugins.

Frequently Asked Questions

Does Zuplo support KrakenD’s declarative API aggregation?

KrakenD excels at declarative API aggregation — merging responses from multiple backends in parallel. Zuplo supports routing to multiple backends and composing responses using custom TypeScript logic, but the approach is programmatic rather than declarative. If backend-for-frontend aggregation is your primary use case, evaluate whether Zuplo’s TypeScript-based approach meets your needs.

How long does a KrakenD migration take?

For most teams using built-in KrakenD features (JWT validation, rate limiting, response transformation), migration takes two to four weeks. Teams with custom Go plugins or extensive Lua scripts should plan for additional time to rewrite those in TypeScript.

Do I need to change my backend services?

No. Zuplo proxies requests to your existing backends using the URL Rewrite handler. Your backend services do not need any changes — Zuplo forwards requests just like KrakenD does.

Can I run Zuplo alongside KrakenD during migration?

Yes. The recommended approach is to run both gateways in parallel during the cutover phase, using DNS or a load balancer to gradually shift traffic from KrakenD to Zuplo.

What replaces KrakenD’s flexible_config?

KrakenD’s flexible_config lets you template and split krakend.json using Go templates. In Zuplo, configuration is natively split across routes.oas.json and policies.json files in a Git repository. Environment-specific values use environment variables referenced as $env(VARIABLE_NAME) in configuration.

Does Zuplo have a developer portal?

Yes. Zuplo includes a developer portal on every plan, auto-generated from your OpenAPI specification. It provides interactive API documentation, an API explorer, and self-serve API key management. KrakenD does not include a developer portal.

Next Steps

Ready to migrate? Sign up for a free Zuplo account and follow the Getting Started Guide to set up your first gateway in minutes.

For planning your migration: