Get the API spec
← All posts Architecture Published

Where should your A/B tests actually run?

By · · 11 min read

Three architecture lanes: fragile client-side, boxed server-side, and a clean API-first conduit

The JavaScript snippet that made A/B testing accessible is now its biggest liability: it flickers, it gets blocked, and it can only touch what the browser renders. This post maps the three architectures, what each can test, and the measurement error each one carries.

01Client-side snippets and their decay

A client-side JS snippet works by letting the browser paint the control page first, then mutating the DOM once the experiment script loads. To hide that flash of original content, most tools hide the page behind an anti-flicker rule, typically opacity: 0, until the script finishes or a timeout fires. Chromium's own guidance describes this pattern and recommends keeping render-blocking experiment code under 100ms, with anti-flicker timeouts commonly defaulting to around four seconds. Kameleoon's SSR implementation for Nuxt documents a 750ms timeout for the same mechanism. In other words, the fix for flicker is itself a rendering-path delay, and vendors' own documentation is candid about the size of it.

There's no clean public number for "flicker alone costs X% conversion": that causal isolation doesn't exist in the primary literature. What is measured is the latency tax the workaround imposes. DebugBear documented a real case where an anti-flicker rule kept a page's body invisible until 6.0 seconds, even though the last render-blocking request had already finished around 2.9 seconds; removing the hiding rule brought Largest Contentful Paint back down to 2.7 seconds. That's a 3.3-second penalty from the anti-flicker mechanism itself, not from the experiment's actual payload. And speed at that scale is not a rounding error commercially: Deloitte's "Milliseconds Make Millions" study found a 0.1-second mobile speed improvement correlated with 8.4% higher conversion in retail and 10.1% in travel; Akamai's research puts a 100ms delay at up to a 7% conversion hit. A four-second anti-flicker window sits well inside the range where these studies say business metrics move.

Snippets are also increasingly fighting the browser itself, not just the render path. eyeo's 2026 report estimates 1.1 billion ad-blocking users worldwide, about 30% of the internet population, and EasyPrivacy (one of the most widely deployed filter lists) explicitly targets analytics, telemetry, beacons, fingerprinting, event/pageview logging, CNAME-cloaked trackers, and known tracking scripts by name. Safari adds a second front: it held 15.31% global browser share and 50.06% of U.S. mobile share as of June 2026, and WebKit's tracking prevention blocks third-party cookies by default, partitions third-party storage, and caps some first-party JavaScript-set or CNAME-cloaked cookies at seven days. Optimizely's own docs note that Web Experimentation cookies set via document.cookie are affected by ITP 2.1 and recommend server/CDN-side cookie creation instead. VWO documents the practical consequence: ITP can reset a visitor's cookies inside seven days, which resets them to "new," skews visitor counts, breaks funnels mid-experiment, and can even flip which variation a returning visitor sees.

Consent infrastructure compounds this. Storing a visitor ID, assignment, or navigation history in a cookie or browser storage (the pattern documented by AB Tasty, Optimizely Web, VWO, GrowthBook, and Convert) is exactly the kind of non-essential storage that regimes like the UK ICO's PECR guidance require active consent for. A rejected or unloaded consent banner is functionally the same failure mode as an ad blocker: the experiment never ran, and depending on the tool, the page may still be sitting behind an anti-flicker rule that never resolves.

02Server-side testing

Server-side experimentation moves the decision earlier: assignment happens at the origin, reverse proxy, or edge, and the browser receives HTML that already reflects the chosen variant. There is no DOM mutation after paint and, done correctly, no anti-flicker rule needed at all: the flicker problem doesn't get solved, it gets removed from the critical path. SiteSpect built its whole architecture around this as a reverse-proxy engine rather than a tag or SDK. Dynamic Yield's Experience APIs are described in its own docs as reducing script impact on page load time specifically because the decision is server-side. Optimizely's Feature Experimentation server-side SDKs decide before content is delivered to the client, same idea from a different vendor.

This is also the only architecture that can honestly test things a snippet never touches: pricing logic, ranking and recommendation algorithms, search relevance, checkout flow branching, in short, anything that lives in backend code rather than rendered markup. A client-side tool can swap a button color; it cannot A/B test which discount algorithm ran, because that decision was already made before the response left the server.

The tradeoff is real: this is the highest-complexity option of the three. It requires application, backend, and often edge integration; templating that can serve multiple variants cleanly; and event logging that dedupes conversions against server-side assignments rather than client-side beacons. That integration cost is precisely why server-side testing has stayed the domain of engineering teams rather than marketers with a visual editor: there's no equivalent of "paste a snippet in the head tag" when the variant has to be decided before the response is even generated.

