Migrate from Ingress NGINX to Apache APISIX

A planned move from retired Ingress NGINX to the APISIX Ingress Controller, covering annotation mapping, parallel running and rollback. Effort depends on how much of your ingress behavior lives in annotations.

On this page

Why teams move off Ingress NGINX to Apache APISIX

If your cluster still runs Ingress NGINX, it probably works today, but it no longer receives releases, bug fixes or security updates. Kubernetes SIG Network set best-effort maintenance to end in March 2026, and existing deployments keep running without further support. The move to the APISIX Ingress Controller is a mapping and cutover exercise, and its size depends mainly on how many Ingress annotations and custom configuration snippets your manifests carry. Plain Ingress rules translate cleanly, while annotation-heavy setups need a deliberate decision for each one.

The APISIX Ingress Controller is a separate project from Apache APISIX itself. It runs in your cluster and translates three kinds of input into APISIX configuration: Kubernetes Ingress v1 resources, Gateway API resources, and APISIX custom resources. Confirm the Ingress v1 requirement early. Version 2.0 of the controller supports only networking.k8s.io/v1 Ingress and not v1beta1, so any older manifests must be converted before you upgrade. Check the controller version you plan to run against your APISIX version as well, since the APISIX Ingress Controller overview lists which APISIX releases each controller line supports.

Before you commit, ask your team to list every Ingress object, its annotations and any snippet-based customizations, then tag each one as a direct route, a plugin equivalent or a gap that needs a custom plugin or a policy decision. That inventory gives you a defensible scope to put in front of a partner or to estimate internally. Expect the gap list to drive the schedule, not the route count.

Which Ingress NGINX features map cleanly to APISIX

This table compares common Ingress NGINX features with their APISIX Ingress Controller or APISIX plugin equivalents, and flags items that need redesign. Read each row as a starting point: confirm every annotation against the controller documentation for your target release before committing to a mapping.

Ingress NGINX featureAPISIX equivalentMigration effort
Ingress v1 rules and path typesSupported by the APISIX Ingress Controller, which reads networking.k8s.io/v1 Ingress resourcesLow. Confirm path matching behavior for each path type in use
TLS secrets referenced by IngressSupported through Ingress TLS configuration; certificates are loaded into APISIXLow. Verify certificate chains and secret namespaces after cutover
Ingress class selectionController selects resources by its configured ingress class; both controllers must not claim the same hostLow. Plan class names so two controllers can run side by side
Gateway API HTTPRoute resourcesSupported by the APISIX Ingress Controller alongside Ingress v1Low to medium. Confirm the Gateway API version and resource kinds in use
Rewrite, auth, rate limiting and body size annotationsTypically mapped to APISIX plugins such as proxy-rewrite, authentication plugins, limit-req or limit-count, and body size limits through CRDsMedium. Each annotation needs a documented plugin mapping and a test
Timeout and canary annotationsTimeouts map to upstream settings; canary behavior maps to traffic-split style plugins or weighted routingMedium. Confirm how weights and timeouts behave under load
Custom NGINX configuration snippetsNo direct equivalent. Behavior must be rebuilt as plugins, CRDs or upstream changesHigh. Redesign each snippet and test it separately
Lua-based behavior or annotations without a documented equivalentNo documented equivalent in most cases. Custom APISIX plugins can be written in Lua or through plugin runnersHigh. Scope as custom plugin work with its own testing

Choosing the target: Ingress v1, Gateway API or APISIX CRDs

Keeping Ingress v1 is usually the lowest-change path when your inventory shows mostly host and path rules, TLS secrets and a small set of annotations that have direct equivalents. The APISIX Ingress Controller translates Ingress v1 resources into APISIX configuration, so the existing objects can often stay in place while the controller changes underneath them. The constraint to plan around is that the 2.0 controller supports only networking.k8s.io/v1 Ingress, not v1beta1, so any legacy manifests must be converted before cutover.

  • Lowest manifest churn: Ingress v1 objects can often be reused, with changes concentrated in the annotations that do not carry over.
  • Version gate: Clusters still holding v1beta1 Ingress objects need conversion first, because the 2.0 controller will not serve them.
  • Annotation gap: Annotations that map to NGINX-specific behavior need a decision: an APISIX equivalent, a plugin configured through an APISIX resource, or retirement.
  • Limited plugin reach: Ingress v1 cannot express most APISIX plugin behavior, so features like advanced traffic policy will still need another target.
  • Long-term fit: Ingress v1 keeps the migration small, but teams that want a role-separated model may later move to Gateway API.

