Context and Overrides¶
Replane’s override system allows you to return different config values based on runtime context. This enables powerful use cases like feature flags, A/B testing, and gradual rollouts.
How Overrides Work¶
Each config in Replane has:
A base value - the default returned when no overrides match
Override rules - conditions that, when matched, return a different value
Override rules are evaluated in order. The first matching rule wins.
Config: "rate_limit"
├── Base value: 100
└── Overrides:
├── 1. If plan == "enterprise" → 10000
├── 2. If plan == "pro" → 1000
└── 3. If region in ["us", "eu"] → 500
Using Context¶
Use with_context() to evaluate overrides:
# Without context - returns base value
rate_limit = replane.configs["rate_limit"] # 100
# With context - evaluates overrides
pro_client = replane.with_context({"plan": "pro"})
rate_limit = pro_client.configs["rate_limit"] # 1000
enterprise_client = replane.with_context({"plan": "enterprise"})
rate_limit = enterprise_client.configs["rate_limit"] # 10000
Context Properties¶
Context is a dictionary with string keys and primitive values:
context = {
# String values
"user_id": "user-123",
"plan": "premium",
"region": "us-east",
"country": "US",
# Numeric values
"age": 25,
"purchase_count": 10,
"account_age_days": 365,
# Boolean values
"is_admin": True,
"is_beta_tester": False,
"email_verified": True,
# None is also valid (treated as "unknown")
"referral_code": None,
}
Default Context¶
Set a default context that applies to all config accesses:
replane = Replane(
...,
context={
"environment": "production",
"app_version": "2.1.0",
},
)
# These accesses include the default context
replane.configs["feature"] # context: {"environment": "production", "app_version": "2.1.0"}
# Additional context is merged with defaults using with_context()
user_client = replane.with_context({"user_id": "123"})
user_client.configs["feature"]
# Effective context: {"environment": "production", "app_version": "2.1.0", "user_id": "123"}
Condition Types¶
Replane supports several condition types for overrides:
Equals¶
Match when a property equals a specific value:
# Override: plan equals "premium"
replane.with_context({"plan": "premium"}).configs["feature"] # Matches
replane.with_context({"plan": "free"}).configs["feature"] # Doesn't match
In / Not In¶
Match when a property is (or isn’t) in a list of values:
# Override: plan in ["pro", "enterprise"]
replane.with_context({"plan": "pro"}).configs["feature"] # Matches
replane.with_context({"plan": "enterprise"}).configs["feature"] # Matches
replane.with_context({"plan": "free"}).configs["feature"] # Doesn't match
Comparison (lt, lte, gt, gte)¶
Numeric comparisons:
# Override: age >= 18
replane.with_context({"age": 21}).configs["adult_content"] # Matches
replane.with_context({"age": 15}).configs["adult_content"] # Doesn't match
Segmentation (Percentage Rollout)¶
Roll out features to a percentage of users:
# Override: 10% of users (based on user_id)
user_client = replane.with_context({"user_id": "user-123"})
user_client.configs["new_checkout"]
# Deterministic: same user always gets same result
Segmentation uses a hash function to deterministically bucket users. This ensures:
The same user always sees the same variant
Distribution is statistically uniform
No server-side state is needed
Logical Operators (AND, OR, NOT)¶
Combine conditions with logical operators:
# Override: (plan == "pro" OR plan == "enterprise") AND region == "us"
replane.with_context({"plan": "pro", "region": "us"}).configs["feature"] # Matches
replane.with_context({"plan": "pro", "region": "eu"}).configs["feature"] # Doesn't match
replane.with_context({"plan": "free", "region": "us"}).configs["feature"] # Doesn't match
Client-Side Evaluation¶
All override evaluation happens locally in your application. The context you provide never leaves your servers.
This design provides:
Privacy - User data stays in your application
Speed - No network round-trip for config reads
Reliability - Works even if connection is temporarily lost
Common Patterns¶
Feature Flags¶
user_client = replane.with_context({"user_id": user.id})
if user_client.configs["new_dashboard_enabled"]:
return render_new_dashboard()
else:
return render_old_dashboard()
Plan-Based Features¶
plan_client = replane.with_context({"plan": user.plan})
max_projects = plan_client.configs["max_projects"]
# free: 3, pro: 10, enterprise: unlimited (-1)
Gradual Rollout¶
Configure a 10% rollout in Replane dashboard, then:
user_client = replane.with_context({"user_id": user.id})
use_new_algorithm = user_client.configs["new_recommendation_algorithm"]
Geographic Targeting¶
geo_client = replane.with_context({"country": request.geo.country})
banner_content = geo_client.configs["homepage_banner"]
A/B Testing¶
user_client = replane.with_context({"user_id": user.id})
button_color = user_client.configs["checkout_button_color"]
# Returns "blue", "green", or "red" based on user's bucket
Missing Context Properties¶
When a condition references a property not in the context:
The condition result is “unknown”
For AND conditions: if any condition is unknown and none fail, the result is unknown
For OR conditions: if any condition matches, it matches; otherwise unknown
Unknown results typically mean the override doesn’t match
# Override requires "plan" property
replane.configs["feature"] # Override won't match (no plan in default context)
replane.with_context({"plan": "pro"}).configs["feature"] # Override can match
Best practice: ensure your context includes all properties that overrides might reference.