Upgrading Apache APISIX from the 3.2 LTS line

A 3.2 LTS gateway needs more than a package bump before it reaches a current 3.x release. This page covers the breaking changes from 3.3 to 3.6, the staged path, and what drives the effort.

On this page

Why upgrading Apache APISIX from 3.2 LTS takes planning

If your gateway runs Apache APISIX 3.2 LTS, the upgrade is not a single package swap. The 3.2.0 release came out on March 6, 2023, and 3.2.1 and 3.2.2 were LTS maintenance releases on the release/3.2 branch. Since then, the project has changed defaults and removed settings in several later minor releases, and each change can alter how routes match, how the gateway talks to etcd, or whether your current configuration loads at all. Treat the move to a current 3.x line as a sequence of version steps, each with its own checks, rather than one jump. The changelog and release notes in the apache/apisix releases page are the primary record for each step, and the CHANGELOG lists the breaking entries by version.

The changes that most often surprise teams are the default router change in 3.3.0, where the default moved from radixtree_uri to radixtree_host_uri, and the OpenResty requirement from 3.5.0, which needs OpenResty 1.21 or later. In 3.5.0, apisix.stream_proxy.only was replaced by apisix.proxy_mode, so a configuration file that worked on 3.2 may need edits before the node starts. In 3.6.0, etcd gRPC (etcd.use_grpc) was removed, the conf server was removed so data planes use config_provider etcd instead of control_plane, and strict schema validation applies to core resources. Each of these affects a different team: platform engineers own the image and OpenResty build, while API owners may see route matching change for requests that previously matched by URI alone.

Before you choose a target release, confirm its support status with the vendor. The APISIX downloads page does not mark any release as long-term support, so a current 3.x release may not carry the LTS commitment your 3.2 line had. Ask your own support contract or internal policy owner which line you must be on, and confirm the end-of-life dates for both your current and target lines. Plan the work as a series of tested stops, record the configuration and route state at each one, and keep the 3.2 nodes available for rollback until the final stop has passed your checks.

Which 3.x changes affect a 3.2 gateway

This table lists the 3.x changes that affect a gateway still running the 3.2 LTS line, grouped by the release that introduced each change. Read each row against your current configuration and custom plugins, and treat the action column as the check to run before you move to that version. The main takeaway is that the router change in 3.3 and the etcd and config changes in 3.6 are the ones most likely to alter traffic or startup behavior.

ChangeImpact on a 3.2 gatewayAction needed
Default router changed from radixtree_uri to radixtree_host_uri (3.3.0)Routes that rely on the default router may match differently when host and URI both matter, which can change which route handles a request.Confirm which router your apisix.yaml sets, then test host-specific and wildcard host routes in staging before cutover.
OpenResty 1.21 or later required (3.5.0)Hosts or container images built on an older OpenResty will not start the new release.Check the OpenResty version in your base image or package source and rebuild custom images against it.
apisix.stream_proxy.only replaced by apisix.proxy_mode (3.5.0)Existing stream proxy settings are no longer read under the old key, so TCP or UDP routes can stop being served as expected.Search your config files for stream_proxy.only and move the setting to apisix.proxy_mode, then confirm stream routes respond.
Snowflake algorithm removed from request-id (3.5.0)Clients or log pipelines that depend on snowflake-format request IDs will see a different ID format.Find request-id plugin settings that name snowflake and choose a supported algorithm, then check downstream log parsers.
etcd.use_grpc removed (3.6.0)Config that enables gRPC between APISIX and etcd no longer has an effect on the new release.Remove etcd.use_grpc from configuration and confirm your etcd endpoints and TLS settings still connect.
Conf server and control_plane removed in favor of config_provider etcd (3.6.0)Data planes that pull configuration from the control plane's conf server will fail to load configuration after the upgrade.Identify every data plane using control_plane, switch them to config_provider etcd, and confirm each one syncs routes.
Strict schema validation on core resources (3.6.0)Route, upstream, consumer or plugin objects with unknown or malformed fields may be rejected on write or fail to load.Validate exported resources against the 3.6 schema in a test instance and fix or remove rejected fields before cutover.

What changes in each step from 3.2 to 3.6

