Docs
Apache APISIXHow-To GuidesTraffic ManagementProxy WebSocket Connections
Version: 3.19.0

Proxy WebSocket Connections

WebSocket provides persistent, bidirectional communication over a single TCP connection. It is commonly used for live feeds, chat, collaborative applications, and other workloads that exchange data in real time.

APISIX can proxy the initial HTTP upgrade request and keep the resulting WebSocket connection open. This guide configures a route to a WebSocket upstream and verifies bidirectional traffic through APISIX.

Prerequisite(s)

Start a WebSocket Upstream

Set GATEWAY_CONTAINER to the running APISIX container. Create a dedicated network and connect the gateway to it:

export GATEWAY_CONTAINER=replace-with-apisix-container-name

docker network create gateway-websocket-net
docker network connect gateway-websocket-net "$GATEWAY_CONTAINER"

Start a pinned sample WebSocket server on the shared network:

docker run -d \
  --name websocket-server \
  --network gateway-websocket-net \
  jmalloc/echo-server:v0.3.7

The server exposes /.ws, which echoes each received message.

Create a Route

Create a route to the WebSocket endpoint and enable WebSocket proxying:

curl "http://127.0.0.1:9180/apisix/admin/routes/websocket-proxy" -X PUT \
  -H "X-API-KEY: ${ADMIN_API_KEY}" \
  -d '{
    "uri": "/.ws",
    "enable_websocket": true,
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "websocket-server:8080": 1
      }
    }
  }'

Verify the Connection

Open a connection through APISIX:

websocat "ws://127.0.0.1:9080/.ws"

Send hello. The server should echo the message:

Request served by <container-id>
hello
hello

The open connection and echoed message confirm that APISIX completed the protocol upgrade and proxies traffic in both directions.

Proxy WebSocket Frames

APISIX can parse WebSocket frames so that plugins can inspect or modify messages. Configure this behavior with a ws or wss upstream and the websocket-proxy plugin. By comparison, enable_websocket performs the protocol upgrade and then relays bytes without exposing individual frames to plugins.

To let plugins process messages from the sample server above, create another route with an upstream scheme of ws:

curl "http://127.0.0.1:9180/apisix/admin/routes/ws-frames" -X PUT \
  -H "X-API-KEY: ${ADMIN_API_KEY}" \
  -d '{
    "uri": "/ws-frames",
    "plugins": {
      "proxy-rewrite": {
        "uri": "/.ws"
      },
      "websocket-proxy": {
        "client_max_payload_len": 1048576,
        "upstream_max_payload_len": 1048576
      }
    },
    "upstream": {
      "type": "roundrobin",
      "scheme": "ws",
      "nodes": {
        "websocket-server:8080": 1
      }
    }
  }'

❶ client_max_payload_len and upstream_max_payload_len raise each direction's default 65,535-byte limit to 1 MiB. The limits apply independently to complete messages, including messages split across frames.

❷ scheme enables frame processing with ws. Use wss for a secure upstream. The enable_websocket route option has no effect on ws or wss upstreams.

Connect and send messages as before:

websocat "ws://127.0.0.1:9080/ws-frames"

Authentication and other rewrite- and access-phase plugins still run during the HTTP handshake. HTTP response transformation plugins do not transform WebSocket messages. Logging runs after the connection closes.

For a secure upstream, use wss, enable upstream.tls.verify, and configure trusted CA certificates through apisix.ssl.ssl_trusted_certificate in config.yaml. The ws and wss schemes do not support per-upstream tls.ca_certs. Set the upstream host to a name covered by the certificate. See Configure Upstream HTTPS for trust and hostname configuration.

Next Steps

You have configured APISIX to proxy WebSocket connections. To control the number of concurrent connections, see Rate Limit WebSocket Connections.