Before committing, confirm the controller version you plan to run and its supported APISIX version, since the overview recommends a specific APISIX release line.

Sequence for running both controllers and switching traffic

This sequence moves Ingress traffic from Ingress NGINX to the APISIX Ingress Controller in controlled stages, so each route is proven on APISIX before it carries production load and either controller can be returned to service quickly. The output is a decommissioned Ingress NGINX controller and a documented record of every cutover decision.

  1. Inventory Ingress resources and annotations

    Your platform team exports every Ingress object across all namespaces, along with its ingressClassName, TLS secrets, backends and annotations, and searches for configuration-snippet and server-snippet annotations, which carry raw NGINX directives that need manual translation. Include any custom controller ConfigMap settings, admission webhooks and certificate automation that depend on the current controller. The inventory is complete when every Ingress maps to a named owner, a hostname and a target controller, and every annotation is classified as supported, replaceable or needing a design decision.

  2. Decide target mapping for each route

    For each Ingress, decide whether it moves to Ingress v1 on APISIX, to Gateway API resources, or to APISIX custom resources for behavior that Ingress v1 cannot express cleanly. Record the plugin or policy that replaces each annotation, and flag any snippet that needs a rewrite. Confirm which Ingress API version your Kubernetes cluster serves, because APISIX Ingress Controller 2.0 supports only networking.k8s.io/v1. The step closes with a signed mapping table that architecture and application owners have reviewed.

  3. Install the APISIX Ingress Controller alongside Ingress NGINX

    Install APISIX and the APISIX Ingress Controller in a separate namespace, using a distinct IngressClass so the two controllers never claim the same Ingress. Confirm the APISIX version against the controller's compatibility notes in the overview, since the 2.x releases recommend APISIX 3.13. Leave Ingress NGINX untouched and verify that both controllers report healthy, that the new one has synced its configuration, and that its LoadBalancer or service address is reachable from the test network.

  4. Pilot on non-critical hosts

    Create the APISIX copies of a small set of low-risk Ingress objects, such as internal tools or a staging hostname, and send test traffic through the new controller. Check routing, TLS certificates, authentication, redirects, request size limits and response headers against the Ingress NGINX behavior recorded in the inventory. Log every difference and resolve it in the mapping table before continuing. The pilot is complete when every test case passes and each difference has an agreed fix.

  5. Run both controllers in parallel with traffic weighting

    Route a small share of production traffic to APISIX using DNS weighting or a load balancer with weighted pools, and keep the Ingress NGINX path as the default. Follow the upgrade guide's advice to use a blue-green deployment or canary release before full switchover, increasing the weight in steps only after each stage has held steady. Monitor error rates, latency, TLS handshake failures and upstream health for each hostname on both paths. The stage is complete when the APISIX path has carried its planned share without incidents that the mapping table does not explain.

  6. Stage the cutover host by host

    Move production hostnames to APISIX in groups, starting with those whose owners have confirmed readiness and whose traffic is least sensitive. Update DNS or load balancer targets, keep the previous record ready for immediate reversal, and confirm each group with its owner before the next group moves. Check that client certificates, mutual TLS, rate limits and audit logging behave as expected on the live path. The cutover is complete when all hostnames serve from APISIX and no traffic reaches Ingress NGINX.

  7. Define and test rollback criteria

    Before the first production cutover, agree on written rollback criteria such as sustained error rate increases, latency regressions beyond the agreed threshold, authentication failures or certificate errors, and who has authority to trigger a rollback. Rehearse the rollback by repointing one test hostname back to Ingress NGINX and confirm the change takes effect within your DNS or load balancer propagation expectations. The step closes when the rehearsal is documented and the on-call team can execute the reversal without the implementation partner.

  8. Decommission Ingress NGINX

    After a stable observation period agreed with the application owners, remove the Ingress NGINX deployment, its IngressClass, its webhook configurations and any leftover ConfigMaps and RBAC bindings. Keep the final inventory, mapping table and cutover log as evidence for change management and audit. Confirm that no Ingress objects still reference the retired class and that certificate renewal and monitoring continue to work on APISIX. Ingress NGINX has no further releases, bug fixes or security updates after its end of maintenance, so the decommission should not be deferred indefinitely.

Documented import and conversion paths

Is there a documented converter that turns Ingress NGINX annotations into APISIX config?

