---
title: "Migrating from Traefik to Zuplo: Configuration Mapping and Step-by-Step Guide"
description: "A practical guide for teams migrating from Traefik Proxy to Zuplo, covering middleware-to-policy mapping, configuration translation, and a phased migration plan."
canonicalUrl: "https://zuplo.com/learning-center/migrating-from-traefik-to-zuplo"
pageType: "learning-center"
authors: "nate"
tags: "API Gateway, Tutorial"
image: "https://zuplo.com/og?text=Migrating%20from%20Traefik%20to%20Zuplo"
---
Traefik is a popular cloud-native reverse proxy that excels at dynamic service
discovery and container-native routing. But as your API program grows beyond
internal service routing into external developer-facing APIs, Traefik's lack of
built-in API management capabilities — developer portals, API key management,
analytics, and monetization — becomes a bottleneck. If your team is evaluating a
move from Traefik to a fully managed API gateway, this guide walks you through
every step.

## Table of Contents

1. [Why Teams Migrate from Traefik](#why-teams-migrate-from-traefik)
2. [Architecture Comparison](#architecture-comparison)
3. [Configuration Mapping](#configuration-mapping)
4. [Middleware-to-Policy Mapping](#middleware-to-policy-mapping)
5. [Authentication Migration](#authentication-migration)
6. [Rate Limiting Migration](#rate-limiting-migration)
7. [Custom Middleware Migration](#custom-middleware-migration)
8. [Adding API Management Capabilities](#adding-api-management-capabilities)
9. [Step-by-Step Migration Plan](#step-by-step-migration-plan)
10. [Frequently Asked Questions](#frequently-asked-questions)
11. [Next Steps](#next-steps)

## Why Teams Migrate from Traefik

Traefik Proxy is a capable reverse proxy, but several pain points drive teams to
look for alternatives:

- **Infrastructure overhead** — Running Traefik requires managing Docker hosts
  or Kubernetes clusters, configuring Helm charts, and maintaining the
  underlying compute infrastructure. Even straightforward setups need
  monitoring, scaling, and upgrade management.
- **No developer portal on the open-source tier** — Traefik Proxy has no
  developer portal. Traefik Hub API Management (the highest commercial tier)
  added an API Portal, but it requires a separate license upgrade from the
  open-source proxy. If you need external developers to discover your API, read
  documentation, and self-manage API keys without paying for the top tier, you
  must build or buy a separate solution.
- **Limited API management** — Traefik Proxy is a routing and load-balancing
  tool. Features like API key management, usage analytics, and monetization
  require upgrading through Traefik Hub's commercial tiers, with each step
  adding cost and complexity.
- **Fragmented product tiers** — Full API management requires moving from
  Traefik Proxy (open source) to Traefik Hub API Gateway, then to Traefik Hub
  API Management. Each tier adds cost and licensing overhead.
- **Go-based plugin system** — Extending Traefik with custom middleware
  typically involves writing Go plugins interpreted at runtime by Yaegi (an
  embedded Go interpreter). Traefik also supports WASM plugins, but both
  approaches limit the developer pool and slow iteration compared to modern
  scripting-based approaches.

## Architecture Comparison

Understanding the architectural differences helps you plan a clean migration.

### Traefik's Architecture

Traefik is built as a cloud-native reverse proxy designed for Docker and
Kubernetes environments. A typical deployment involves:

- **Entrypoints** that listen on specific ports for incoming traffic
- **Routers** that match requests based on rules (host, path, headers)
- **Middlewares** that transform requests before they reach services (rate
  limiting, authentication, headers, path stripping)
- **Services** that define how to reach your backend (load balancers, weighted
  round robin, mirroring)
- **Providers** that supply dynamic configuration (Docker labels, Kubernetes
  CRDs, file-based YAML/TOML, Consul, etcd)
- **Automatic TLS** via Let's Encrypt ACME integration

Configuration happens through Docker labels, Kubernetes IngressRoute CRDs, or
YAML/TOML files — each defining routers, middlewares, and services.

### Zuplo's Architecture

Zuplo takes a fundamentally different approach:

- **Edge-native deployment** — Your gateway runs across 300+ data centers
  worldwide automatically. There is no infrastructure 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 middleware plugins, 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.
- **Fully managed** — No Docker hosts, no Kubernetes clusters, no Helm charts.
  Zuplo handles all infrastructure, scaling, TLS, and updates.
- **Built-in developer portal** — Auto-generated from your OpenAPI spec, with
  API key management and an API explorer included.

## Configuration Mapping

This section shows how Traefik concepts map to Zuplo equivalents.

### Routers → Zuplo Routes

In Traefik, routers match incoming requests using rules and direct them to
services. Here is a typical Traefik YAML configuration:

```yaml
# traefik dynamic config
http:
  routers:
    user-api:
      rule: "Host(`api.example.com`) && PathPrefix(`/users`)"
      service: user-service
      middlewares:
        - rate-limit
        - api-auth
      tls:
        certResolver: letsencrypt
  services:
    user-service:
      loadBalancer:
        servers:
          - url: "http://user-backend:8080"
```

In Zuplo, the equivalent lives in `routes.oas.json` — a standard OpenAPI file
extended with Zuplo configuration:

```json
{
  "paths": {
    "/users": {
      "get": {
        "summary": "Get Users",
        "x-zuplo-route": {
          "corsPolicy": "none",
          "handler": {
            "export": "urlRewriteHandler",
            "module": "$import(@zuplo/runtime)",
            "options": {
              "rewritePattern": "http://user-backend:8080/users"
            }
          },
          "policies": {
            "inbound": ["rate-limit", "api-key-auth"]
          }
        }
      }
    }
  }
}
```

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 middleware** — Instead of attaching middleware via labels
  or YAML, you reference named policies in your route config.
- **Everything in Git** — Both `routes.oas.json` and `policies.json` are files
  in your repository. There are no Docker labels or Kubernetes CRDs to manage.
- **Automatic TLS** — Zuplo handles TLS as part of its managed edge deployment.
  You never need to configure certificate resolvers or ACME providers.

### Services / Load Balancers → URL Rewrite Handler

Traefik services define how to reach your backend, including load balancing
across multiple servers. In Zuplo, the
[URL Rewrite handler](https://zuplo.com/docs/handlers/url-rewrite) proxies
requests to your backend:

```json
{
  "handler": {
    "export": "urlRewriteHandler",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "rewritePattern": "https://api-backend.example.com/${params.path}"
    }
  }
}
```

The URL Rewrite handler supports dynamic values using JavaScript template
literal syntax. You can reference `env` (environment variables), `params` (path
parameters), `query` (query strings), and `headers` from the incoming request.

### TLS Configuration → Automatic TLS

Traefik's automatic Let's Encrypt integration is one of its best features for
self-hosted environments. With Zuplo, TLS is simply included with zero
configuration — certificates are provisioned and renewed automatically as part
of the managed edge deployment.

## Middleware-to-Policy Mapping

One of the biggest questions during migration is: "What replaces my Traefik
middleware?" Below is a mapping of Traefik's most commonly used middleware to
their Zuplo equivalents.

### Traffic Control

- **RateLimit** →
  [Rate Limiting Policy](https://zuplo.com/docs/policies/rate-limit-inbound) —
  Supports per-user, per-IP, per-API-key, or custom attribute-based rate limits.
  No Redis or external data store needed.
- **InFlightReq** → Zuplo's edge-native architecture handles concurrency at the
  platform level. For custom concurrency control, use a
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound).
- **CircuitBreaker** → Implement with a
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
  or use Zuplo's built-in health monitoring.

### Authentication

- **BasicAuth** →
  [Basic Auth Policy](https://zuplo.com/docs/policies/basic-auth-inbound) —
  Built-in support for HTTP Basic authentication with configurable accounts.
- **ForwardAuth** →
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
  — Write a TypeScript policy that calls your external auth service and
  validates the response.
- **DigestAuth** →
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
  — Implement digest authentication logic in TypeScript.

### Path and URL Manipulation

- **StripPrefix** → The
  [URL Rewrite handler](https://zuplo.com/docs/handlers/url-rewrite) handles
  path manipulation natively. Map your public path to a different backend path
  using template syntax:
  `"rewritePattern": "https://backend.example.com${params.path}"`.
- **AddPrefix** → Use the URL Rewrite handler to add prefixes when forwarding:
  `"rewritePattern": "https://backend.example.com/api/v1${pathname}"`.
- **ReplacePath** / **ReplacePathRegex** → The URL Rewrite handler supports
  arbitrary path rewriting. For complex regex transformations, use a
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound).
- **RedirectScheme** / **RedirectRegex** → Zuplo handles HTTPS automatically at
  the edge. For custom redirects, use the
  [Redirect handler](https://zuplo.com/docs/handlers/redirect).

### Headers

- **Headers** (add/remove request and response headers) →
  [Add or Set Request Headers Policy](https://zuplo.com/docs/policies/set-headers-inbound)
  and
  [Set Response Headers Policy](https://zuplo.com/docs/policies/set-headers-outbound)
  — Configure security headers (HSTS, X-Frame-Options, CSP) and custom headers
  declaratively.

### Request and Response Modification

- **Compress** → Zuplo handles compression at the edge automatically.
- **ContentType** → Use a
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
  to set or validate content types.
- **Retry** → Implement retry logic in a
  [Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
  using standard `fetch` with retry patterns.

### Validation

- **Request body/schema validation** (commonly done with custom Traefik plugins)
  →
  [Request Validation Policy](https://zuplo.com/docs/policies/request-validation-inbound)
  — Validates request bodies, query parameters, path parameters, and headers
  against your OpenAPI schema definitions automatically.

## Authentication Migration

Authentication is typically the most critical part of any gateway migration.
Here is how to approach each Traefik auth middleware.

### BasicAuth → Basic Auth Policy

Traefik's BasicAuth middleware uses htpasswd-format credentials configured via
labels or YAML:

```yaml
# Traefik BasicAuth middleware
http:
  middlewares:
    auth:
      basicAuth:
        users:
          - "admin:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
```

Zuplo's [Basic Auth Policy](https://zuplo.com/docs/policies/basic-auth-inbound)
provides equivalent functionality with environment variable support for secrets:

```json
{
  "name": "basic-auth",
  "policyType": "basic-auth-inbound",
  "handler": {
    "export": "BasicAuthInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "accounts": [
        {
          "username": "$env(ADMIN_USERNAME)",
          "password": "$env(ADMIN_PASSWORD)",
          "data": {
            "role": "admin"
          }
        }
      ]
    }
  }
}
```

### ForwardAuth → JWT or API Key Authentication

Traefik's ForwardAuth middleware delegates authentication to an external
service. If your forward auth service validates JWTs, migrate to Zuplo's
[JWT Auth Policy](https://zuplo.com/docs/policies/open-id-jwt-auth-inbound):

```json
{
  "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 your forward auth service validates API keys, switch to Zuplo's
[API Key Authentication policy](https://zuplo.com/docs/policies/api-key-inbound),
which provides a managed key service with self-service key management through
the developer portal.

## Rate Limiting Migration

Traefik's RateLimit middleware uses a token bucket algorithm configured via
labels or YAML:

```yaml
# Traefik rate limiting
http:
  middlewares:
    rate-limit:
      rateLimit:
        average: 100
        period: 1m
        burst: 50
```

Zuplo's
[Rate Limiting policy](https://zuplo.com/docs/policies/rate-limit-inbound)
provides more granular control:

```json
{
  "name": "rate-limit",
  "policyType": "rate-limit-inbound",
  "handler": {
    "export": "RateLimitInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "rateLimitBy": "user",
      "requestsAllowed": 100,
      "timeWindowMinutes": 1
    }
  }
}
```

Key advantages of Zuplo's rate limiting:

- **Per-user, per-IP, or per-key limiting** — Choose what attribute to rate
  limit by, rather than only client IP.
- **Custom bucket functions** — Write a TypeScript function to define custom
  rate limit grouping logic (for example, rate limit by customer tier using API
  key metadata).
- **No external dependencies** — Zuplo's rate limiter works out of the box
  without managing additional infrastructure like Redis or external data stores.
- **Standard 429 responses** — Automatically returns `429 Too Many Requests`
  with appropriate `Retry-After` headers.

## Custom Middleware Migration

If your team has built custom Traefik middleware plugins in Go using the Yaegi
interpreter, migrating them to Zuplo TypeScript policies is usually simpler than
you might expect. Zuplo's
[Custom Code Inbound Policy](https://zuplo.com/docs/policies/custom-code-inbound)
lets you write arbitrary request processing logic in TypeScript.

### Traefik Go Plugin vs. Zuplo TypeScript Policy

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

**Traefik (Go):**

```go
package header_plugin

import (
    "context"
    "net/http"
)

type Config struct {
    HeaderValue string `json:"headerValue"`
}

func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
    return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        req.Header.Set("X-Custom-Header", config.HeaderValue)
        next.ServeHTTP(rw, req)
    }), nil
}
```

**Zuplo (TypeScript):**

```typescript
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);
  return newRequest;
}
```

Key advantages of the TypeScript approach:

- **Full IDE support** — Autocomplete, type checking, and inline documentation
  in VS Code or any TypeScript-capable editor.
- **npm ecosystem** — Import any npm package for tasks like data validation,
  cryptography, or API calls.
- **Standard Web APIs** — Zuplo uses standard `Request`, `Response`, and
  `Headers` objects. If you know the Fetch API, you know how to write Zuplo
  policies.
- **Faster iteration** — No compilation step or binary rebuilds. Push your
  TypeScript, and it deploys to the edge.

## Adding API Management Capabilities

Migrating from Traefik to Zuplo is not just a one-for-one replacement — it is an
upgrade to full API lifecycle management. Here are the capabilities you gain
that Traefik does not provide:

### Developer Portal

Zuplo's developer portal is
[auto-generated from your OpenAPI spec](https://zuplo.com/docs/dev-portal/introduction).
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-service API key management** — Consumers sign up, get keys, and manage
  them without your intervention.
- **Custom branding** — Add your own logo, colors, and custom pages.

### API Key Management

Zuplo's [API key service](https://zuplo.com/docs/articles/api-key-management)
provides a complete consumer management system:

- Create consumers with metadata (plan tier, organization, usage limits)
- Issue API keys that are validated at the edge
- Manage keys programmatically via the
  [API Key Management API](https://zuplo.com/docs/articles/api-key-api)
- Let developers self-manage their keys through the developer portal

### API Monetization

With
[Zuplo's monetization features](https://zuplo.com/docs/articles/monetization),
you can charge for API access with usage-based billing powered by Stripe — a
capability that is not available with Traefik at any tier.

### Analytics and Observability

Zuplo includes built-in analytics and integrates with popular observability
platforms. You get request logging, error tracking, and usage metrics without
configuring separate monitoring stacks.

## Step-by-Step Migration Plan

A typical Traefik-to-Zuplo migration follows three phases:

### Phase 1: Setup and Configuration (Week 1)

- Create a [Zuplo account](https://portal.zuplo.com) and project
- Connect your GitHub repository
- Inventory your Traefik routers, middlewares, and services
- Translate routers to `routes.oas.json` format with `x-zuplo-route` extensions
- Configure authentication policies to match your Traefik auth middleware
- Set up rate limiting policies
- Add
  [environment variables](https://zuplo.com/docs/articles/environment-variables)
  for backend URLs, secrets, and per-environment config

### Phase 2: Custom Logic and Testing (Week 2)

- Migrate custom Go middleware plugins to TypeScript policies
- Set up request/response header transformation policies
- Configure the developer portal
- 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: Cutover and Validation (Week 3)

- Run Zuplo in parallel alongside Traefik (both receiving traffic)
- Compare response behavior between Traefik and Zuplo
- Gradually shift external API traffic from Traefik to Zuplo using DNS
- Monitor error rates, latency, and throughput
- Complete DNS cutover to Zuplo for external API traffic
- Keep Traefik running for internal service routing if needed
- Update developer documentation and portal URLs

### Rollback Strategy

Because Zuplo deployments are Git-based, rollback is straightforward:

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

## Frequently Asked Questions

### Can Zuplo replace Traefik for internal service routing?

Zuplo is designed for external-facing API management rather than internal
east-west traffic. If you use Traefik for internal container-to-container
routing, keep Traefik for that and add Zuplo for your external API layer. You
get developer portals, API key management, and monetization without replacing
your internal infrastructure.

### How long does a Traefik-to-Zuplo migration take?

Most teams complete the migration in one to three weeks depending on the number
of routes and custom middleware. Teams with straightforward configurations
(standard routing, rate limiting, and basic auth) can often finish in under a
week.

### Do I need to change my backend services?

No. Zuplo proxies requests to your existing backends using the
[URL Rewrite handler](https://zuplo.com/docs/handlers/url-rewrite). Your backend
services do not need any changes — Zuplo forwards requests the same way Traefik
does.

### Does Zuplo require Kubernetes or Docker?

No. Zuplo is fully managed and deploys to 300+ edge locations globally without
any container orchestration. You configure Zuplo to proxy requests to your
existing Docker or Kubernetes backends.

### Can I run Zuplo alongside Traefik during migration?

Yes. The recommended approach is to run both in parallel during the cutover
phase, using DNS or a load balancer to gradually shift external API traffic from
Traefik to Zuplo while keeping Traefik for internal routing.

## Next Steps

**Ready to migrate?**
[Sign up for a free Zuplo account](https://portal.zuplo.com) and follow the
[Getting Started Guide](https://zuplo.com/docs/articles/step-1-setup-basic-gateway)
to set up your first gateway in minutes.

For planning your migration:

- [Compare Zuplo and Traefik](https://zuplo.com/api-gateways/traefik-alternative-zuplo)
  — See a detailed feature-by-feature comparison.
- [What is an API Gateway?](https://zuplo.com/learning-center/what-is-an-api-gateway)
  — Understand the difference between reverse proxies and API gateways.
- [Managed vs Self-Hosted API Gateway](https://zuplo.com/learning-center/managed-vs-self-hosted-api-gateway)
  — Learn about the benefits of moving from self-hosted to managed.
- [Policy Catalog](https://zuplo.com/docs/policies/overview) — Browse all
  available built-in policies.
- [Custom Policies Documentation](https://zuplo.com/docs/policies/custom-code-inbound)
  — Learn how to write your own TypeScript policies.