request-id
The request-id plugin assigns a unique ID to each request proxied through the gateway, which can be used for request tracking and debugging. If a request already includes an ID in the header specified by header_name, the plugin uses that value instead of generating a new one.
The request ID is included in gateway logs by default. When the plugin is enabled, it is also added to the response header.
Examples
The examples below demonstrate how you can configure request-id in different scenarios.
Understand Request ID in Gateway Logs
The request ID is included in both access and error logs in APISIX from version 3.15.0 and in API7 Enterprise from version 3.3.0, regardless of whether the plugin is enabled.
- When the plugin is disabled, the request ID defaults to Nginx's built-in
$request_id. - When the plugin is enabled, the request ID is set to the unique ID generated by the plugin.
This ensures request tracing is always available, with enhanced functionality when the plugin is enabled.
The following example demonstrates how the request ID appears in the gateway logs when the plugin is disabled and when it is enabled.
Create a route without the request-id plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response. In the gateway log, you should see an entry similar to the following, where the last value is the request ID from Nginx's built-in $request_id:
192.168.215.1 - - [30/Jan/2026:07:21:31 +0000] localhost:9080 "GET /anything HTTP/1.1" 200 391 1.657 "-" "curl/8.6.0" 3.210.41.225:80 200 1.608 "http://localhost:9080" "8a14012e5d0414aff4f15f04b0bd8cb9"
Update the route with the request-id plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response. In the gateway log, you should see an entry similar to the following, where the last value is the request ID generated by the plugin:
192.168.215.1 - - [30/Jan/2026:07:36:24 +0000] localhost:9080 "GET /anything HTTP/1.1" 200 391 0.685 "-" "curl/8.6.0" 52.20.30.6:80 200 0.653 "http://localhost:9080" "8c0ac818-f9d6-4160-be60-8fc74e76be73"
Attach Request ID to Default Response Header
The following example demonstrates how to configure request-id on a route which attaches a generated request ID to the default X-Request-Id response header, if the header value is not passed in the request. When the X-Request-Id header is set in the request, the plugin will take the value in the request header as the request ID.
Create a route with the request-id plugin using its default configurations (explicitly defined):
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {
"header_name": "X-Request-Id",
"include_in_response": true,
"algorithm": "uuid"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id:
header_name: X-Request-Id
include_in_response: true
algorithm: uuid
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
header_name: X-Request-Id
include_in_response: true
algorithm: uuid
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
config:
header_name: X-Request-Id
include_in_response: true
algorithm: uuid
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response and see the response includes the X-Request-Id header with a generated ID:
X-Request-Id: b9b2c0d4-d058-46fa-bafc-dd91a0ccf441
Send a request to the route with a custom request ID in the header:
curl -i "http://127.0.0.1:9080/anything" -H 'X-Request-Id: some-custom-request-id'
You should receive an HTTP/1.1 200 OK response and see the response includes the X-Request-Id header with the custom request ID:
X-Request-Id: some-custom-request-id
Attach Request ID to Custom Response Header
The following example demonstrates how to configure request-id on a route which attaches a generated request ID to a specified header.
Create a route with the request-id plugin as such:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {
"header_name": "X-Req-Identifier",
"include_in_response": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id:
header_name: X-Req-Identifier
include_in_response: true
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
header_name: X-Req-Identifier
include_in_response: true
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
config:
header_name: X-Req-Identifier
include_in_response: true
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
❶ Define a custom header that carries the request ID.
❷ Include the request ID in the response header.
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response and see the response includes the X-Req-Identifier header with a generated ID:
X-Req-Identifier: 1c42ff59-ee4c-4103-a980-8359f4135b21
Hide Request ID in Response Header
The following example demonstrates how to configure request-id on a route which attaches a generated request ID to a specified header. The header containing the request ID should be forwarded to the upstream service but not returned in the response header.
Create a route with the request-id plugin as such:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {
"header_name": "X-Req-Identifier",
"include_in_response": false
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id:
header_name: X-Req-Identifier
include_in_response: false
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
header_name: X-Req-Identifier
include_in_response: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
config:
header_name: X-Req-Identifier
include_in_response: false
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
❶ Define a custom header that carries the request ID.
❷ Do not include the request ID in the response header.
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response not and see X-Req-Identifier header among the response headers. In the response body, you should see:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-6752748c-7d364f48564508db1e8c9ea8",
"X-Forwarded-Host": "127.0.0.1",
"X-Req-Identifier": "268092bc-15e1-4461-b277-bf7775f2856f"
},
...
}
This shows the request ID is forwarded to the upstream service but not returned in the response header.
Use nanoid Algorithm
The following example demonstrates how to configure request-id on a route and use the nanoid algorithm to generate the request ID.
Create a route with the request-id plugin as such:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {
"algorithm": "nanoid"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id:
algorithm: nanoid
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
algorithm: nanoid
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
config:
algorithm: nanoid
Apply the configuration to your cluster:
kubectl apply -f request-id-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response and see the response includes the X-Req-Identifier header with an ID generated using the nanoid algorithm:
X-Request-Id: kepgHWCH2ycQ6JknQKrX2
Attach Request ID Globally and on a Route
The following example demonstrates how to configure request-id as a global plugin and on a route to attach two IDs.
- Admin API
- ADC
- Ingress Controller
Create a global rule for the request-id plugin which adds request ID to a custom header:
curl -i "http://127.0.0.1:9180/apisix/admin/global_rules" -X PUT -d '{
"id": "rule-for-request-id",
"plugins": {
"request-id": {
"header_name": "Global-Request-ID"
}
}
}'
Create a route with the request-id plugin which adds request ID to a different custom header:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "request-id-route",
"uri": "/anything",
"plugins": {
"request-id": {
"header_name": "Route-Request-ID"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
Configure the request-id plugin as a global rule and on a route:
global_rules:
- id: rule-for-request-id
plugins:
request-id:
header_name: Global-Request-ID
services:
- name: request-id-service
routes:
- name: request-id-route
uris:
- /anything
plugins:
request-id:
header_name: Route-Request-ID
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
Update your GatewayProxy manifest to enable request-id as a global plugin:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# ...
# your control plane connection configuration
plugins:
- name: request-id
enabled: true
config:
header_name: Global-Request-ID
Create a route with the request-id plugin which adds request ID to a different custom header:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: request-id-plugin-config
spec:
plugins:
- name: request-id
config:
header_name: Route-Request-ID
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: request-id-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: request-id-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f request-id-ic.yaml
Create a Kubernetes manifest file for a global request-id plugin:
apiVersion: apisix.apache.org/v2
kind: ApisixGlobalRule
metadata:
namespace: aic
name: global-request-id
spec:
ingressClassName: apisix
plugins:
- name: request-id
enable: true
config:
header_name: Global-Request-ID
Create a route with the request-id plugin which adds request ID to a different custom header:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: request-id-route
spec:
ingressClassName: apisix
http:
- name: request-id-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: request-id
enable: true
config:
header_name: Route-Request-ID
Apply the configuration to your cluster:
kubectl apply -f global-request-id.yaml -f request-id-ic.yaml
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response and see the response includes the following headers:
Global-Request-ID: 2e9b99c1-08ed-4a74-b347-49c0891b07ad
Route-Request-ID: d755666b-732c-4f0e-a30e-a7a71ace4e26