No. The APISIX documentation for the Ingress Controller describes how the controller reads Kubernetes Ingress v1, Gateway API resources and APISIX custom resources, but it does not assume a one-step converter from Ingress NGINX annotations. Many annotations have no direct equivalent, so each one needs a decision: map it to a plugin, move it to a custom resource, or retire it. Before you rely on any community tool, confirm with its maintainers which annotations it handles, how it treats unsupported ones, and whether it is still maintained. Test its output against your own cluster rather than trusting it blindly.

Which Ingress resources does the APISIX Ingress Controller read directly?

The controller reads Kubernetes Ingress resources in the networking.k8s.io/v1 API. According to the APISIX Ingress Controller overview, version 2.0 supports only networking.k8s.io/v1 Ingress and not the older v1beta1 form, so any manifests still on the beta API must be converted first. Plain host and path rules usually carry over with little change. Annotation-driven behavior such as rewrites, authentication, rate limits and upstream settings does not carry over automatically and needs a separate mapping step.

Can Gateway API resources be used instead of Ingress with APISIX?

Yes. The APISIX Ingress Controller translates Gateway API resources into APISIX configuration alongside Ingress v1 and its own custom resources. Gateway API is the direction Kubernetes SIG Network points to after the Ingress NGINX retirement, so it is a common target for new routing definitions. Check the Gateway API resource kinds and features your routes depend on against the controller's documentation for your chosen release, because support differs between resource types and filters.

When should we use APISIX custom resources instead of Ingress or Gateway API?

Use APISIX custom resources when you need APISIX features that Ingress v1 and Gateway API do not express cleanly, such as specific plugin configuration for authentication, limits or traffic policies. The controller translates these resources into APISIX configuration directly. The trade-off is portability: custom resources tie your routing definitions to APISIX, while Ingress and Gateway API definitions are more portable across controllers. Decide per route, and record the reason so the next team understands why a given route is written the way it is.

What is the standalone API-driven mode, and which APISIX version does it need?

The standalone API-driven mode runs APISIX without etcd and takes configuration through an API, and the Ingress Controller can drive it. According to the APISIX Ingress Controller overview, the controller supports this mode with APISIX 3.13 or later. Confirm the minimum version and the exact controller release for your environment before choosing this mode, because it changes how configuration is stored, recovered and reviewed. Teams that already run etcd-backed APISIX may prefer to keep that model during the migration.

What does the upgrade guide require before switching traffic to the new controller?

The APISIX Ingress Controller upgrade guide recommends a blue-green deployment or a canary release before full switchover. In practice this means running the new controller and your existing controller side by side, sending a limited share of traffic through the new path, and comparing behavior before you move everything. Confirm the upgrade steps for your exact starting and target versions in the guide, since the controller's major versions carry different requirements. Plan rollback to the old controller as a tested step, not an assumption.

How much of this work can our own team do, and what would a partner cover?

Your team can do the inventory, mapping and cutover if it has Kubernetes and gateway experience and enough time to test each route. A partner typically adds value by building the annotation inventory, deciding the target for each pattern, writing the mappings, setting up parallel running and rehearsing rollback. DeployOpen works on fixed-scope engagements, so the written scope should name the clusters, namespaces, annotation sets and routes covered. Effort depends mainly on the number of distinct annotation patterns and the count of routes that need authentication or traffic policy, so ask for both figures when requesting a quote.

What usually goes wrong and how to prevent it

Most failed ingress migrations fail quietly, not loudly. The controller starts, the routes look present, and the problem only shows up under real traffic or after DNS changes. The six risks below share one root cause: Ingress NGINX behavior was often set by annotations, defaults and cluster conditions that nobody wrote down, so the new controller does not inherit them.

Annotations dropped during mapping

Ingress NGINX annotations carry much of the real behavior: rewrites, body size, auth, redirects and custom snippets. A mapping that only copies spec fields loses them without an error. Build a full annotation inventory across every namespace, mark each one as mapped to Ingress v1, Gateway API or an APISIX CRD, or retired, and have a named owner sign off the retired list before any cutover. Confirm each APISIX equivalent in the controller overview rather than assuming one exists.

Timeouts and body limits differ

Requests that succeeded under one controller can fail under another when proxy timeouts, request body limits and buffering defaults differ. Large uploads, long-polling calls and slow upstreams are the usual casualties, and they often show up as 413 or 504 responses only for a subset of clients. Export the effective values from the running Ingress NGINX configuration, set them explicitly on the APISIX side for every route, and test with the largest request and the slowest upstream you serve.