APISIX 3.3.0 changed the default router from radixtree_uri to radixtree_host_uri. Routes that do not set a router explicitly now match on the host and the URI together, so a route that only matched on path before the change can behave differently once several hostnames share the gateway. This matters most for teams that publish the same paths under different hostnames, and for any tooling that generates routes without host fields.

  • Default router: 3.3.0 switched the default from radixtree_uri to radixtree_host_uri.
  • Host sensitivity: Routes that relied on path-only matching across hosts need a review before cutover.
  • Generated routes: Routes produced by Ingress controllers, sync scripts or infrastructure templates may omit host fields, so check what they emit.
  • Overlapping paths: Identical URIs on different hosts, or wildcard hosts, are the cases most likely to change which route wins.

Before moving on, inventory every route that lacks an explicit host and every path shared across virtual hosts, then confirm the exact matching rules and the router settings in the 3.3.0 entry of the changelog.

What to prepare before the first version step

Before you change a version number, four artifacts need to exist: a restorable copy of your configuration data, a list of custom code that depends on core behavior, a list of routes that the 3.5 proxy mode change can touch, and a test environment that behaves like production. Each one protects against a different failure, and each has a clear owner on your side.

Restorable etcd and configuration backup

Take a snapshot of the etcd data that holds your routes, upstreams, consumers and plugin metadata, and keep the APISIX configuration files with it. Test the restore on a separate etcd cluster before you rely on it, because a backup you have never restored is only a hope. The platform team owns this step, and the change window should not open until the restore has been verified.

Inventory of custom plugins

List every custom Lua plugin and every plugin runner plugin in Java, Go, Python or WebAssembly, then mark which ones call core functions, read request headers, or depend on the default router. Each version step can change that behavior, so the owning development team should test these plugins against the target release first. Plugins nobody has touched in a long time are the most likely to break silently.

Routes affected by proxy mode

The 3.5.0 release replaced apisix.stream_proxy.only with apisix.proxy_mode. Find every stream proxy and every configuration file that still sets the old key, and record which services depend on TCP or UDP traffic. The application owners of those services must confirm the expected behavior, since a misread setting can stop stream traffic without an obvious error.

Route matching and default router review

The 3.3.0 release changed the default router from radixtree_uri to radixtree_host_uri. List routes that rely on matching by path alone, and routes that depend on host headers for matching. The API owners should decide which routes must set the router explicitly, so that matching does not change between environments during the upgrade.

Test environment with production-like identity

Build a staging gateway that receives representative traffic, uses the same plugin set and talks to test copies of your identity providers, such as Keycloak or your enterprise directory. Authentication behavior is where upgrades most often fail, so the security team should test token validation and session flows, not only routing. The test environment should be ready before the first version step, not after it.

How to step through the upgrade with rollback points

