How APISIX Works
In this document, you will learn how the major pieces of APISIX fit together to handle a request, including the configuration store, the router, the plugin engine, the request lifecycle, and the hot-reload model.
Explore additional resources at the end of the document for more information on related topics.
Overview
APISIX is a Lua application that runs inside OpenResty, which is NGINX extended with the lua-nginx-module. NGINX provides the connection handling, worker model, and request phase machinery; APISIX adds a Lua program that hooks into each phase to perform routing, plugin execution, and upstream selection.
This page takes a request-flow view of APISIX. Every request that APISIX serves passes through three runtime components:
- A configuration store that supplies the route and plugin definitions.
- A router that matches the request to a route.
- A plugin engine that runs the matched route's plugins at the appropriate NGINX phase.
The sections below describe each component and then trace a single request through them. Other parts of APISIX such as load balancing, service discovery, and the Admin API are referenced where they appear in the request flow but are covered in depth in their own pages.
The diagram below shows the request and configuration flow in the default traditional deployment mode, where etcd is the source of configuration. The router, plugin engine, balancer, and in-memory configuration all live inside each APISIX worker process:
Standalone mode keeps the same request path but changes where the in-memory configuration comes from. An apisix.yaml (or apisix.json) file on disk is the source, and each worker reloads it when the file changes:
Configuration Store
In the default deployment mode, APISIX uses etcd as the source of truth for routes, upstreams, services, consumers, SSL certificates, plugin configurations, and global rules. Every NGINX worker subscribes to etcd through a long-poll watch and keeps an in-memory copy of the configuration.
When you create or update a resource through the Admin API, the change is written to etcd. Workers observe the change through the watch and rebuild their in-memory routing structures independently, without reload, restart, or cross-worker coordination. Configuration changes apply across a live cluster without dropping connections.
APISIX supports two deployment modes that change where the configuration comes from:
- Traditional mode (default): etcd is the source of truth and every worker watches it. This is the model described above.
- Standalone mode: each worker holds the configuration entirely in memory. The configuration is loaded from
apisix.yaml(orapisix.json) on disk and reloaded when the file changes. There is no etcd.
The request-flow behaviour described in the rest of this page is the same in all modes; only the source of the configuration differs. See Deployment Modes for the full list of supported modes and how to configure them.
Router
The router turns an incoming request into a matched route. APISIX uses a radix tree (a compressed prefix tree) as the matching engine.
Routes are inserted into the tree at configuration time, and at request time the URI is walked through the tree in time proportional to the length of the URI, not the number of routes configured. Match cost stays roughly flat as the route count grows.
APISIX bundles three HTTP router variants, which differ in what they use as the primary index of the tree:
radixtree_host_uri(default): useshost + urias the primary index. Matches both the request host and URI.radixtree_uri: uses onlyurias the primary index. Hosts are not part of the index.radixtree_uri_with_parameter: same asradixtree_uribut additionally supports path parameters such as/user/:id.
The active HTTP router is selected through the apisix.router.http setting in config.yaml. SSL certificate selection during the TLS handshake uses a separate radixtree_sni router that matches the client's SNI value against the configured certificate set. For configuration and a feature comparison of the HTTP router variants, see Router Options.
Plugin Engine
Once the router has identified the matched route, the plugin engine runs the plugins that apply to that request. The set of plugins to run is assembled from several sources:
- The matched route.
- The route's service, if any.
- The matched consumer and consumer group, if any.
- Any global rules.
At each NGINX phase, the engine sorts the assembled plugins by their priority field (highest first) and calls the corresponding phase function on each plugin in turn. A plugin may modify the request, modify the response, or terminate the request early. For example, an authentication plugin can return 401 before the request ever reaches an upstream.
A plugin defines one or more phase functions. The phases the engine drives for HTTP traffic are rewrite, access, before_proxy, header_filter, body_filter, and log.
Most plugins ship as Lua modules. APISIX also supports plugins written in Go, Java, and Python through the external plugin runner, and WebAssembly modules through the WASM runner. See Plugins for the per-phase model and the rules for combining plugin configuration from route, service, and consumer.
Request Lifecycle
The following table traces a single HTTP request through the NGINX phases that APISIX hooks into:
| Phase | What APISIX Does |
|---|---|
ssl_client_hello / ssl_certificate | Use the client's SNI value to pick a certificate from the radixtree_sni router. |
access | Match the request against the HTTP router to identify the route, then run the route's plugins for the rewrite and access plugin phases in priority order. A plugin may short-circuit the request here, for example an authentication plugin returning 401. After the upstream is selected, the before_proxy plugins run, immediately before NGINX dispatches the request to the upstream. |
balancer | Pick a single upstream node from the route's upstream definition, using the configured load-balancing algorithm and, optionally, the active health-check state. |
header_filter | Run response-header plugins as NGINX assembles the response headers. |
body_filter | Run response-body plugins as the response body is streamed back to the client. |
log | Run logging plugins after the response has been sent. Most logger plugins use NGINX timers so the client does not wait for the log write. |
The diagram below shows the order in which APISIX executes routing, the plugin phases, balancer selection, and proxying for a single HTTP request:
Stream (Layer 4) traffic follows a parallel but smaller lifecycle:
| Phase | What APISIX Does |
|---|---|
preread | Match the connection against the stream router to identify the route, then run the route's preread and before_proxy plugins. A plugin may close the connection here. |
balancer | Pick a single upstream node from the route's upstream definition, using the configured load-balancing algorithm and, optionally, the active health-check state. |
log | Run logging plugins after the connection has been closed. |
Hot Configuration Updates
Every worker keeps its own in-memory copy of the configuration and refreshes it from the configured source. Configuration changes therefore apply without reloading NGINX, restarting workers, or coordinating between workers.
In the default traditional mode, a change made through the Admin API is written to etcd and picked up across the cluster on each worker's next watch cycle, with no separate apply step. In standalone mode, the same applies when the apisix.yaml (or apisix.json) file changes.
Additional Resources
- Key Concepts - Routes, Upstreams, Plugins, Stream Routes
- Reference - Router Options