Server-Timing
Deserve has no Server-Timing middleware. The duration it would report is already measured by the lifecycle events, and emitting the header is a single line when a route wants it.
Why It Is Not Built In
The Server-Timing header surfaces server-side metrics in browser DevTools, so a request shows how long a stage took. A middleware that adds it for every response makes two assumptions for the whole app at once, which metrics to expose and to whom.
Those metrics are a detail of a single handler, not a framework-wide policy. One route times a database call, another times a render, and a public endpoint may not want to reveal timing at all. So the decision is to leave the header to the route that knows what is worth measuring, and to keep the measurement where it already lives.
The Duration Is Already Measured
Every request:complete event carries durationMs, the measured time for the whole request, alongside the route and method. For dashboards and logs that is the number to read, with no header and no per-route code. See Request Logging for turning it into a log line.
router.on((event) => {
// Read the measured request duration
if (event.kind === 'request:complete') {
const { route, durationMs } = event.metadata as { route?: string, durationMs: number }
console.log(`${route ?? 'unknown'} took ${Math.round(durationMs)}ms`)
}
})
await router.serve(8000)Emitting the Header When Wanted
For a route that does want the metric in DevTools, the header is one ctx.setHeader call. Time the work, then write a Server-Timing entry with a name and the duration in milliseconds.
export async function GET(ctx: Context): Promise<Response> {
// Time the work this route cares about
const start = performance.now()
const data = await loadData()
const ms = (performance.now() - start).toFixed(1)
// Expose it to DevTools for this route
ctx.setHeader('Server-Timing', `db;dur=${ms}`)
return ctx.send.json(data)
}
declare function loadData(): Promise<unknown>The header names the stage that matters for this route, which is more useful than a blanket number the framework would have to guess at. For tracing a request across services instead of timing one stage, see Distributed Tracing.