Path matching behaves differently

A path rule that matches one prefix in Ingress NGINX may match a wider or narrower set under another controller, depending on path type, trailing slashes and regular expression support. The same request can then reach a different backend after cutover. Compare path types for every host, write test requests for the edge cases you care about (trailing slash, encoded characters, overlapping prefixes), and replay them against both controllers before switching traffic.

TLS secrets mishandled at cutover

Certificates often live in Kubernetes Secrets referenced by Ingress TLS blocks. If the new controller expects a different secret reference, namespace or format, HTTPS fails for that host only. Secrets also remain unencrypted in etcd unless encryption at rest is configured, so copying them between namespaces widens exposure. Inventory every TLS host, confirm the APISIX side loads the same certificate chain, restrict who can read those Secrets, and check expiry dates before the switch.

DNS caching hides the switch

Once traffic moves to the new load balancer address, clients and resolvers may keep the old address until their cached records expire. Some services then appear to succeed on one path and fail on another, which makes the test results hard to trust. Lower the record TTL well before the change, keep both controllers serving during the overlap, and verify from several networks which backend answers. Record the old address so rollback is a DNS change, not a rebuild.

Cluster policies block the new controller

Network policies, Pod Security Standards and admission rules written for Ingress NGINX can prevent the APISIX Ingress Controller and its gateway pods from starting, reaching etcd or the Kubernetes API, or running with the privileges they need. The failure appears as pods stuck in creation rather than a routing error. Review the policies that select the ingress namespace, check the Pod Security level enforced there, and deploy the new controller in a staging namespace with the same policies before production.

Questions buyers ask before moving off Ingress NGINX

How much does moving off Ingress NGINX cost?

The cost depends on how many Ingress resources, annotations and custom snippets you run, how many clusters and environments sit behind them, and how much of the existing behavior must be reproduced exactly. Most of the spend is one-time: inventory, mapping annotations to Ingress v1, Gateway API or APISIX resources, testing, parallel running and the cutover itself. Recurring cost is the platform team's time to operate two controllers during the overlap and then one controller afterward. Ask any partner for a fixed-scope quote that lists the clusters, the number of routes and annotation patterns in scope, the test environments, and whether validation and cutover support are included. DeployOpen does not publish prices, so the written scope is what sets the quote.

How long does an Ingress NGINX to APISIX migration take?

Duration is set mainly by the inventory. A cluster with a small set of plain Ingress objects moves much faster than one with heavy annotation use, server snippets, custom Lua or authentication tied to Ingress NGINX features. Other drivers include the number of clusters, how many teams own routes, change freeze windows, and how much traffic validation your organization requires before switching. The overlap period, when both controllers run side by side, usually lasts as long as your validation plan needs. Ask for a timeline built from the inventory results, not from a generic estimate.

What does our internal team need to provide?

Your team needs to supply access and decisions that only you can make. This includes read access to the clusters and Git repositories holding Ingress manifests, a list of owners for each service, the authentication and TLS arrangements in use, and the change window rules. You also need someone who can approve which Ingress NGINX behaviors are required and which can be dropped, and a staging environment that resembles production. Confirm with the partner how cluster credentials, certificates and secrets will be handled, since Kubernetes Secrets are stored unencrypted in etcd by default unless encryption at rest is configured.

Can our own platform team do this migration in house?

Yes, many platform teams can do it in house if they have Kubernetes experience, time to test each annotation mapping, and a clear rollback plan. The work is mostly methodical: inventory, mapping, deploying the APISIX Ingress Controller alongside the existing controller, comparing behavior, and shifting traffic gradually. The harder parts are annotations with no direct equivalent, gateway-level policies that need redesign, and sustained validation under production load. Teams that lack capacity for the overlap period often bring in a partner for the inventory and mapping, then keep the cutover in house. Decide this by comparing your team's available hours and Kubernetes skills against the inventory size.

Does Ingress NGINX still work after its retirement?

Existing Ingress NGINX deployments keep working after retirement, but they stop receiving releases, bug fixes and security updates. The Kubernetes project announced that best-effort maintenance would run until March 2026, after which there would be no further releases. That makes the risk operational and security related rather than an immediate outage. Unpatched edge components on public traffic paths are a compliance concern for many frameworks, so you should record the decision, the owner and the target date for moving off the controller. Confirm which Ingress NGINX version each cluster runs and whether your vulnerability management process still tracks it.

