In an environment receiving large volume of requests, it is always handy to have some pseudo-unique identification so it is easy to track where the request was routed to. APISIX has a built-in request-id plugin that does exactly that: gives each request a unique request ID but it also tags the response with it. If the specific header is present in the request, the plugin will not modify it.

curl http://127.0.0.1:9180/apisix/admin/global_rules/1  -H "X-API-KEY: $APISIX_ADMIN_TOKEN" -X PUT -d '
{
  "plugins": {
    "request-id": {
      "include_in_response": true,
      "header_name": "message-id",
      "generator": "none",
      "disable": false
    }
  }
}'

Modify access logs to display message tag as below in values.yaml and redeploy APISIX.

        accessLogFormat: '$remote_addr - $remote_user [$time_local] $http_host \"$request\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\" $sent_http_message_id'

Example letting APISIX tag message:

dalen@Dalens-MBP ~ % curl -X POST http://localhost:9080/deck-api/deck/create -H 'Content-Type: application/json' -v  -d '{
"deckType": "standard52"
}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Host localhost:9080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:9080...
* Connected to localhost (::1) port 9080
> POST /deck-api/deck/create HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 28
>
* upload completely sent off: 28 bytes
< HTTP/1.1 200
< Content-Type: application/json
< Content-Length: 132
< Connection: keep-alive
< Date: Thu, 16 Oct 2025 14:20:04 GMT
< Server: APISIX
< message-id: f93e00bc-b8fe-456f-ad1d-babc60adbcc5
<
* Connection #0 to host localhost left intact
{"deckState":"rO0ABXcUAApzdGFuZGFyZDUyAAAANAAAAAB1cgACW0p4IAS1ErF1kwIAAHhwAAAAAHVxAH4AAAAAAAEAD////////w==","deckType":"standard52"}%

Example passing original message-id:

dalen@Dalens-MBP ~ % curl -X POST http://localhost:9080/deck-api/deck/create -H 'Content-Type: application/json' -H 'message-id: surprise' -v  -d '{
"deckType": "standard52"
}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Host localhost:9080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:9080...
* Connected to localhost (::1) port 9080
> POST /deck-api/deck/create HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: application/json
> message-id: surprise
> Content-Length: 28
>
* upload completely sent off: 28 bytes
< HTTP/1.1 200
< Content-Type: application/json
< Content-Length: 132
< Connection: keep-alive
< Date: Thu, 16 Oct 2025 14:21:05 GMT
< Server: APISIX
< message-id: surprise
<
* Connection #0 to host localhost left intact
{"deckState":"rO0ABXcUAApzdGFuZGFyZDUyAAAANAAAAAB1cgACW0p4IAS1ErF1kwIAAHhwAAAAAHVxAH4AAAAAAAEAD////////w==","deckType":"standard52"}%