This sequence moves a 3.2 LTS gateway to a current 3.x release while keeping a known-good state available at every stage, so each change can be checked and reversed before it reaches production traffic.

  1. Freeze configuration changes during the upgrade

    Agree a change freeze with the teams that publish routes, plugins and consumers to the gateway, and record the current state of the cluster as the baseline. Export the routes, upstreams, consumers, plugin configurations and plugin metadata through the Admin API, and store them in version control with a timestamp. The step is done when the change freeze is announced and the exported baseline can be read back and compared with the live cluster. Confirm who owns each route before the freeze starts, because unowned routes are the ones most likely to change without anyone noticing.

  2. Back up etcd and configuration files

    Take a snapshot of the etcd cluster that holds APISIX state, and copy the APISIX configuration files, including conf/config.yaml and any custom plugin code, to storage outside the gateway nodes. Record the APISIX version, the OpenResty version and the etcd version alongside each backup. The step is done when you have restored the snapshot into a scratch etcd instance and confirmed that the key count and a sample of routes match the baseline. Without a tested restore, the backup is only an assumption.

  3. Upgrade a test environment one minor step at a time

    Build a test environment from the backup, then upgrade it through each minor release that the release notes require, starting from 3.2 and checking the order against the upgrade guidance on GitHub before running any command. Keep each intermediate version in the test environment, not only the final one, so that any breaking change is isolated to the step that introduced it. The step is done when the test environment runs the target version and every intermediate version has been recorded as a restore point. Changes such as the default router change in 3.3 and the OpenResty requirement in 3.5 are easier to diagnose when each one is applied alone.

  4. Run schema and route checks after each step

    After each version in the test environment, run the Admin API schema validation against the exported routes and plugin configurations, then send a fixed set of representative requests through the gateway and compare status codes, response headers and upstream selection with the baseline. Include requests that use host-based and URI-based matching, authenticated routes, and any custom plugin. The step is done when every route passes both checks, or when each failure has a written owner and a fix. A failed check is the rollback point for that version: return to the previous restore point, correct the configuration, and repeat the step.

  5. Move a canary data plane onto the new version

    Start one data plane on the target version, connected to the same configuration source as the production nodes, and route a small share of real traffic to it through your load balancer. Watch error rates, latency, authentication failures and log volume for the canary against the production nodes, and keep the production nodes on the 3.2 line during this phase. The step is done when the canary has handled production traffic through an agreed observation window and its metrics match the baseline. Rollback here means removing the canary from the load balancer, which leaves production untouched.

  6. Cut over with a documented rollback point

    Upgrade the remaining data planes in small groups, keeping the previous 3.2 nodes available and registered with the load balancer until the cutover is confirmed. Record the time, the version and the configuration snapshot taken immediately before the switch. The step is done when all data planes report the target version, traffic flows through them, and the baseline checks pass against production. To roll back, return traffic to the 3.2 nodes and restore the recorded configuration snapshot, which requires that you tested this path in the test environment before the cutover.

  7. Retire the old nodes after a confirmed period

    Keep the 3.2 nodes in a stopped but recoverable state until the agreed post-cutover period has passed without a rollback decision. Then remove them from the infrastructure, update runbooks, monitoring and dashboards to the new version, and close the change freeze. The step is done when the old nodes are removed, the final configuration backup is stored, and the upgrade record lists each version, check result and rollback point. Confirm the exact upgrade commands and version order against the release notes on GitHub before running any of these steps.

How to test each step and roll back safely

Testing for this upgrade should prove that every route still matches the request it served before, because the default router changed from radixtree_uri to radixtree_host_uri in 3.3. Build a replay set from production access logs covering the same hosts, paths and methods, and compare the upstream each request reaches on the 3.2 gateway and the candidate 3.x gateway. Routes that depend on matching by URI alone, without a host, are the first place a silent mismatch appears. Run the same comparison for apisix.proxy_mode on any stream routes, since 3.5 replaced apisix.stream_proxy.only. Confirm the OpenResty version on your build image meets the 1.21 requirement before any of this testing starts.

Authentication tests should cover each consumer type you run, not a sample login. For openid-connect, test the full authorization code flow against your identity provider, token introspection where you use it, and session expiry and renewal, because those paths carry the most configuration. For key-auth, test valid, revoked and malformed keys against the consumers you actually hold. Then send Admin API payloads from your automation through the candidate's Admin API. The 3.6 release enforced strict schema validation on core resources, so a payload with an unknown or misspelled field that 3.2 quietly accepted will now fail. Treat those failures as findings to fix in your pipeline, not as noise to suppress. Custom plugins need their own test cases, including any that read request headers or use the Lua APIs you depend on, and their logs and metrics should be checked alongside the responses. For rollback, the cheapest option is keeping the 3.2 data plane running in parallel and shifting traffic back at the load balancer or DNS layer. This works only while the two gateways read compatible configuration. Before each step, take an etcd snapshot and record which step produced it. The 3.6 change that removed gRPC between APISIX and etcd and the removal of the conf server both affect how data planes connect, so confirm with the project's release notes and your own test cluster how a restored snapshot behaves on the older version. Confirm also that observability output such as log formats and metric names still feeds your dashboards and alerts before you retire the old data plane. Note that a snapshot restores only what was in etcd at that moment: any route or consumer changed after it, and any configuration written in a format the older release cannot read, will not return cleanly on rollback. Plan those writes as one-way once the cutover is complete.

Questions teams ask before upgrading APISIX from 3.2

How much effort does upgrading APISIX from 3.2 take?

