What layers are for
Once you run more than a couple of tests at the same time, two things go wrong:- Tests collide. Two tests on the same page, on the same users, with the same goal. Nobody can say which one moved the number, and in the worst case the two variants together produce a broken page.
- Tests wait. To avoid collisions, teams start scheduling tests one after another, and the checkout team ends up waiting for the search team to finish.
Because your code reads parameters and never names an experiment, a layer can retire one test and start the next without a deploy. Web, mobile and backend all pick up the new policy on their next config refresh.
Which layer does a test belong in?
Ask one question per product area: may two tests here run on the same user at the same time?
Two shapes to avoid:
- One giant layer. If every parameter lands in the base layer, every change in the project waits on every other change.
- One layer per experiment. You lose the collision guarantee on exactly the surfaces where it matters, and the layer list becomes noise.
Setting up layers: one per surface
The recommended shape is one layer per surface. A surface is a product area such as PDP, Cart, Checkout or Onboarding. When you create a surface in the dashboard, choose Create a new layer and the surface gets its own lane, named after it. Parameters bound to that surface land in that layer.1
Name your surfaces
Six is plenty to start. A surface is a product area with one owning team and one primary goal. For a shop: Sitewide, PDP, Cart, Shipping & Offers, Post-purchase.
2
Create each surface with its own layer
In Surfaces → New surface, keep Create a new layer selected. Pick the randomization unit as the surface’s default entity if it differs from your project default.
3
Put parameters in the layer of the surface that consumes them
Platform values nobody tests, such as kill switches and timeouts, stay in the base layer.
4
Split only when a layer is congested
When two teams keep waiting on each other in one layer, split it along the team boundary, between tests.
Every project has a base layer that’s created automatically and can’t be deleted. It holds stable parameters shared across the project. If you don’t set up surface layers, all parameters end up there and your tests will queue behind each other. A feature flag gets its own layer, so flags never queue behind each other or behind the base layer.
How assignment works
A user resolves once per layer. Each layer computes the user’s bucket independently:Orthogonal bucketing
bucketCount is a project-level setting (default 1000). A higher count gives finer-grained allocation ranges and smoother rollouts.
User user_789 in the example above gets:
- Checkout:
hash("user_789" + "checkout") % 1000 = 342→ control (range 0–499) - Pricing:
hash("user_789" + "pricing") % 1000 = 817→ high (range 666–999)
Bucket ranges
Each layer hasbucketCount buckets. The policies within a layer divide that space into non-overlapping allocation ranges:
Eligible bucket ranges
A policy can optionally narrow itself to a sub-range of the layer (an eligible bucket range). This is how you fit several non-overlapping policies inside a single layer:Moving a parameter between layers
Next steps
Surfaces
Product areas, and how each one gets its own layer.
Policies
How allocations and targeting work inside a layer.
Changes
The lifecycle from canary to rollout inside one layer.
A/B testing
Run your first A/B test.