Must APISIX replace our whole gateway estate at once?

No. The usual approach is to move Ingress NGINX workloads cluster by cluster or service by service, while other gateways and ingress paths keep running. The APISIX Ingress Controller supports Ingress v1, Gateway API and APISIX custom resources, so you can choose the representation that fits each route. Plan for a period where DNS, load balancers or upstream routing directs specific hostnames to the new controller. Keep the scope of each wave written down so that a problem in one service does not stall the rest of the estate.

Which APISIX Ingress Controller version should we target?

Target a release that matches your APISIX version and your Kubernetes version, and confirm the support matrix before you choose. The APISIX Ingress Controller project documents support for APISIX 3.0 and later with 2.0.0 and 2.1.0, recommends APISIX 3.13, and supports standalone API-driven mode from APISIX 3.13. Version 2.0 supports only networking.k8s.io/v1 Ingress, not v1beta1, so clusters with older manifests need conversion first. Its upgrade guide recommends a blue-green deployment or canary release before full switchover. Ask your partner to check the current release notes, since the supported combinations change over time.

Primary sources for the migration

The sources below cover the three questions that shape this migration: why Ingress NGINX has to move, how the APISIX Ingress Controller translates your resources, and how far the Kubernetes control plane can be upgraded around the cutover. Read them in that order before the inventory starts, and keep the upgrade guide open during the parallel-run phase.

Ingress NGINX retirement notice

The Kubernetes project announced the retirement of Ingress NGINX, with best-effort maintenance until March 2026 and no further releases, bug fixes or security updates after that. Existing deployments keep running, but the risk moves from function to security exposure over time. Use the notice to set the deadline your change board will hold you to, and confirm which Ingress NGINX version and annotation set your clusters actually run.

APISIX Ingress Controller overview

This page explains which inputs the controller translates: Kubernetes Ingress v1, Gateway API resources and APISIX custom resources. It also states the APISIX versions each controller release supports and the standalone API-driven mode. Use it to decide which of the three target formats fits each Ingress group, and to confirm that your planned APISIX version is in the supported range before you pin versions.

APISIX Ingress Controller upgrade guide

The upgrade guide covers the version-specific changes that affect a migration, including the Ingress API version the controller accepts. It recommends a blue-green deployment or canary release before full switchover, which is the basis for the parallel-run design. Read the section for your target controller version and list each breaking change against your inventory before the first test cluster is built.

Kubernetes version skew policy

The skew policy sets the order of control plane and node upgrades and how far kubelets may lag behind kube-apiserver. A controller change and a cluster upgrade should not be stacked in one change window, so this page determines which of the two happens first. Check your current minor version against the supported list, then plan the sequence so both controllers are validated on a version your clusters will still run after cutover.

Kubernetes release lifecycle

The release page lists the three most recent minor versions that receive patches and their end-of-life dates. An ingress migration that finishes on a minor version already out of support creates a second upgrade in the same quarter. Record the end-of-life date of your cluster version in the migration plan, and ask your platform team whether a cluster upgrade is already scheduled in the same window.

How DeployOpen scopes and delivers the migration

DeployOpen plans, builds, documents and hands over the move from Ingress NGINX to the APISIX Ingress Controller inside your own clusters and cloud accounts. Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

How we scope

  • Inventory every Ingress resource, annotation and ConfigMap setting that the current controller reads across all clusters
  • Map each behavior to Ingress v1, Gateway API or APISIX custom resources, and record which annotations have no direct equivalent
  • Agree the written scope, deliverables and timeline with you before any cluster change is made

How we build

  • Deploy the APISIX Ingress Controller alongside the existing controller in a non-production cluster first
  • Translate routes, TLS secrets, authentication and rate limits into APISIX configuration kept in version control
  • Test each migrated route with replayed or representative traffic and compare responses against the current controller

How we hand over

  • Deliver the annotation mapping, route inventory and cutover runbook as documents your team can audit and reuse
  • Document the parallel-running period, the traffic switch steps and the rollback procedure for each ingress class
  • Walk your platform and security engineers through the configuration and operating model before the engagement closes

How we support

  • Offer ongoing support, upgrades and continuous testing of the gateway as a retainer after handover
  • Plan controller version upgrades with a blue-green or canary approach, as the APISIX upgrade guidance recommends
  • Agree in the written scope how post-cutover issues, decommissioning of the old controller and follow-up changes are handled

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.