Skip to main content
Version: 3.17

traffic-label

Description#

The traffic-label Plugin sets request headers based on configurable matching rules. Similar to the workflow Plugin, it evaluates rules in order and executes an action on the first match. The key difference is that traffic-label supports weighted distribution within each rule's action list, enabling proportional traffic labeling for canary deployments and A/B testing.

Each rule consists of:

  • match — An optional list of conditions evaluated using lua-resty-expr. If omitted, the rule matches all requests.
  • actions — An array of actions to execute when the rule matches. Each action can set request headers and has an optional weight. Traffic is distributed proportionally across actions using weighted round-robin.

Rules are evaluated in array order. Evaluation stops at the first matching rule.

Attributes#

NameTypeRequiredDefaultValid valuesDescription
rulesarray[object]TrueList of matching rules. Rules are evaluated in order; the first match wins.
rules[].matcharrayFalse[]Match conditions using lua-resty-expr syntax. Each element is either an expression array [var, operator, value] or the string "OR" / "AND" to control logical grouping. When omitted, the rule matches all requests.
rules[].actionsarray[object]TrueActions to execute when the rule matches. Traffic is distributed across actions based on their weight.
rules[].actions[].set_headersobjectFalseRequest headers to set. Overwrites an existing header or adds a new one. Values support NGINX variables such as $remote_addr. Format: {"header-name": "value"}.
rules[].actions[].weightintegerFalse1≥ 1Relative weight for this action. Traffic proportion = this weight / sum of all weights in the rule. An action with only weight set passes traffic through without modification.
note
  • Rules are evaluated in order. Only the first matching rule executes; subsequent rules are skipped.
  • Currently, set_headers is the only supported action type.

Examples#

The examples below demonstrate how you can configure traffic-label in different scenarios.

note
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

Label Traffic Based on Request Conditions#

The following example demonstrates how to set a request header X-Server-Id to different values based on the ?version query parameter.

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "traffic-label-route",
"uri": "/anything",
"plugins": {
"traffic-label": {
"rules": [
{
"match": [["arg_version", "==", "v1"]],
"actions": [{"set_headers": {"X-Server-Id": "100"}}]
},
{
"match": [["arg_version", "==", "v2"]],
"actions": [{"set_headers": {"X-Server-Id": "200"}}]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"httpbin.org:80": 1}
}
}'

Send a request with ?version=v1:

curl "http://127.0.0.1:9080/anything?version=v1"

The upstream will receive X-Server-Id: 100. Send a request with ?version=v2 and the upstream receives X-Server-Id: 200. Requests without a version parameter match no rule and pass through without modification.

Distribute Traffic Across Actions by Weight#

The following example demonstrates weighted distribution using traffic-label. When a request matches the rule, traffic is proportionally distributed across actions based on their weight:

  • 30% of requests: X-Server-Id: 100
  • 20% of requests: X-API-Version: v2
  • 50% of requests: pass through without modification
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "traffic-label-route",
"uri": "/anything",
"plugins": {
"traffic-label": {
"rules": [
{
"match": [["uri", "==", "/anything"]],
"actions": [
{
"set_headers": {"X-Server-Id": "100"},
"weight": 3
},
{
"set_headers": {"X-API-Version": "v2"},
"weight": 2
},
{
"weight": 5
}
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"httpbin.org:80": 1}
}
}'

The total weight is 3 + 2 + 5 = 10. Across 10 requests, approximately 3 will have X-Server-Id: 100, 2 will have X-API-Version: v2, and 5 will pass through without any added header.