Skip to main content
Version: 2.5


Why a new API gateway?#

There are new requirements for API gateways in the field of microservices: higher flexibility, higher performance requirements, and cloud native.

What are the differences between APISIX and other API gateways?#

APISIX is based on etcd to save and synchronize configuration, not relational databases such as Postgres or MySQL.

This not only eliminates polling, makes the code more concise, but also makes configuration synchronization more real-time. At the same time, there will be no single point in the system, which is more usable.

In addition, APISIX has dynamic routing and hot loading of plug-ins, which is especially suitable for API management under micro-service system.

What's the performance of APISIX?#

One of the goals of APISIX design and development is the highest performance in the industry. Specific test data can be found here:benchmark

APISIX is the highest performance API gateway with a single-core QPS of 23,000, with an average delay of only 0.6 milliseconds.

Does APISIX have a console interface?#

Yes, APISIX has a powerful Dashboard. APISIX and APISIX Dashboard are independent projects, you can deploy APISIX Dashboard to operate APISIX through the web interface.

Can I write my own plugin?#

Of course, APISIX provides flexible custom plugins for developers and businesses to write their own logic.

How to write plugin

Why we choose etcd as the configuration center?#

For the configuration center, configuration storage is only the most basic function, and APISIX also needs the following features:

  1. Cluster
  2. Transactions
  3. Multi-version Concurrency Control
  4. Change Notification
  5. High Performance

See more etcd why.

Why is it that installing APISIX dependencies with Luarocks causes timeout, slow or unsuccessful installation?#

There are two possibilities when encountering slow luarocks:

  1. Server used for luarocks installation is blocked
  2. There is a place between your network and github server to block the 'git' protocol

For the first problem, you can use https_proxy or use the --server option to specify a luarocks server that you can access or access faster. Run the luarocks config rocks_servers command(this command is supported after luarocks 3.0) to see which server are available. For China mainland users, you can use the as the luarocks server.

We already provide a wrapper in the Makefile to simplify your job:


If using a proxy doesn't solve this problem, you can add --verbose option during installation to see exactly how slow it is. Excluding the first case, only the second that the git protocol is blocked. Then we can run git config --global url."https://".insteadOf git:// to using the 'HTTPS' protocol instead of git.

How to support gray release via APISIX?#

An example,, gray release based on id in the query string in URL as a condition:

  1. Group A:id <= 1000
  2. Group B:id > 1000

There are two different ways to do this:

  1. Use the vars field of route to do it.
curl -i -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/index.html",    "vars": [        ["arg_id", "<=", "1000"]    ],    "plugins": {        "redirect": {            "uri": "/test?group_id=1"        }    }}'
curl -i -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/index.html",    "vars": [        ["arg_id", ">", "1000"]    ],    "plugins": {        "redirect": {            "uri": "/test?group_id=2"        }    }}'

Here is the operator list of current lua-resty-radixtree

  1. Use traffic-split plugin to do it.

Please refer to the plugin documentation for usage examples.

How to redirect http to https via APISIX?#

An example, redirect to

There are several different ways to do this.

  1. Directly use the http_to_https in redirect plugin:
curl  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/hello",    "host": "",    "plugins": {        "redirect": {            "http_to_https": true        }    }}'
  1. Use with advanced routing rule vars with redirect plugin:
curl -i  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/hello",    "host": "",    "vars": [        [            "scheme",            "==",            "http"        ]    ],    "plugins": {        "redirect": {            "uri": "https://$host$request_uri",            "ret_code": 301        }    }}'
  1. serverless plugin:
curl -i  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/hello",    "plugins": {        "serverless-pre-function": {            "phase": "rewrite",            "functions": ["return function() if ngx.var.scheme == \"http\" and == \"\" then ngx.header[\"Location\"] = \"\" .. ngx.var.request_uri; ngx.exit(ngx.HTTP_MOVED_PERMANENTLY); end; end"]        }    }}'

Then test it to see if it works:

curl -i -H 'Host:'

The response body should be:

HTTP/1.1 301 Moved PermanentlyDate: Mon, 18 May 2020 02:56:04 GMTContent-Type: text/htmlContent-Length: 166Connection: keep-aliveLocation: APISIX web server
<html><head><title>301 Moved Permanently</title></head><body><center><h1>301 Moved Permanently</h1></center><hr><center>openresty</center></body></html>

How to fix OpenResty Installation Failure on MacOS 10.15#

When you install the OpenResty on MacOs 10.15, you may face this error

