APISIX vs Kong Plugin Ecosystems

Kong and APISIX are close enough architecturally that a feature comparison is mostly a draw: both are NGINX-derived, both run Lua plugins, both have declarative configuration and a control-plane story. The differences that decide a selection are in the extension model, the configuration store, and what happens when you need something the plugin catalogue does not have. This page compares those.

Prerequisite concepts

This complements gateway selection criteria, which covers the control-plane shapes, and Kong vs Tyk vs Envoy for microservices, which covers execution models across a wider field.

Where the configuration lives

A polling database, a static file, or a watched key-value store Kong reads from a relational database with a cache refreshed on an interval, or from a declarative file loaded at boot. APISIX watches etcd, so a configuration change is pushed to every node within milliseconds and requires no restart, at the cost of operating an etcd cluster as a production dependency. Kong 3.x database or YAML file node node cache refreshed on a timer, or immutable until redeploy APISIX 3.x etcd, watched node node pushed in milliseconds, etcd is a production dependency

The propagation difference is real and cuts both ways. Sub-second convergence is genuinely useful for traffic shifting and incident response. It also means a bad configuration reaches every node in milliseconds, so the staged rollout discipline from rolling back a bad gateway config safely matters more, not less.

The extension model

Both run Lua in the request path. The differences show at the edges: what else you can write a plugin in, and how a plugin is deployed.

Three entities or one, and what that does to a code review Kong splits a route into a service, a route and one plugin entity per policy, related by identifier. APISIX puts the upstream, the matching rule and the plugin configuration into a single route object. Neither model is more expressive; they produce very different diffs. Kong 3.x — related entities service route plugin: jwt plugin: rate-limiting four objects, joined by id APISIX 3.x — one object route: uri + upstream + plugins { jwt-auth, limit-count, proxy-rewrite } the whole behaviour of the route is visible in one diff one object, self-contained The Kong model reuses a service across many routes, which is genuinely useful at scale; the APISIX model makes a single route reviewable without cross-referencing. Pick the one that matches how your team reviews changes. What you can write a plugin in, and what it costs to run Both support Lua in-process at the lowest cost. Both support external plugin runners for Go, Python and JavaScript at the cost of an inter-process hop per request. APISIX additionally runs WebAssembly modules in-process, and Kong offers a Go plugin development kit over the same external runner mechanism. runtime Kong APISIX cost per request Lua, in-process yes yes microseconds WebAssembly, in-process no yes tens of microseconds Go, Python, JS — external yes yes an IPC hop, per request The bottom row is the one to model before committing: an inter-process hop on every request is a latency floor and a second process to supervise, and it is where most "we will just write a plugin" plans meet reality.
# APISIX 3.x — a route with plugins, expressed in one object
routes:
  - uri: /v2/orders/*
    name: orders
    upstream:
      type: roundrobin
      nodes: { "orders.internal:8080": 1 }
    plugins:
      limit-count:
        count: 1000
        time_window: 60
        key_type: var
        key: consumer_name
        policy: redis
        redis_host: redis.internal
      jwt-auth: {}
      proxy-rewrite:
        regex_uri: ["^/v2/orders/(.*)", "/orders/$1"]

APISIX keeps route, upstream and plugins in one object; Kong splits them into service, route and plugin entities. Neither is better, but the difference shows up in how configuration is reviewed: APISIX diffs are self-contained, Kong diffs require holding three entities in your head at once.

Decision matrix

If you care most about Lean
Sub-second config propagation APISIX
Not operating etcd Kong, DB-less
A large commercial plugin catalogue Kong
WebAssembly extensions in-process APISIX
Familiar relational operations Kong with a database
One object per route in review APISIX
Existing team experience whichever they already run

Gotchas and failure signals

etcd is a real dependency. Its quorum, disk latency and backup story become yours. An etcd cluster on slow disks manifests as configuration changes that apply on some nodes and not others.

External plugin runners fail independently. When the runner process dies, requests either bypass the plugin or fail, depending on configuration — decide which, explicitly, before it happens.

Plugin priority ordering differs between the two, so a chain ported from one produces a different execution order on the other. Re-derive the order rather than translating the numbers.

Both catalogues contain plugins of varying maturity. Check when the plugin was last updated and whether it is covered by the same support agreement as the core.

Migration between them is mostly the plugins

Because both are NGINX-derived and both express routes, upstreams and policies, the routing half of a migration in either direction is close to mechanical: paths, hosts, methods and upstream targets map across with little judgement involved. What does not map is everything that carries configuration semantics — plugin names, their option keys, their defaults, and above all their ordering.

The practical approach is to treat the plugin chain as a specification to be re-derived rather than a config to be translated. Write down what each route must enforce and in what order, in plain language, then implement that on the target and assert it with tests that exercise the boundaries: an unauthenticated request, an over-quota request, a request that should be rewritten, and one that should pass through untouched. That set catches ordering mistakes, which are the errors most likely to survive a manual review, because a chain in the wrong order usually still works for the happy path.

Validation

  • Configuration store operated by someone, with backups tested
  • Plugin execution order asserted by a test, not inferred from the catalogue
  • External runner failure mode chosen and exercised
  • Propagation time measured under a realistic route count
  • Any custom plugin has an owner and a test that runs on upgrade
  • Upgrade path rehearsed on a copy of production configuration, including every custom plugin, since both projects have made breaking changes to plugin interfaces between major releases and the failure surfaces at boot rather than in review

FAQ

What is the biggest practical difference between them?

Where configuration lives and how fast it propagates. APISIX watches etcd, so a change reaches every node in milliseconds without a restart. Kong reads from a relational database with a periodically refreshed cache, or from a declarative file fixed at boot. Fast propagation is genuinely useful and it also means a bad change arrives everywhere just as quickly, so staged rollout matters more rather than less.

Do I have to run etcd to use APISIX?

Yes, and it should be treated as a production dependency with the same care as any datastore: quorum, disk latency, backups and an upgrade path. The symptom of an under-provisioned etcd is configuration that applies on some nodes and not others, which is much harder to diagnose than an outright failure.

Can I write plugins in Go for either?

Both support external plugin runners for Go and other languages, at the cost of an inter-process hop on every request that traverses the plugin. That is a latency floor and a second process to supervise. APISIX additionally supports WebAssembly modules in-process, which avoids the hop for extensions that fit the model.

Can I port a plugin chain from one to the other?

The plugins usually have equivalents, but the execution order will not carry across — priority numbering differs between the two. Re-derive the intended order from the semantics, assert it with a test, and treat any chain that depends on a subtle ordering as something to verify rather than translate.


Parent: Gateway Selection Criteria