Request ID
The Request ID middleware adds unique identifiers to each request, enabling distributed tracing, audit logging, and request correlation across services.
Quick Start
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
const app = new TabiApp();
// Add request IDs (generates UUIDs by default)
app.use(requestId());
app.get("/api/users", (c) => {
const id = c.get("requestId");
console.log(`Processing request ${id}`);
return c.json({ users: [] });
});
Deno.serve(app.handler);How It Works
The middleware generates or reuses a request ID for each incoming request. The ID is stored in the context and added to the response headers. If a client provides a request ID via the header, it is reused for distributed tracing.
Options
| Option | Type | Default | Description |
|---|---|---|---|
generator |
() => string |
crypto.randomUUID() |
Function to generate request IDs |
headerName |
string |
"X-Request-ID" |
Header name for request ID |
Examples
Custom Header Name
Use a different header name:
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
const app = new TabiApp();
app.use(
requestId({
headerName: "X-Trace-ID",
}),
);Custom ID Generator
Generate IDs in a custom format:
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
let counter = 0;
const app = new TabiApp();
app.use(
requestId({
generator: () => `req-${Date.now()}-${++counter}`,
}),
);Client-Provided IDs
The middleware automatically reuses request IDs provided by clients:
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
const app = new TabiApp();
app.use(requestId());
// Client sends: X-Request-ID: abc123
// Server reuses: abc123
// Context: c.get("requestId") === "abc123"
// Response header: X-Request-ID: abc123Logging Integration
Use request IDs in your logging:
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
const app = new TabiApp();
app.use(requestId());
app.get("/api/users", async (c) => {
const id = c.get("requestId");
console.log(`[${id}] Fetching users`);
const users = await db.getUsers();
console.log(`[${id}] Returning ${users.length} users`);
return c.json(users);
});Accessing in Handlers
Access the request ID from context:
import { TabiApp } from "@tabirun/app";
import { requestId } from "@tabirun/app/request-id";
const app = new TabiApp();
app.use(requestId());
app.get("/api/data", (c) => {
const id = c.get("requestId");
return c.json({
data: "value",
requestId: id,
});
});Security Benefits
- Audit Trails: Correlate security events across requests
- Incident Response: Track malicious activity through request IDs
- Rate Limiting: Identify and block abusive clients
- Compliance: Meet logging requirements for regulated industries
Notes
- Request IDs are available in context via
c.get("requestId") - IDs are added to response headers for client-side correlation
- If client provides a request ID, it is reused (enabling distributed tracing)
- Generated IDs are UUIDs by default (RFC 4122 compliant)
- Should be applied early in middleware chain for consistent availability
- Useful for:
- Distributed tracing across microservices
- Correlating logs across multiple systems
- Security incident investigation
- Debugging production issues
- Rate limiting and abuse detection
Related
- Middleware System - How middleware works
- TabiContext - Accessing context data