Collecting Custom Data from your CDN
Getting visibility into the edge using server-timing headers
The use of a content delivery network (CDN) remains one of the most effective tools for improving your page performance. However, visibility into the inner workings or your CDN has not always been easy. Thankfully, most CDNs allow you to take advantage of server-timing headers as a way of understanding what's going on inside the black box. Here are some examples of what can be exposed by mainstream CDNs with relative ease.
Some of the more common use cases:
- Cache status: Was the basepage served from the CDN (HIT) or did the request get routed to origin (MISS)
- POP/Edge node: What datacenter was the request served from?
- Edge time: How much elapsed time was spent on the CDN (edge)?
- Origin time: How much elapsed time in ms was spent at the origin?
- Round trip time (RTT): How long did it take the CDN to respond to the browser?
- Request ID
Akamai
Akamai was the first CDN to expose server-timing headers out of the box for their customers. This data is available by enabling the mPulse behavior in property manager. With the behavior enabled, you will start seeing the following server-timing headers:
Server-Timing: cdn-cache; desc=<MISS|HIT>
Cache HIT/MISS from CDN. This would be best defined as a dimension.
Server-Timing: edge; dur=<# ms>
Time spent at the edge (CDN). Best defined as a timing metric.
Server-Timing: origin; dur=<# ms>
Time spent fetching from origin. Best defined as a timing metric.
Also, note that if you don't use the mPulse product you can still enable the headers without the snippet by modifying property settings. Another option would be using EdgeWorkers to add the headers to the request, similar to the example shown next.
Cloudflare
Using Cloudflare Workers, you can add values from existing headers such as CF-Cache-Status
into server-timing headers. Other possible use cases are parsing the datacenter location from the CF-Ray
header.
Here is an example:
/**
* @param {Response} response
* @returns {Response}
*/
function addServerTimingHeaders(response, startTime) {
const serverTiming = [];
const cfCache = response.headers.get('cf-cache-status');
if (cfCache) {
serverTiming.push(`cf_cache;desc=${cfCache}`);
}
serverTiming.push(`worker;dur=${Date.now() - startTime}`);
response.headers.set('Server-Timing', serverTiming.join(', '));
}
Fastly
While you could likely use Compute@Edge to add server-timing headers via Fastly, using VCL is pretty straightforward as discussed in this post
TL;DR
To get the following:
Server-Timing: time-start-msec;dur=1544705663920,time-elapsed;dur=0,fastly-pop;desc=LCY,hit-state;desc=HIT
Use the following VCL:
set resp.http.Server-Timing = "time-start-msec;dur=" time.start.msec ",time-elapsed;dur=" time.elapsed.msec ",fastly-pop;desc=" server.datacenter ",hit-state;desc=" fastly_info.state;
There are a lot of VCL variables available that might be interesting candidates for custom data.
Cloudfront
You can add server-timing headers via opt-in via the AWS Console as mentioned in this post. Here is an example of server-timing headers provided with this opt-in taken from https://www.perfwork.com/
server-timing: cdn-upstream-layer;desc="EDGE",cdn-upstream-dns;dur=0,cdn-upstream-connect;dur=69,cdn-upstream-fbl;dur=562,cdn-cache-miss,cdn-pop;desc="DEN52-P3",cdn-rid;desc="5McHcGf1pCMEZKUtTuHH-UI7Co2qq-817CJu_cD7oVUo9BmxBtpIHQ==",cdn-downstream-fbl;dur=563
Shopify
Shopify provides the following server-timing headers for all Shopify sites. It's important to note that these are not considered public, so use at your own risk.
server-timing: processing;dur=15, db;dur=5, asn;desc="7922", edge;desc="DFW", country;desc="US", theme;desc="Prestige", pageType;desc="index", servedBy;desc="8jlx", requestID;desc="4ab33c3d-21e6-425a-9754-a6f42a27d36f"
server-timing: cfRequestDuration;dur=48.999786, earlyhints
As of the writing of this article, our understanding of each of the headers is as follows:
Timings:
cfRequestDuration
= Duration from the time the request hits Cloudflare (CDN) until it is finished processing.
processing
= Duration from the time the request reaches the Storefront until processing of the request is complete.
db
= Duration of the request processing spent querying the database. (Subset of processing time)
Dimensions
asn
= Autonomous System Number
edge
= Location of CDN edge server
country
= Country of CDN edge server
theme
= Shopify theme used
pageType
= page identifier
servedBy
= ??
requestID
= ??
earlyhints
= Were early hints used for the request (if present, assume yes)
Updated 10 months ago