Self-hosted API gateways like NGINX, Traefik, and Envoy are popular starting points. They're free, flexible, and give you full control. But as your API program grows, so does the operational burden of keeping them running — patching security vulnerabilities, managing configuration drift across environments, scaling infrastructure for traffic spikes, and cobbling together observability from a handful of open-source tools.
If you're starting to feel that pain, you're not alone. Many teams reach a point where the self-hosted gateway becomes the bottleneck, not the enabler. This guide walks you through every step of migrating from a self-hosted API gateway to a managed platform — from recognizing the signs, to mapping your existing configuration, to cutting over with zero downtime.
When It's Time to Migrate
Not every team needs to migrate immediately. But there are clear signals that your self-hosted gateway is holding you back:
- The ops burden is growing faster than your API. You're spending more time upgrading NGINX modules, rotating TLS certificates, or debugging Traefik middleware chains than building API features.
- Scaling is manual and reactive. Traffic spikes mean scrambling to add instances, tune connection pools, or restart pods. You've been burned by outages that a managed platform would have absorbed automatically.
- Security patching is a full-time job. Every CVE in NGINX, OpenSSL, or your Lua/Go plugin dependencies triggers an emergency update cycle. You can't move fast when you're constantly firefighting.
- Observability is stitched together. Your monitoring is a patchwork of Prometheus exporters, custom dashboards, and log aggregation pipelines that nobody fully understands.
- Configuration drift is real. Your staging and production gateway configs have diverged in ways nobody can fully explain. Deployments are nerve-wracking because you're never 100% sure the config is correct.
- You can't deploy globally. Your gateway runs in one or two regions. Users in other geographies experience high latency, and deploying additional instances means duplicating your entire infrastructure stack.
If more than two of these resonate, it's time to seriously evaluate a managed alternative.
What You Gain with a Managed Gateway
A managed API gateway eliminates the undifferentiated heavy lifting of infrastructure management while giving you capabilities that would take months to build in-house:
- Automatic scaling. Traffic spikes are handled without intervention. No capacity planning, no pod autoscaler tuning, no database connection pool limits.
- Built-in security. DDoS protection, automatic TLS, and regularly updated security policies — maintained by a dedicated security team, not yours.
- Zero-downtime deployments. Push a config change and it rolls out globally without dropping a single request.
- Global distribution. Your API runs at the edge, close to your users, with automatic failover across regions.
- Developer portal. Auto-generated API documentation, interactive API explorer, and self-serve API key management — no separate tooling to build and maintain.
- GitOps workflows. Routes and policies defined in code, version controlled, and deployed via CI/CD — giving you the same developer-centric workflow you value from managing config files in Git.
For a deeper look at why hosted gateways outperform self-managed solutions across cost, security, and customization, see Why a Hosted API Gateway Is Better Than Building Your Own.
Migration Planning Checklist
Before you touch any configuration, you need a complete inventory of what your current gateway does. Missed items become production incidents after migration.
Routes and Upstream Services
- List every route (path + method) and its upstream backend
- Document path rewriting rules and regex-based routing
- Identify wildcard or catch-all routes
- Note any WebSocket, gRPC, or Server-Sent Events endpoints
Security Policies
- Authentication methods (API keys, JWT, OAuth 2.0, mTLS, basic auth)
- Authorization rules (RBAC, IP allowlists, header-based access control)
- TLS/SSL certificate configuration and renewal process
- CORS policies per route or globally
Traffic Management
- Rate limiting rules (per IP, per user, per API key, global)
- Request/response size limits
- Timeout configurations
- Circuit breaker or retry policies
Request/Response Transformations
- Header injection or removal
- Request body transformations
- Response body transformations (XML to JSON, field filtering)
- URL rewriting
Custom Logic
- Custom Lua scripts (NGINX/Kong)
- Go middleware (Traefik)
- C++ or Wasm filters (Envoy)
- Any business logic embedded in the gateway layer
Observability and Monitoring
- Logging format and destinations
- Metrics and alerting rules
- Distributed tracing configuration
- Health check endpoints
Mapping Self-Hosted Concepts to a Managed Gateway
The biggest conceptual shift in migration is understanding how your existing gateway primitives translate to a managed platform's model. Here's how the core concepts map when migrating to Zuplo:
NGINX → Zuplo
| Concept | NGINX | Zuplo Equivalent |
|---|---|---|
| Route definition | location blocks in nginx.conf | Routes in routes.oas.json (OpenAPI format) |
| Upstream/backend | upstream + proxy_pass | urlForwardHandler with baseUrl |
| Rate limiting | limit_req_zone + limit_req | rate-limit-inbound policy |
| Authentication | auth_request + Lua scripts | api-key-inbound, open-id-jwt-auth-inbound, or custom policy |
| Request transformation | proxy_set_header, Lua | Inbound policies (TypeScript) |
| Response transformation | sub_filter, Lua | Outbound policies (TypeScript) |
| TLS termination | ssl_certificate directives | Automatic (managed) |
| Custom business logic | Lua scripts via ngx_lua | TypeScript policy modules |
| Config management | Files on disk, often in Git | Git-native (routes.oas.json + policies.json) |
| Documentation | Separate tooling (Swagger UI, etc.) | Built-in developer portal (auto-generated from OpenAPI) |
Traefik → Zuplo
| Concept | Traefik | Zuplo Equivalent |
|---|---|---|
| Route definition | IngressRoute CRDs or file provider | Routes in routes.oas.json (OpenAPI format) |
| Upstream/backend | Service definitions | urlForwardHandler with baseUrl |
| Rate limiting | RateLimit middleware | rate-limit-inbound policy |
| Authentication | ForwardAuth middleware or OIDC | api-key-inbound, open-id-jwt-auth-inbound, or custom policy |
| Request transformation | Headers middleware | Inbound policies (TypeScript) |
| Response transformation | Plugin middleware | Outbound policies (TypeScript) |
| TLS termination | TLSStore / Let's Encrypt | Automatic (managed) |
| Custom business logic | Go middleware plugins | TypeScript policy modules |
| Config management | YAML files or K8s CRDs | Git-native (routes.oas.json + policies.json) |
| Documentation | Separate tooling | Built-in developer portal (auto-generated from OpenAPI) |
Envoy → Zuplo
| Concept | Envoy | Zuplo Equivalent |
|---|---|---|
| Route definition | route_config in YAML | Routes in routes.oas.json (OpenAPI format) |
| Upstream/backend | clusters | urlForwardHandler with baseUrl |
| Rate limiting | envoy.filters.http.ratelimit | rate-limit-inbound policy |
| Authentication | ext_authz filter | api-key-inbound, open-id-jwt-auth-inbound, or custom policy |
| Request transformation | Lua or Wasm filters | Inbound policies (TypeScript) |
| Response transformation | Lua or Wasm filters | Outbound policies (TypeScript) |
| TLS termination | transport_socket | Automatic (managed) |
| Custom business logic | C++/Wasm/Lua filters | TypeScript policy modules |
| Config management | YAML + xDS API | Git-native (routes.oas.json + policies.json) |
| Documentation | Separate tooling | Built-in developer portal (auto-generated from OpenAPI) |
For a broader comparison of API gateway hosting models and how different gateways compare, check out those dedicated guides.
Step-by-Step Migration from NGINX
NGINX is one of the most common self-hosted API gateways. Here's how a typical NGINX API gateway configuration translates to Zuplo.
NGINX Configuration (Before)
Zuplo Configuration (After)
In Zuplo, this configuration is split into two files: routes defined in OpenAPI format, and policies defined declaratively.
config/routes.oas.json — your routes:
config/policies.json — your policies:
Notice what disappeared entirely: TLS certificate management, upstream health checks, load balancer configuration, and the auth subrequest plumbing. Zuplo handles all of that automatically.
Step-by-Step Migration from Traefik
Traefik's middleware model maps cleanly to Zuplo's policy pipeline. Here's how a typical Traefik configuration translates.
Traefik Configuration (Before)
How the Traefik Config Maps to Zuplo
The same routes.oas.json and policies.json pattern from the NGINX example
applies. Here's the equivalent Zuplo route for the Traefik api-users router
above:
The key differences to note:
- TLS and certificate resolution — eliminated entirely. Zuplo manages TLS automatically.
- Load balancing — handled by Zuplo's edge infrastructure. No server lists to maintain.
- Middleware chaining — maps directly to Zuplo's inbound policy array. The execution order is the same: policies run in the order you list them.
- ForwardAuth — replaced by built-in auth policies (
api-key-inbound,open-id-jwt-auth-inbound) or a custom TypeScript policy for proprietary auth schemes.
If you have complex Traefik middleware chains, map each middleware to its Zuplo
policy equivalent and list them in the inbound array in the same order.
Handling Custom Logic
This is where many migrations stall. If you've written custom plugins in Lua (NGINX/Kong), Go (Traefik), or C++/Wasm (Envoy), you need to rewrite them. The good news: TypeScript is a significant upgrade in readability and maintainability.
Example: Custom Lua Script in NGINX
Equivalent TypeScript Policy in Zuplo
In Zuplo, you implement this as a custom rate limit identifier function — a
TypeScript module that the built-in rate-limit-inbound policy calls to
determine per-request limits:
Wire it up in config/policies.json using the rateLimitBy: "function" option:
The TypeScript version is shorter, type-safe, and doesn't require managing a Redis connection — Zuplo's rate limiting infrastructure handles the distributed counting. No more debugging Lua coroutines or managing C++ build toolchains.
Migration Tips for Custom Logic
- Start with built-in policies. Zuplo has dozens of built-in policies covering authentication, rate limiting, request validation, caching, and more. Check if your custom logic already has a built-in equivalent before rewriting.
- Use TypeScript modules. Custom policies are standard TypeScript files in
your project's
modules/directory. They have full access to theRequest,Response, andZuploContextobjects. - Leverage the policy pipeline. Instead of one monolithic plugin that does everything, break your logic into composable inbound and outbound policies.
Zero-Downtime Migration Strategies
The biggest risk in any gateway migration is dropping production traffic. Here are three strategies for cutting over safely.
Strategy 1: DNS-Based Blue-Green
The simplest approach. Run your new managed gateway in parallel with your existing self-hosted gateway, then switch DNS.
- Set up Zuplo with all your routes, policies, and custom logic.
- Test thoroughly using the preview environment (every PR gets its own isolated environment in Zuplo).
- Lower DNS TTL on your API domain to 60 seconds, 24 hours before cutover.
- Switch DNS to point at your Zuplo gateway.
- Monitor for errors and latency changes.
- Roll back by reverting DNS if anything goes wrong.
Best for: Teams with simple routing who want the lowest-risk approach.
Strategy 2: Canary Routing with Percentage-Based Rollout
Route a small percentage of traffic to the new gateway and gradually increase it.
With Zuplo, you can implement percentage-based canary routing using a custom inbound policy that hashes a stable client identifier and routes based on a configurable percentage:
Start at 5%, monitor, increase to 25%, then 50%, then 100%. This approach gives you fine-grained control and sticky routing per client. For more on this pattern, see What Is Canary Routing?.
Best for: High-traffic APIs where you need to validate performance under real load before full cutover.
Strategy 3: Shadow Traffic Testing
Forward a copy of production traffic to the new gateway without affecting the response path.
- Configure your existing gateway to mirror requests to Zuplo.
- Compare responses, latency, and error rates between old and new.
- Fix any discrepancies.
- Once parity is confirmed, cut over using DNS or canary routing.
Best for: Mission-critical APIs where you need absolute confidence before any traffic switch.
Post-Migration Validation
After cutover, run through this validation checklist:
Functional Validation
- Every route returns the expected response codes
- Authentication works for all methods (API key, JWT, OAuth)
- Rate limiting triggers at the correct thresholds
- Request and response transformations produce identical output
- Error responses match the expected format
- CORS headers are correct for all origins
Performance Validation
- P50, P95, and P99 latency is equal to or better than the old gateway
- Throughput handles peak traffic without degradation
- No increased error rates under load
Observability Validation
- Logs are flowing to your log aggregation system
- Metrics are visible in your monitoring dashboards
- Alerts trigger correctly for error rate and latency thresholds
Security Validation
- TLS is terminating correctly (verify certificate chain)
- Unauthorized requests are rejected
- Rate limiting blocks excessive traffic
- No unintended routes are exposed
Common Migration Pitfalls and How to Avoid Them
1. Incomplete Route Inventory
The mistake: You migrate the routes you know about and miss the ones buried in ancient NGINX config includes or Kubernetes annotations.
The fix: Use automated tooling to extract routes. For NGINX, parse all
included config files. For Traefik, export all IngressRoute CRDs. For Envoy,
dump the route table via the admin API. Cross-reference with access logs to
identify routes that still receive traffic.
2. Ignoring Implicit Behavior
The mistake: Self-hosted gateways have implicit behaviors — NGINX's default buffering, Traefik's automatic HTTPS redirects, Envoy's default timeouts. You don't realize you depend on them until they're gone.
The fix: Document not just what your gateway does, but what it does by default. Test edge cases: large request bodies, slow backends, WebSocket upgrades, and connection timeouts.
3. Big-Bang Cutover
The mistake: Migrating everything at once on a Friday afternoon.
The fix: Migrate route by route or service by service. Start with low-traffic, low-risk endpoints. Use canary routing to validate each batch before moving to the next.
4. Not Testing Under Real Load
The mistake: Your test suite passes, so you assume production will work.
The fix: Use shadow traffic or replay production logs against the new gateway. Synthetic tests don't catch the weird edge cases that real traffic exposes.
5. Losing Custom Headers or Transformations
The mistake: Your NGINX config adds X-Request-ID headers, your Lua script
strips sensitive headers from responses, or your Traefik middleware rewrites
paths. These subtle transformations are easy to miss.
The fix: Capture request/response pairs from your existing gateway using access logs or traffic capture. Replay them against the new gateway and diff the results.
Making the Move
Migrating from a self-hosted API gateway to a managed platform is a significant undertaking, but it pays dividends in reduced operational burden, better security, and faster development velocity. The key is to approach it methodically: inventory everything, migrate incrementally, and validate thoroughly.
Zuplo is designed specifically for teams making this transition. The GitOps workflow feels familiar if you're used to managing NGINX or Traefik configs in Git. TypeScript policies replace complex Lua or Go plugins with readable, type-safe code. And the OpenAPI-native routing means you can import your existing API specs to generate routes and a developer portal instantly.
If you're evaluating your options, check out our comparison of API gateway hosting options and the build vs. buy decision framework to see how managed gateways stack up against self-hosted solutions. When you're ready to start, sign up for free and deploy your first API to 300+ edge locations in minutes.