Why do two users get different variations?

Last updated:

In a percentage rollout that is the expected behaviour. Each user is hashed together with the flag key to produce a bucket from 0 to 100, so a 30% rollout puts roughly three users in ten on the new variation. The same user always lands in the same bucket for the same flag. Different flags hash independently, so being in the 30% for one says nothing about another.

Two colleagues compare screens, see different things, and file a bug. Nine times out of ten the rollout is working exactly as configured.

What the split is doing

The user identifier and the flag key are hashed together, producing a number from 0 to 100. A 30% rollout serves the new variation to everyone below 30. Because the hash is deterministic, a user stays in the same bucket forever, across refreshes, sessions and devices.

That stability is the whole point. Nobody watches a feature appear and vanish between page loads.

Why your test accounts disagree

They hash differently. There is no pattern to it, and no way to reason about which side a given account will land on without checking.

Give yourself a deterministic answer instead: add a targeting rule above the rollout that serves your own account the variation you want to see. Rules run first and win, so the rollout never gets a say.

1. email endsWith "@yourcompany.com" -> serve true
2. Fallthrough: 30% rollout

Now internal accounts always see the new path and the percentage still governs everyone else.

Why the same user differs across two flags

Different flags produce different hashes for the same person. If they did not, every rollout at the same percentage would hit exactly the same users, and a customer unlucky enough to sit at bucket 2 would be the guinea pig for everything you ship.

Independent hashing spreads that risk. It also means you cannot line up two rollouts by setting both to 30%.

When it really is wrong

Two cases are worth ruling out.

No identifier. Without a stable key there is nothing to hash. A server SDK evaluating locally falls back to the control variation, and the hosted endpoint spreads traffic with no stickiness at all, which does produce a user seeing different values on consecutive requests. That case has its own answer.

A changing identifier. If you pass a session ID rather than a user ID, the bucket moves whenever the session rotates. Anything you hash on has to outlive the rollout.

Widening the rollout

Going from 30% to 50% widens the window. Everyone already inside stays inside, and only new users are added, so nobody loses a feature they had yesterday.

Hashing and rollout mechanics are documented in Rollout strategies.

Still stuck?

The docs cover every SDK, and the free Solo plan is enough to reproduce most of these locally.