skills/a6-plugin-fault-injection/SKILL.md
Skill for configuring the Apache APISIX fault-injection plugin via the a6 CLI. Covers injecting delays and HTTP aborts for chaos engineering, percentage-based sampling, conditional injection via vars expressions, custom response headers and body with Nginx variable interpolation.
npx skillsauth add moonming/a6 a6-plugin-fault-injectionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The fault-injection plugin injects faults — delays and HTTP aborts — into
requests for chaos engineering and resiliency testing. It runs in the rewrite
phase with priority 11000 (very early), meaning it executes before most other
plugins including authentication and rate limiting.
Execution order: delay first → abort second. If abort fires, subsequent plugins do NOT execute.
At least one of abort or delay must be specified.
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| http_status | integer | Yes | — | HTTP status code (≥ 200) |
| body | string | No | — | Response body; supports Nginx variables ($remote_addr) |
| headers | object | No | — | Response headers; values support Nginx variables |
| percentage | integer | No | 100 (always) | Percentage of requests to abort (0–100) |
| vars | array | No | — | Conditional rules using lua-resty-expr (max 20 items) |
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| duration | number | Yes | — | Delay in seconds (supports decimals: 0.5, 1.5) |
| percentage | integer | No | 100 (always) | Percentage of requests to delay (0–100) |
| vars | array | No | — | Conditional rules using lua-resty-expr (max 20 items) |
The vars field uses lua-resty-expr for conditional fault injection.
[
[["condition1a"], ["condition1b"]], // AND group 1
[["condition2a"]] // AND group 2
]
// Groups joined by OR — first matching group triggers the fault
| Prefix | Source | Example |
|--------|--------|---------|
| arg_* | Query parameters | arg_name → ?name=value |
| http_* | Request headers | http_apikey → X-Api-Key header |
| (none) | Nginx built-ins | remote_addr, uri, request_method |
| Operator | Example |
|----------|---------|
| == | ["arg_name", "==", "jack"] |
| ~= | ["arg_env", "~=", "prod"] |
| >, >=, <, <= | ["arg_age", ">", 18] |
| ~~ | ["arg_env", "~~", "[Dd]ev"] (regex) |
| ~* | ["arg_env", "~*", "dev"] (case-insensitive regex) |
| in | ["arg_ver", "in", ["v1","v2"]] |
| ! | ["arg_age", "!", "<", 18] (negation → >=) |
| ipmatch | ["remote_addr", "ipmatch", ["10.0.0.0/8"]] |
a6 route create -f - <<'EOF'
{
"id": "delay-test",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"delay": {
"duration": 3
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "abort-test",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 503,
"body": "Service temporarily unavailable",
"percentage": 50
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
Only abort when ?name=jack:
a6 route create -f - <<'EOF'
{
"id": "conditional-abort",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 403,
"body": "Fault Injection!\n",
"vars": [
[["arg_name", "==", "jack"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
Abort when (name=jack AND age≥18) OR (has api-key header):
a6 route create -f - <<'EOF'
{
"id": "complex-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 403,
"body": "Fault Injection!\n",
"vars": [
[
["arg_name", "==", "jack"],
["arg_age", "!", "<", 18]
],
[
["http_apikey", "==", "api-key"]
]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "headers-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 200,
"body": "{\"uri\": \"$uri\"}",
"headers": {
"X-Fault-Injected": "true",
"X-Request-URI": "$uri"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
Only users with X-Canary: true header experience 10% fault rate:
a6 route create -f - <<'EOF'
{
"id": "canary-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 500,
"percentage": 10,
"vars": [
[["http_x_canary", "==", "true"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "combined-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"delay": {
"duration": 2,
"vars": [
[["http_x_slow", "==", "true"]]
]
},
"abort": {
"http_status": 503,
"vars": [
[["http_x_fail", "==", "true"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
version: "1"
routes:
- id: fault-injection-demo
uri: /api/*
plugins:
fault-injection:
delay:
duration: 1
percentage: 25
abort:
http_status: 503
body: "Service unavailable"
percentage: 5
upstream_id: my-upstream
sleep(duration)math.random(1, 100) <= percentagePriority 11000 means fault-injection runs very early:
To apply faults only to authenticated users, use vars to check auth-related
variables or headers.
| Symptom | Cause | Fix |
|---------|-------|-----|
| Fault never triggers | percentage: 0 or vars never match | Check vars expressions; set percentage > 0 |
| Fault always triggers | No percentage set (defaults to 100%) | Set percentage to desired value |
| Auth bypass via fault | Plugin runs before auth (priority 11000) | Use vars to restrict fault scope |
| Body not interpolated | Missing $ prefix on variable | Use $uri not uri in body/headers |
| Abort + delay both fire | Delay runs first, then abort | This is expected behavior; delay always executes before abort check |
tools
Core skill for working with the a6 CLI — the Apache APISIX command-line tool. Provides project conventions, command patterns, architecture overview, and development workflow. Load this skill when working on a6 source code, adding new commands, writing tests, or modifying any a6 component.
tools
Recipe skill for implementing multi-tenant API gateway patterns using the a6 CLI. Covers tenant isolation via Consumer Groups, host/path/header-based routing, per-tenant rate limiting, context forwarding with proxy-rewrite, and declarative config sync workflows for multi-tenant management.
tools
Recipe skill for configuring mutual TLS (mTLS) using the a6 CLI. Covers SSL certificate management, upstream mTLS to backend services, client certificate verification, and end-to-end mTLS setup from client through APISIX to upstream.
tools
Recipe skill for configuring upstream health checks using the a6 CLI. Covers active health checks (HTTP probing), passive health checks (response analysis), combining both, configuring healthy/unhealthy thresholds, and monitoring upstream node status.