How Is Server-Timing used on the web?

I was curious to see where Server-Timing was implemented on the web, so I started searching the HTTP Archive for sites using it. Interestingly enough, there were no sites in the HTTP Archive that had Server-Timing response headers before 3/1/2017. Since then it’s usage has been gradually increasing each month. As of July 2017, there are 72 sites and 352 HTTP responses containing Server-Timing headers.

Here’s a query that I wrote to find a list of sites with Server-Timing headers. You can run it on BigQuery here :

    SELECT p.url, p.rank, count(*) as freq
      ( SELECT pageid, url, rank 
        FROM [httparchive:runs.latest_pages] 
      ) p
      ( SELECT pageid,url,respOtherHeaders 
        FROM [httparchive:runs.latest_requests] 
        WHERE LOWER(respOtherHeaders) CONTAINS "server-timing"
      ) r
    ON p.pageid = r.pageid
    GROUP BY p.url, p.rank
    ORDER BY freq DESC

Next I was curious to see the actual Server-Timing headers to understand how they are being used. I wrote this query to strip out the server-timing headers from the respOtherHeaders column. The query has a lot of string manipulations to extract the text. I’ve added some comments to the query to help make it easier to follow -

    SELECT HOST(url), status, mimeType,
    IF (
        -- In respOtherHeaders, remove everything to the left of the server-timing header.   Is there a ; in the remaining string?
        RIGHT(respOtherHeaders,LENGTH(respOtherHeaders)-INSTR(LOWER(respOtherHeaders),"server-timing")+1) CONTAINS ";",
        -- Then strip out everything to the left of the server-timing header and everything to the right of the ";" character.
        -- If there are no ; chars, then the respOtherHeaders column ends with server-timing.  Remove everything to the left of server-timing
    ) as ServerTimingHeader
    FROM [httparchive:runs.latest_requests] 
    WHERE LOWER(respOtherHeaders) CONTAINS "server-timing"

You can see it on BigQuery here

Looking at the Server-Timing headers, I can see 3 different types of data being sent in these headers:

Timing Metrics (such as application time, gateway time, image resize time, etc)

Server-Timing = app=133.99219512939;
Server-Timing = gateway-time=25;
Server-Timing = resizer=0.015;
server-timing = view=2.188, db=0.000, total=61.743, x-runtime = 0.069661, x-ua-compatible = ie=edge,chrome=1, x-frame-options = SAMEORIGIN
Server-Timing = app=53.393840789795;

Caching Information

server-timing = hit, cf-cache-status = HIT
server-timing = cold, cf-cache-status = MISS
server-timing = hit, cf-cache-status = HIT
server-timing = cold, cf-cache-status = MISS


server-timing = ibs_5318e9209631=1
server-timing = ibs_1964fd84c9cea3=1
server-timing = ibs_1880bf4b0f6311=1

Looking at all of the data in the 7/1/2017 tables, I can see that the current examples in the wild are split between these 3 types of data, although the caching ones are mostly on images, the informational ones are set on JS and responses w/ no content (ie, 204s -likely beacon responses), and the actual timing metrics are spread across a wide range of content.

It’ll be interesting to see how this evolves as Server-Timing adoption increases over time.

Originally published at

© 2022 Paul Calvano. All rights reserved.

Powered by Hydejack v9.0.2