03API-first as a third category

The useful distinction inside "API-first" isn't API-first versus server-side: it's local evaluation versus remote evaluation. LaunchDarkly's server and edge SDKs evaluate flags in-memory against embedded rules, with no round-trip per check; its client-side SDKs, by contrast, call out to LaunchDarkly's backend. Eppo downloads a config file from its CDN once, caches it, and evaluates locally from then on, with no further network requests per evaluation. GrowthBook supports both modes and is explicit that remote evaluation adds a network request per check and loses cacheability, while local evaluation doesn't. Amplitude publishes sub-millisecond local-evaluation numbers, in the range of 0.007–0.098ms, across its JVM, Node, and Go server SDKs. The pattern across all of them: local/edge evaluation behaves like server-side testing: fast, no client round-trip, decision made before or alongside render; remote client-side evaluation reintroduces the same latency and browser-dependency problems as a snippet.

What makes this a genuine third category rather than a rebrand of server-side testing is the integration shape: assignment becomes a service any surface can call, not a script tied to one rendering context. A snippet only runs where a browser executes JavaScript. An API-first assignment call is just as usable from a server rendering a webpage, a backend deciding what an email or SMS says, an ad-serving pipeline choosing creative, or a mobile app deciding which onboarding flow to show, the same one assignment held consistently across every channel a user touches, because the call is a request/response pair, not a DOM mutation. Rendering stays wherever the caller already lives: your CMS renders its own templates, your ESP renders its own email, your ad platform renders its own creative. The experimentation layer doesn't need write access to any of them.

TraqLyte is built exactly to this shape and is a concrete instance of the pattern rather than a hypothetical: the entire integration surface is two endpoints, POST /assign to get a cohort back for a user, and POST /outcome to record what happened. Neither endpoint renders anything or requires a browser. A web page calls /assign server-side before it builds its response; an email send job calls it before composing a template; an ads pipeline calls it before selecting creative. The variant lives in whatever system already owns rendering for that surface, which is the same principle described above, just with a specific two-call shape instead of a broader SDK.

04A vendor landscape by architecture

Three architecture lanes compared: client-side, server-side, and API-first
Same three architectures, viewed as one comparison rather than three separate pitches.

Most vendors don't sit cleanly in one bucket anymore (many product lines span two), but each has a documented primary or flagship mode. For a broader rundown of the 2026 experimentation vendor landscape, see our separate comparison; sorting by primary mode here:

Bucket Representative vendors
Client-side snippet Optimizely Web Experimentation, VWO/Wingify Testing (SmartCode), AB Tasty Web Experimentation, Convert Web Testing, Kameleoon Web Experimentation, and most default Adobe Target / Dynamic Yield web implementations.
Server-side SiteSpect (reverse-proxy engine, the purest example), plus Adobe Target's Delivery API, Dynamic Yield's Experience APIs, Kameleoon's edge/server kits, and Convert Fullstack.
API-first LaunchDarkly, Statsig, Eppo, GrowthBook, Amplitude Experiment, Firebase A/B Testing / Remote Config, Harness Feature Management & Experimentation, PostHog, Unleash, Flagsmith, and Optimizely Feature Experimentation.

A few products deliberately straddle categories and are worth naming rather than forcing into one row. Adobe Target ships both at.js/Web SDK for browser rendering and a Delivery API for server-side use. Convert explicitly separates "Web Testing" from "Fullstack" as two different products. Kameleoon runs anti-flicker web experimentation alongside edge starter kits. Optimizely's Feature Experimentation line supports server-side, client-side, and edge SDKs under one product. None of that is inconsistency on the vendors' part: it reflects that the market has converged on the same conclusion this piece argues: the architecture question is separable from the vendor brand.

Before migrating off a snippet, the questions worth asking a vendor are the ones the mechanics above point to directly: does assignment happen before or after first paint; is evaluation local/edge or a remote round-trip per check; where do visitor IDs and event logs live, first-party or third-party; and what happens to a returning visitor when Safari expires their cookie or a filter list blocks the script. A vendor's category label in its own marketing is less reliable than the answer to those four questions.

Sources

Run experiments your whole stack can call.

Get the API spec

Free SEO & AI-readiness audit

Check your security headers, on-page SEO and AI-crawler readiness in about 30 seconds. No sign-up required.

Run my free audit