> brew install openrestyUpdating Homebrew...==> Auto-updated Homebrew!Updated 1 tap (homebrew/cask).No changes to formulae.
==> Installing openresty from openresty/brewWarning: A newer Command Line Tools release is available.Update them from Software Update in System Preferences or
==> Downloading downloaded: /Users/wusheng/Library/Caches/Homebrew/downloads/4395089f0fd423261d4f1124b7beb0f69e1121e59d399e89eaa6e25b641333bc--openresty-> ./configure -j8 --prefix=/usr/local/Cellar/openresty/ --pid-path=/usr/local/var/run/ --lock-path=/usr/Last 15 lines from /Users/wusheng/Library/Logs/Homebrew/openresty/01.configure:DYNASM    host/buildvm_arch.hHOSTCC    host/buildvm.oHOSTLINK  host/buildvmBUILDVM   lj_vm.SBUILDVM   lj_ffdef.hBUILDVM   lj_bcdef.hBUILDVM   lj_folddef.hBUILDVM   lj_recdef.hBUILDVM   lj_libdef.hBUILDVM   jit/vmdef.luamake[1]: *** [lj_folddef.h] Segmentation fault: 11make[1]: *** Deleting file `lj_folddef.h'make[1]: *** Waiting for unfinished jobs....make: *** [default] Error 2ERROR: failed to run command: gmake -j8 TARGET_STRIP=@: CCDEBUG=-g XCFLAGS='-msse4.2 -DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT' CC=cc PREFIX=/usr/local/Cellar/openresty/
If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
These open issues may also help:Can't install openresty on macOS 10.15 openresty-debug package should use openresty-openssl-debug instead to install OpenResty
Error: A newer Command Line Tools release is available.Update them from Software Update in System Preferences or

This is an OS incompatible issue, you could fix by these two steps

  1. brew edit openresty/brew/openresty
  2. add \ -fno-stack-check in with-luajit-xcflags line.

How to change the log level?#

The default log level for APISIX is warn. However You can change the log level to info if you want to trace the messages print by


  1. Modify the parameter error_log_level: "warn" to error_log_level: "info" in conf/config.yaml.
nginx_config:  error_log_level: "info"
  1. Reload or restart APISIX

Now you can trace the info level log in logs/error.log.

How to reload your own plugin?#

The Apache APISIX plugin supports hot reloading. See the Hot reload section in plugins for how to do that.

How to make APISIX listen on multiple ports when handling HTTP or HTTPS requests?#

By default, APISIX only listens on port 9080 when handling HTTP requests. If you want APISIX to listen on multiple ports, you need to modify the relevant parameters in the configuration file as follows:

  1. Modify the parameter of HTTP port listen node_listen in conf/config.yaml, for example:

     apisix:   node_listen:     - 9080     - 9081     - 9082

    Handling HTTPS requests is similar, modify the parameter of HTTPS port listen ssl.listen_port in conf/config.yaml, for example:

    apisix:  ssl:    listen_port:      - 9443      - 9444      - 9445
  2. Reload or restart APISIX

How does APISIX use etcd to achieve millisecond-level configuration synchronization#

etcd provides subscription functions to monitor whether the specified keyword or directory is changed (for example: watch, watchdir).

APISIX uses etcd.watchdir to monitor directory content changes:

  • If there is no data update in the monitoring directory: the process will be blocked until timeout or other errors occurred.
  • If the monitoring directory has data updates: etcd will return the new subscribed data immediately (in milliseconds), and APISIX will update it to the memory cache.

With the help of etcd which incremental notification feature is millisecond-level, APISIX achieve millisecond-level of configuration synchronization.

How to customize the APISIX instance id?#

By default, APISIX will read the instance id from conf/apisix.uid. If it is not found, and no id is configured, APISIX will generate a uuid as the instance id.

If you want to specify a meaningful id to bind APISIX instance to your internal system, you can configure it in conf/config.yaml, for example:

```apisix:  id: "your-meaningful-id"```

Why there are a lot of "failed to fetch data from etcd, failed to read etcd dir, etcd key: xxxxxx" errors in error.log?#

First please make sure the network between APISIX and etcd cluster is not partitioned.

If the network is healthy, please check whether your etcd cluster enables the gRPC gateway. However, The default case for this feature is different when use command line options or configuration file to start etcd server.

  1. When command line options is in use, this feature is enabled by default, the related option is --enable-grpc-gateway.
etcd --enable-grpc-gateway --data-dir=/path/to/data

Note this option is not shown in the output of etcd --help.

  1. When configuration file is used, this feature is disabled by default, please enable enable-grpc-gateway explicitly.
# etcd.json{    "enable-grpc-gateway": true,    "data-dir": "/path/to/data"}

Indeed this distinction was eliminated by etcd in their master branch, but not backport to announced versions, so be care when deploy your etcd cluster.

How to set up high available Apache APISIX clusters?#

The high availability of APISIX can be divided into two parts:

  1. The data plane of Apache APISIX is stateless and can be elastically scaled at will. Just add a layer of LB in front.

  2. The control plane of Apache APISIX relies on the highly available implementation of etcd cluster and does not require any relational database dependency.

Why does the make deps command fail in source installation?#

When executing the make deps command, an error such as the one shown below occurs. This is caused by the missing openresty's openssl development kit, you need to install it first. Please refer to the /docs/apisix/2.5/install-dependencies document for installation.

$ make deps......Error: Failed installing dependency: - Could not find header file for OPENSSL  No file openssl/ssl.h in /usr/local/includeYou may have to install OPENSSL in your system and/or pass OPENSSL_DIR or OPENSSL_INCDIR to the luarocks command.Example: luarocks install luasec OPENSSL_DIR=/usr/localmake: *** [deps] Error 1

How to access APISIX Dashboard through APISIX proxy#

  1. Keep the APISIX proxy port and Admin API port different(or disable Admin API). For example, do the following configuration in conf/config.yaml.

The Admin API use a separate port 9180:

apisix:  port_admin: 9180            # use a separate port
  1. Add proxy route of APISIX Dashboard:

Note: The APISIX Dashboard service here is listening on

curl -i  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uris":[ "/*" ],    "name":"apisix_proxy_dashboard",    "upstream":{        "nodes":[            {                "host":"",                "port":9000,                "weight":1            }        ],        "type":"roundrobin"    }}'

How to use route uri for regular matching#

The regular matching of uri is achieved through the vars field of route.

curl -i -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{    "uri": "/*",    "vars": [        ["uri", "~~", "^/[a-z]+$"]    ],    "upstream": {            "type": "roundrobin",            "nodes": {                "": 1            }    }}'

Test request:

# The uri matched successfully$ curl -iHTTP/1.1 200 OK...
# The uri match failedcurl -iHTTP/1.1 404 Not Found...

In route, we can achieve more condition matching by combining uri with vars field. For more details of using vars, please refer to lua-resty-expr.