The effort depends mostly on how much of your gateway configuration touches the behavior that changed between 3.2 and your target release. A gateway with a small set of routes that use only core features usually needs much less work than one with many custom plugins, several authentication methods, and automation that calls the Admin API. The main drivers are the number of routes and consumers, the plugins in use, whether you rely on the default router, whether you run a custom Lua plugin or plugin runner, and how much monitoring and alerting depends on metric names or log formats. Ask for a written inventory of these items before any quote is agreed.

How long does an APISIX 3.2 upgrade take?

Duration is set by the number of upgrade steps, the size of the test effort and the change window your organization can use. Each intermediate minor release that introduces breaking changes adds a validation cycle, so the path you choose matters as much as the gateway size. Other factors include how long your staging environment takes to match production, how many environments must be upgraded, whether a parallel cluster is used for cutover, and approval steps for production changes. Confirm the target version, the number of environments and the cutover method in writing, then agree a timeline against those inputs.

What does our internal team need to provide for the upgrade?

Your team needs to provide access to the gateway configuration, the etcd or configuration source in use, the staging and production environments, and the owners of each upstream service and identity provider. Someone must be able to approve test results and change windows, and someone must own the monitoring dashboards and alert rules that depend on APISIX metrics. If you use the Admin API in scripts or pipelines, the owners of those scripts must review them against the new release. Plan for these people to be available during testing and cutover, not only at kickoff.

Can an in-house team upgrade APISIX from 3.2 without a partner?

Yes, a team that already runs APISIX in production and has a tested staging environment can carry out the upgrade alone. The work is manageable when the gateway is small, the plugins are standard, and the team has time to read each release changelog and test every affected route. The risk rises when the team has not operated APISIX before, when custom plugins must be reviewed against changed core interfaces, or when the release calendar is tight. Compare the internal hours needed for reading changelogs, building test cases and running rollback drills against the people available, and decide which parts you want to hand over.

What does a fixed-scope quote for this upgrade include?

A fixed-scope quote follows from a written scope that names the source and target versions, the environments in scope, the gateway components covered (routes, plugins, authentication, etcd or configuration source, Kubernetes ingress if used), and the deliverables. It should list the test cases, the rollback procedure, the cutover plan, the handover documentation and any work excluded from the scope. Ask the provider to state which items are one-time and which recur, and what changes require a new quote. DeployOpen does not publish a price list, so the quote comes from the agreed scope.

Does the upgrade from 3.2 skip the 3.x releases in between?

You can move to a later 3.x release directly only after reviewing every breaking change between 3.2 and that target, because the changes in intermediate releases still apply to your configuration. Several releases in the 3.x line changed defaults, removed options or enforced stricter validation, and skipping them means those changes arrive in one step. A stepwise path lets you test each set of changes separately and locate the cause of any failure. Confirm the path against the APISIX changelog and the upgrade notes for each release, and decide with your provider whether to test one step at a time or to validate the target directly.

How do our custom plugins affect the upgrade?

Custom plugins are often the largest source of upgrade effort because they depend on internal APIs, request handling and the plugin lifecycle, which can change between releases. A plugin written in Lua may call functions whose behavior or defaults changed, and a plugin runner in Java, Go or Python depends on the runner version and its protocol. Some changes in the 3.x line affect how request headers and body data reach plugins. Inventory each custom plugin, record the APISIX functions it calls, check its tests against the target release, and confirm with the plugin author who will own fixes after the upgrade.

What makes this upgrade longer or shorter

This table lists the factors that most change the effort of leaving the 3.2 LTS line, with the direction each one moves the work and what to inventory before estimating. Read it as a checklist: the rows that apply to your gateway set the scope, and the inventory column tells your team what to collect before asking a partner for a quote.

