Server Timing in the Wild

How we expose web performance in iPlayer

Server-Timing data for /iplayer in Chrome
Server-Timing headers from /iplayer
Performance Timing API Data

How we did it

In iPlayer, we use Express and Node.js (for more information about our tech you can read an excellent post by Richard Wong), so we implemented this as a middleware. To start with we used the high resolution timer available in Node.js:

const startTime = process.hrtime();
const timeDifference = process.hrtime(startTime);
function convertToMs(hrtime) {
const ms = hrtime[0] * 1e3 + hrtime[1] * 1e-6;
return ms.toFixed(3);
}
const onHeaders = require('on-headers'); function convertToMs(hrtime) {
const ms = hrtime[0] * 1e3 + hrtime[1] * 1e-6;
return ms.toFixed(3);
}
module.exports = function serverTiming(req, res, next) {
const startTime = process.hrtime();
onHeaders(res, () => {
const timeDifference = process.hrtime(startTime);
const timeDifferenceMs = convertToMs(timeDifference);
res.append('server-timing', `total;dur=${timeDifferenceMs}`);
});
next();
};

Taking this a bit further

We extended upon this idea a little bit by having two maps that contained our runningTimers and finishedTimers so that we could easily add more timings if necessary as well. These were accessible using two methods added to the res object as serverTimingStart and serverTimingEnd which meant we could measure any piece of code we wanted such as:

res.serverTimingStart('data');
const data = await dataProcessing();
res.serverTimingEnd('data');
express.use(timing((req, key, value) => {
sendMyStats(req.url, key, value);
}));

If you’re interested in quickly adding Server-Timing to your express app, try out the express-simple-timing module!

But there are so many other fun uses

If you have a cached response it’s still useful to see how long it took for your server to prepare it so you know how long that poor person without a cached response had to wait.

Server-Timing with Cache information
vcl 4.0;
import header;
sub vcl_deliver {
if (obj.hits > 0) {
header.append(resp.http.server-timing, "hit");
} else {
header.append(resp.http.server-timing, "miss");
}
}
add_header server-timing $upstream_cache_status;
Server Timing description in Chrome Dev Tools

Final Thoughts

Taking some time to add these headers into your application and caching layers means that developers can easily see why server responses are slowing down. Further headers can be added at multiple points in the chain to further inform as to where your requests are being routed and what is taking that vital time to first byte.

Join us

If you’re interested and excited by what we’ve talked about here, then you might be interested in our joining our Web team. We’re always looking for driven engineers to join us.

BBC Design + Engineering

BBC D+E. Building the best BBC products, platforms and services for audiences in the UK and around the world

Thanks to Richard (Kit) Wong.

Christopher Sidebottom

Written by

Development Lead on the iPlayer Website

BBC Design + Engineering

BBC D+E. Building the best BBC products, platforms and services for audiences in the UK and around the world