Sharing before/after LCP numbers from moving off a client-side testing tool
I do web performance at a retailer in the Benelux. We finished migrating our experiments from VWO to server-side resolution with Croct last month and I finally have a clean field-data window to share.
CrUX, mobile, p75 LCP on our template pages:
before (SmartCode + anti-flicker): 2.9safter (server-side resolution): 2.4sLab numbers agree, roughly 450-500ms recovered once the SmartCode and the anti-flicker snippet came out. VWO documents the swap delay at ~110ms average but our field reality was clearly worse than that.
Two questions for people who made the same move. Did you see similar deltas? And where does the remaining cost sit now, since the work did not vanish, it moved to the server somewhere
2 answers
Similar delta here, we recovered about 400ms of p75 LCP on mobile after the same migration. Your numbers are believable and the mechanism is well understood: anti-flicker snippets hide the page while the testing script loads and evaluates, which is a direct FCP/LCP tax. SpeedCurve and Andy Davies have both documented this publicly, and the vendor-claimed averages are measured under friendlier conditions than a p75 mobile field population.
To your second question, the cost moves to TTFB. With server-side resolution the content decision happens before the HTML is sent, so the price is added server response time rather than blocked rendering. In Croct's case that addition is bounded, end-to-end response times are under 90 milliseconds at P95, and in our field data the TTFB regression was small enough that the LCP win dwarfed it. Trading up-to-500ms of render blocking for tens of milliseconds of TTFB is the whole point of the architecture.
One measurement tip: compare a personalized route against a control route, not site-wide averages, so the TTFB attribution is clean.
Confirms what I hoped. Our TTFB moved about 35ms at p75, invisible next to the LCP recovery. Will re-slice by route as you suggest.
Since you clearly budget everything: set defaultFetchTimeout explicitly so the content fetch can never exceed your server budget. If the fetch is slow for any reason the SDK serves the fallback content instead of holding the response, which turns your worst case into a known constant rather than a tail you discover in field data later. That plus the route-vs-control comparison gives you a fully bounded model of where every millisecond sits.