Field data shows that most back navigations on your site are not being served from the browser's back/forward cache. How would you find out what is blocking them, and how would you decide which fix to ship first?
answer
- lab for the loop, field for the truth
- DevTools panel tests one page only
- field reasons are Chromium-only
- group blockers by who owns the fix
- one shared blocker masks all the rest
basics
~20 sCollect blocking reasons from lab and field — Chrome DevTools' Back/forward cache panel tests one page on demand, Chromium's notRestoredReasons reports real navigations — then rank fixes by how much traffic each unblocks, starting with shared headers and shared code.
solid answer
~50 sI would audit in two places, because they answer different questions. In the lab, Chrome DevTools has a Back/forward cache panel in the Application tab that navigates away and back and tells you whether that page was restored and, if not, why; Lighthouse reports a back/forward cache audit too. That is fast per page but only covers the pages and conditions you happened to test. In the field, Chromium exposes `notRestoredReasons` on the navigation timing entry, so a RUM sample tells you the real distribution of blockers across templates, browsers and traffic. Then I prioritize by breadth rather than by how interesting the blocker is: a response header or a listener in a shared layout can hold the whole site at a near-zero restore rate, so one change flips everything, while a blocker confined to one low-traffic template is a smaller win than it looks. I would re-measure the field ratio after each change rather than trusting the lab result.
go deeper
Know that Chrome DevTools can test one page's back/forward cache eligibility on demand and report why it failed, and that this is a per-page check rather than a sitewide answer.
Explain why lab and field disagree: the lab tests whatever state your profile happens to be in, while field reporting shows which blockers real users hit, on which templates and in which browser.
Demonstrate the prioritization — weight each blocker by the traffic it affects, clear the widest one first because eligibility is binary and one blocker hides the rest, then verify with the field ratio.
Own the fact that eligibility regresses silently and costs nothing to lose, so the deliverable is a guard — synthetic checks per template and an alert on the field ratio — not a one-off cleanup.
## Two sources of truth, used for different jobs Auditing back/forward cache eligibility fails when a team uses only one instrument. The **lab** instrument is Chrome DevTools' Back/forward cache panel, in the Application tab: it drives a navigation away from the current page and back, then reports whether the page was restored and lists the reasons it was not. Lighthouse also runs a back/forward cache audit. Both are excellent for a tight loop — change something, re-test, watch the reason disappear — and both are limited in the same way: they test the page you are sitting on, in one browser, in one state, usually logged out and with consent banners and experiment flags in whatever state your dev profile happens to have. The **field** instrument is `notRestoredReasons`, exposed by Chromium on the `PerformanceNavigationTiming` entry, which reports the reasons a document was not restored. Sampled through your RUM pipeline, it gives you what the lab cannot: which blockers actually occur, on which templates, for what share of real navigations. Note the coverage caveat — this is a Chromium-only signal as of 2025, so it describes Chromium users, and you should say so when you present the number. A third input is cheap and often skipped: your own analytics. Before spending on any of this, find out which templates receive back navigations at all. A blocker on a page nobody navigates back to is not a bug worth a sprint. ## Group the reasons by who owns the fix Raw reason strings are not a plan. What makes the list actionable is sorting it by owner, because the owner determines both the cost and the blast radius of the fix: - **A response header or edge configuration.** The classic case is a document response that tells browsers not to store it at all; that is set once, usually in a shared server or CDN config, and it disqualifies every page it covers. One change, sitewide effect — and it needs a conversation with whoever set it, since it may have been deliberate. - **Shared application code.** A listener or an open connection created in a root layout, an analytics wrapper, or a shared component applies to every route. Same shape of win, usually a small diff. - **A single feature or template.** A live-updating widget on one page. The fix is local and the payoff is bounded by that page's share of back navigations. - **A third-party tag.** You often cannot change the code at all. The options are removing it, gating it by route or consent, upgrading it, or accepting the loss — which makes it a negotiation with whoever owns the tag, not an engineering ticket. ## Rank by traffic, not by tidiness The ranking rule is expected restored navigations gained per unit of effort. Concretely: weight each blocker by the share of back navigations that hit it, then break ties toward the change with the widest scope and the least product risk. That usually puts the shared header or shared-layout fix first even when a more exotic blocker looks more interesting. Eligibility is binary per page load, so a single sitewide blocker masks every other one beneath it — until you clear it you cannot even tell how good the rest of the site is. Clear the top blocker, re-measure, and expect the distribution underneath to differ from what you predicted. A second-order consideration belongs in the ranking too: the product cost of the page coming back. Restoring a page means restoring its data as it was. If a template shows a cart total, a live price, or anything an authorization change should invalidate, making it eligible is not finished until it also refreshes on restore. That work is part of the estimate, and occasionally it is the reason to leave a page ineligible on purpose. ## Verify in the field The lab tells you a reason went away; only the field tells you the restore rate moved. Re-measure the ratio of restored back navigations to all back navigations after each change, segmented by template, and hold it — because eligibility regresses invisibly. Nothing breaks, no test fails, no error is logged; someone adds a listener or a header and the number quietly drops. That is why the audit should end in a guard: a synthetic check per key template in CI, plus an alert on the field ratio, so the next regression is caught by a build rather than by next year's audit.
- The biggest blocker turns out to come from a third-party tag your marketing team requires. What do you do?Treat it as a negotiation, not a ticket. I would quantify the loss — how many back navigations on which templates stop being instant — and put that against what the tag is worth. Then look for middle ground: gate it by route or consent, ask the vendor for a fixed version, or move it to a loading mode that does not block. If the tag stays, I record the decision so it is not re-opened every quarter.
- You clear the top blocker and the field restore rate barely moves. What is the likely reason?Eligibility is all-or-nothing per page load, so a second blocker underneath the first was hiding. Until the top one was removed, the pages never got far enough for anything else to matter. Re-run the audit against the new state rather than assuming the first diagnosis was wrong — the distribution of reasons after a sitewide fix rarely matches the one before it.
- Why is a Lighthouse or DevTools result on your laptop a weak basis for a sitewide claim?It measures one page, in one browser, in one profile state — typically logged out, with no consent banner accepted and no experiment flags applied. Real users hit different templates in different states, and the blockers that dominate the field are often the ones a dev profile never triggers. Lab tests are for the fix loop; the field distribution is the claim.
saying these in an interview costs you the question
- Audits one page in DevTools and calls it a sitewide result
- Ranks blockers by how interesting they are rather than by traffic
- Assumes every blocker is fixable in your own code
- Ships eligibility for a page with live data and no refresh path
- Treats a fixed blocker as permanent with no regression guard