DriverEffect on effortWhat to inventory
Custom plugins and languageMore custom Lua plugins or plugin runner code (Java, Go, Python) lengthens testing against each intermediate releaseEach plugin, its language, the core APIs it calls, and whether it reads request headers or body buffers
Routes and stream proxiesMore routes and stream routes increase regression testing, especially where routing changes from 3.3 applyRoute count, host-based versus URI-only matching, and any stream proxy configuration using apisix.stream_proxy.only
etcd gRPC or conf server useUsing etcd.use_grpc or the conf server adds configuration changes and a cutover step when 3.6 is reachedWhether etcd.use_grpc is set, which data planes read from a control_plane, and the config_provider settings in use
Data plane topologyTraditional mode is the simplest path, decoupled mode needs control and data plane upgraded in order, standalone mode needs its YAML or JSON file checked against new schemasDeployment mode per cluster, the number of data plane nodes, and the file or etcd source each node reads
Identity integrationsEach openid-connect, jwt-auth or LDAP integration needs its own test and may pick up stricter validationIdentity providers in use, flows enabled, token introspection calls, and the TLS settings to upstream identity endpoints
Environments kept in stepEach extra environment (dev, test, staging, production) repeats the upgrade and test cycle and adds coordinationNumber of environments, their versions, who approves each promotion, and the rollback window each team requires
Schema and Admin API automationScripts that write partial resources or depend on defaults need review once strict validation appliesAutomation tools, CI pipelines and Admin API calls that create or update routes, consumers and plugins

How the later breaking changes fit into the same path

The point of this section is that the 3.6 release is not the end of the breaking changes. Releases after 3.6 carry further changes to authentication, Admin API defaults and ingress behavior, and each of them is covered on its own sibling page. The practical consequence is that the team should plan a sequence of stops from 3.2 through each relevant line rather than jumping straight to the newest release. A jump skips the point where a change is introduced, so the team loses the chance to read the change in isolation, test it against its own routes and plugins, and roll back if needed.

The sibling pages that follow the 3.6 line are the Apache APISIX 3.9 to 3.10 upgrade, which covers the auto-generated Admin API key, encryption of sensitive fields and header behavior that affects custom plugins; the Apache APISIX 3.10 to 3.12 upgrade, which covers the jwt-auth, hmac-auth and AI plugin changes; the Apache APISIX 3.13 to 3.14 upgrade, which covers Admin API default handling on write and required secrets for jwt-auth and openid-connect sessions; the Apache APISIX 3.15 to 3.17 upgrade, which covers authentication hardening; the Apache APISIX 3.17 to 3.18 upgrade, which covers body buffering, logger limits and LLM metric labels; and the Apache APISIX 3.18 to 3.19 upgrade, which covers upstream TLS verification and token introspection checks. Read each page against your own configuration before you move to the next stop.

Confirm two things before you build the sequence. First, check the exact release tags you will land on in the project's release notes and changelog, because the stop list depends on the version you choose to run. Second, if you run the APISIX Ingress Controller, the separate APISIX Ingress Controller 1.x to 2.x upgrade page applies on its own track, and its blue-green switchover should be scheduled against the gateway stops rather than after them. Record each stop as a dated change in your plan, with its own test scope and rollback point. The effort you will spend depends mostly on how many of your plugins and consumers each stop touches, which is best established by an inventory of your routes and authentication settings.

How DeployOpen scopes and delivers the APISIX upgrade

DeployOpen approaches this upgrade as a scoped engineering change to your gateway, starting from an inventory of your routes, plugins and custom code measured against the 3.3, 3.5 and 3.6 breaking changes. Each step is agreed in writing, tested in a non-production environment and handed over with the runbook your team needs to operate the result.

How we scope

  • We inventory routes, plugins, custom Lua code, etcd configuration and deployment mode before any version is chosen.
  • The written scope names every target release, the environments covered and the breaking changes each step addresses.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts; ask for the quote to list each step.

How we build

  • We rehearse the upgrade on a copy of your configuration, checking the default router change and removed options first.
  • Custom plugins and scripts are tested against the strict schema validation and OpenResty 1.21 requirements.
  • Each intermediate release is validated with replayed traffic and rollback points defined before the production step.

How we hand over

  • You receive an updated configuration repository, a change log mapping each setting to its release, and test evidence.
  • Operating runbooks cover the etcd gRPC and conf server removals, so your team knows the new data plane configuration path.
  • Knowledge transfer sessions walk your engineers through the procedure, rollback steps and open items.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers for later APISIX releases.
  • We track upstream release notes so that future breaking changes are assessed before they reach your gateway.
  • Confirm with DeployOpen the response arrangements and retainer terms in the written agreement before work starts.

Sources and further reading

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.