Skip to main content

a6-plugin-ext-plugin

Overview

The APISIX external plugin system lets you run plugins written in Go, Java, Python, or JavaScript via a Plugin Runner process. APISIX communicates with the runner over a Unix socket using FlatBuffers serialization.

Three plugins control when external plugins execute:

PluginPhasePriorityDescription
ext-plugin-pre-reqrewrite12000Before built-in Lua plugins
ext-plugin-post-reqaccess−3000After Lua plugins, before upstream
ext-plugin-post-respbefore_proxy−4000After upstream response received

When to Use

  • Implement custom logic in Go, Java, or Python instead of Lua
  • Reuse existing business logic from non-Lua codebases
  • Apply pre-processing (auth, validation) or post-processing (response transform)
  • Teams that prefer statically-typed languages over Lua

Plugin Configuration Reference

All three plugins share the same schema:

FieldTypeRequiredDefaultDescription
confarrayNoList of external plugins to execute
conf[].namestringYesPlugin identifier (1–128 chars)
conf[].valuestringYesJSON string configuration passed to the plugin
allow_degradationbooleanNofalseWhen true, requests continue if runner is unavailable

Plugin Runner Architecture

┌──────────┐    Unix Socket    ┌───────────────┐
│ APISIX │ ◄──────────────► │ Plugin Runner │
│ (Nginx) │ FlatBuffers │ (Go/Java/Py) │
└──────────┘ └───────────────┘
  1. APISIX starts the runner as a subprocess (managed lifecycle)
  2. On ext-plugin-* trigger, APISIX sends an RPC over Unix socket
  3. Runner executes external plugins and returns the result
  4. APISIX applies modifications (headers, body, status) to the request/response

RPC Protocol

  • PrepareConf: Syncs plugin configuration → returns a conf token (cached)
  • HTTPReqCall: Per-request execution with serialized HTTP data + conf token
  • ExtraInfo: Runner can request additional data (variables, body, response)

Supported Plugin Runners

LanguageRepositoryStatus
Goapache/apisix-go-plugin-runnerGA
Javaapache/apisix-java-plugin-runnerGA
Pythonapache/apisix-python-plugin-runnerExperimental
JavaScriptzenozeng/apisix-javascript-plugin-runnerCommunity

APISIX Configuration (config.yaml)

Production Setup

APISIX manages the runner as a subprocess:

ext-plugin:
cmd: ["/path/to/runner-executable", "run"]

Runner-Specific Commands

# Go runner
ext-plugin:
cmd: ["/opt/apisix-go-runner", "run"]

# Java runner
ext-plugin:
cmd: ["java", "-jar", "-Xmx1g", "-Xms1g", "/opt/apisix-runner.jar"]

# Python runner
ext-plugin:
cmd: ["python3", "/opt/apisix-python-runner/apisix/main.py", "start"]

Development Setup (Standalone Runner)

For local development, run the runner separately:

# APISIX config.yaml — do NOT set cmd
ext-plugin:
path_for_test: "/tmp/runner.sock"
# Start runner manually
APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock ./runner run

Environment Variables

Pass environment variables to the runner:

nginx_config:
envs:
- MY_ENV_VAR
- DATABASE_URL

Step-by-Step Examples

1. Single External Plugin

a6 route create -f - <<'EOF'
{
"id": "ext-auth",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF

2. Multiple External Plugins with Degradation

a6 route create -f - <<'EOF'
{
"id": "ext-chain",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"},
{"name": "RateLimiter", "value": "{\"requests_per_second\":100}"}
],
"allow_degradation": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF

3. All Three Plugin Types (Full Request Lifecycle)

a6 route create -f - <<'EOF'
{
"id": "full-ext",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [{"name": "auth-check", "value": "{}"}]
},
"ext-plugin-post-req": {
"conf": [{"name": "request-transform", "value": "{}"}]
},
"ext-plugin-post-resp": {
"conf": [{"name": "response-logger", "value": "{}"}]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF

Execution order: pre-req → (Lua plugins) → post-req → (upstream) → post-resp

Config Sync Example

version: "1"
routes:
- id: ext-plugin-demo
uri: /api/*
plugins:
ext-plugin-pre-req:
conf:
- name: AuthFilter
value: '{"token_required":true}'
allow_degradation: true
upstream_id: my-upstream

Compatibility Matrix

Featureext-plugin-pre-reqext-plugin-post-reqext-plugin-post-resp
Phaserewriteaccessbefore_proxy
RunsBefore Lua pluginsAfter Lua pluginsAfter upstream response
proxy-mirror
proxy-cache
proxy-control
mTLS to upstream

ext-plugin-post-resp limitation: Uses lua-resty-http internally, which makes it incompatible with proxy-mirror, proxy-cache, proxy-control, and mTLS to upstream.

Performance Considerations

  • Unix socket + FlatBuffers: Low-latency IPC, no TCP overhead
  • Conf token caching: PrepareConf called once per config change, not per request
  • Process management: APISIX sends SIGTERM then SIGKILL (1s grace) on reload
  • Degradation mode: Enable allow_degradation: true for non-critical plugins
  • Connection reuse: Runner should reuse socket connections

Troubleshooting

SymptomCauseFix
failed to receive RPC_PREPARE_CONFRunner not listening or socket path mismatchVerify path_for_test matches APISIX_LISTEN_ADDRESS
503 Service UnavailableRunner crashed or not startedCheck runner logs; verify cmd path is correct
Runner not receiving env varsNginx hides env vars by defaultAdd vars to nginx_config.envs in config.yaml
Slow response timesExternal plugin doing heavy workProfile runner; consider async processing
ext-plugin-post-resp conflictsIncompatible with proxy-* pluginsUse ext-plugin-post-req instead, or remove proxy-mirror/cache

This page is generated from a6-plugin-ext-plugin/SKILL.md in the api7/a6 repository. Browse all skills on the AI Agent Skills page.

API7.ai Logo

The digital world is connected by APIs,
API7.ai exists to make APIs more efficient, reliable, and secure.

Sign up for API7 newsletter

Product

API7 Gateway

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2026. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the Apache Software Foundation