Abrova
☰ Docs menu · Multivariate
Coming soon. Abrova Flags is coming soon. This page describes how it will work; it can’t be used yet.

Multivariate Flags

Multivariate flags go beyond on/off toggles. Define weighted variants to serve different values, configurations, or UI experiences to different user segments.

Last updated: 27 Oct 2026
Multivariate Flags.

Multivariate flags go beyond simple on/off toggles. Define weighted variants to serve different values, configurations, or UI experiences to different user segments.

Defining Variants#

Each variant has a key, a value, and a weight (percentage). Weights must sum to 100 (Abrova Console enforces this). All values of one flag have the flag's type: string, number, json or boolean.

json
{
  "variants": [
    { "key": "control", "value": "old_checkout", "weight": 80 },
    { "key": "variant_a", "value": "new_checkout", "weight": 15 },
    { "key": "variant_b", "value": "minimal_checkout", "weight": 5 }
  ]
}

How Variant Selection Works#

Variant selection is deterministic. Abrova Flags uses deterministic hashing into 10,000 buckets (0 to 9,999) and walks the variants in order by weight. This ensures each user always gets the same variant, in every SDK.

text
bucket = deterministic hash of the user → 0 … 9999

Variants: control (80%) | variant_a (15%) | variant_b (5%)
Ranges:   0-7999        | 8000-9499       | 9500-9999

If bucket = 4200  → control (old_checkout)
If bucket = 8500  → variant_a (new_checkout)
If bucket = 9700  → variant_b (minimal_checkout)
  • The id is the user id, or the anonymous id when no user is signed in. A user who signs in is placed again by their user id.
  • The variant bucket is independent of the rollout bucket of the same flag.
  • A user only gets a variant when the flag is on for them. Otherwise the flag's off value is served and variant is empty.
  • Without any id, a split cannot be decided: the flag is served off with reason NO_BUCKETING_ID. Client SDKs always send an anonymous id, so this only happens on a server when you pass neither userId nor anonymousId.

Using Variants in Code#

Typed getter — get the variant value

typescript
// Client SDKs
const checkoutFlow = flags.getString('checkout_flow', 'old_checkout');
// Returns: 'old_checkout', 'new_checkout', or 'minimal_checkout'

// Server SDKs: pass the context
const checkoutFlow = flags.getString('checkout_flow', { userId: 'user-123' }, 'old_checkout');

Use the getter that matches the flag type: getString, getNumber, getJson or getBoolean (getBool in Flutter). A getter of another type returns your default with reason TYPE_MISMATCH.

getDetail — get the full result with the variant key

typescript
// Client SDKs (server SDKs: add the context as the second argument)
const result = flags.getDetail('checkout_flow', 'old_checkout');
// result includes {
//   value: 'new_checkout',
//   enabled: true,
//   variant: 'variant_a',
//   reason: 'VARIANT',
//   version: 4
// }

Flutter

dart
final result = flags.getStringDetail('checkout_flow', 'old_checkout');

switch (result.variant) {
  case 'control':
    return OldCheckout();
  case 'variant_a':
    return NewCheckout();
  case 'variant_b':
    return MinimalCheckout();
  default:
    return OldCheckout();
}

Use Cases#

A/B/n Testing

Test multiple versions of a feature simultaneously to find the best performer

Dynamic Configuration

Return different config values (colors, copy, limits) per variant

Phased Launches

Release a new experience to a small group while keeping the old one for most users

Personalization

Serve different UI layouts or content based on user segments

Tip.

Variant analytics are available in the flag detail page in Abrova Console. They count the evaluations the service makes for client SDKs. Server SDK evaluations run locally and are included only when the SDK runs with sendUsage: true.

Was this page helpful?
Report a problem