python 30 lines · 5 steps

Timing requests with Flask hooks

Two request lifecycle hooks measure how long each request takes and attach the result as response headers.

Explained by highlit
1import time
2 
3from flask import Flask, g, request
4 
5app = Flask(__name__)
6 
7 
8@app.before_request
9def start_timer():
10 g.request_start = time.perf_counter()
11 
12 
13@app.after_request
14def add_timing_header(response):
15 start = g.get("request_start")
16 if start is None:
17 return response
18 
19 elapsed_ms = (time.perf_counter() - start) * 1000
20 response.headers["X-Response-Time"] = f"{elapsed_ms:.2f}ms"
21 response.headers["Server-Timing"] = f"app;dur={elapsed_ms:.2f}"
22 
23 app.logger.info(
24 "%s %s -> %s in %.2fms",
25 request.method,
26 request.path,
27 response.status_code,
28 elapsed_ms,
29 )
30 return response
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Flask's request-scoped `g` object is the natural place to stash per-request state between hooks.
  2. 2`before_request` and `after_request` let you wrap logic around every request without touching individual view functions.
  3. 3Emitting `Server-Timing` headers surfaces backend latency directly in browser devtools.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Timing requests with Flask hooks — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code