A Traefik middleware plugin that adds or propagates an X-Request-ID header.
If the incoming request already contains the configured request ID header, the plugin preserves it and also adds the same value to the response headers.
If the incoming request does not contain the header, the plugin generates a new UUID v7, injects it into the request, and returns the same value in the response.
In distributed systems, reverse proxies, APIs, workers, and logs need a common identifier to correlate what happened during a request.
This plugin helps you:
- correlate Traefik access logs with application logs;
- propagate request IDs to backend services;
- return the request ID to clients for debugging;
- standardize request tracing across services;
- avoid generating different IDs in every layer.
Request:
GET / HTTP/1.1
Host: app.example.com
X-Request-ID: client-123The plugin keeps the existing value.
Forwarded request to backend:
X-Request-ID: client-123Response to client:
X-Request-ID: client-123Request:
GET / HTTP/1.1
Host: app.example.comThe plugin generates a UUID v7.
Forwarded request to backend:
X-Request-ID: 018f8f2e-7c3b-7cc2-9f1a-2d0f3c6d9e21Response to client:
X-Request-ID: 018f8f2e-7c3b-7cc2-9f1a-2d0f3c6d9e21- Adds
X-Request-IDto incoming requests when missing. - Preserves existing request IDs.
- Adds the same request ID to response headers.
- Supports custom header names.
- Uses UUID v7 for generated IDs.
- Works as a Traefik HTTP middleware plugin.
Add the plugin to your Traefik static configuration.
experimental:
plugins:
requestid:
moduleName: github.com/code-chat-br/traefik-request-id
version: v0.1.0For local development:
experimental:
localPlugins:
requestid:
moduleName: github.com/code-chat-br/traefik-request-idhttp:
middlewares:
request-id:
plugin:
requestid:
headerName: X-Request-IDThen attach the middleware to a router:
http:
routers:
app:
rule: Host(`app.example.com`)
entryPoints:
- websecure
service: app-service
middlewares:
- request-id
services:
app-service:
loadBalancer:
servers:
- url: http://app:3000services:
app:
image: your-app:latest
labels:
- traefik.enable=true
- traefik.http.routers.app.rule=Host(`app.example.com`)
- traefik.http.routers.app.entrypoints=websecure
- traefik.http.routers.app.service=app-service
- traefik.http.routers.app.middlewares=request-id
- traefik.http.services.app-service.loadbalancer.server.port=3000
- traefik.http.middlewares.request-id.plugin.requestid.headerName=X-Request-ID| Option | Type | Default | Description |
|---|---|---|---|
headerName |
string | X-Request-ID |
Header name used to read, inject, and return the request ID. |
http:
middlewares:
request-id:
plugin:
requestid:
headerName: X-Correlation-IDRequest without header:
curl -i https://app.example.comExpected response:
X-Correlation-ID: 018f8f2e-7c3b-7cc2-9f1a-2d0f3c6d9e21curl -i https://app.example.comExpected:
X-Request-ID: <generated-uuid-v7>curl -i \
-H "X-Request-ID: test-123" \
https://app.example.comExpected:
X-Request-ID: test-123Example folder structure:
plugins-local/
└── src/
└── github.com/
└── code-chat-br/
└── traefik-request-id/
├── go.mod
├── go.sum
├── requestid.go
└── .traefik.ymlTraefik static configuration:
experimental:
localPlugins:
requestid:
moduleName: github.com/code-chat-br/traefik-request-idDocker Compose example:
services:
traefik:
image: traefik:v3.6.7
command:
- --configFile=/etc/traefik/traefik.yml
volumes:
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./plugins-local:/plugins-local
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- public
networks:
public:
external: trueExample .traefik.yml:
displayName: Request ID Middleware
type: middleware
import: github.com/code-chat-br/traefik-request-id
summary: Adds or propagates X-Request-ID in request and response headers.
testData:
headerName: X-Request-IDTo get the full benefit of this plugin, your backend application should read the request ID header and include it in logs.
Example in Node.js / Express:
app.use((req, res, next) => {
const requestId = req.headers['x-request-id']
req.requestId = requestId
res.setHeader('X-Request-ID', requestId)
next()
})Example log:
{
"level": "info",
"request_id": "018f8f2e-7c3b-7cc2-9f1a-2d0f3c6d9e21",
"message": "request processed"
}This plugin is useful for request correlation.
It is not a full distributed tracing solution.
For complete tracing across services, use OpenTelemetry and the traceparent header.
Recommended usage:
- Use
X-Request-IDfor simple request correlation. - Use
traceparentfor distributed tracing. - Use both when you need simple debugging plus full observability.
This plugin preserves an incoming request ID if the client sends one.
That is useful when clients or upstream gateways already generate request IDs.
However, if you do not trust external clients, be careful when using client-provided IDs in logs or dashboards.
Do not treat X-Request-ID as an authentication, authorization, or security boundary.
This plugin is designed for Traefik HTTP routers and middlewares.
It does not apply to TCP or UDP routers.
MIT