Feature Flags
Remote configuration, percentage rollouts, user and tenant targeting, and instant kill-switches — evaluated locally with no per-request network call. Ships Phase 2.
Phase note. Feature flags ship Phase 2. The API shown below is the planned interface; it is not available in Phase 1.
Feature Flags
CoreSDK's built-in feature flag engine evaluates flags locally against the current request context. Flags are defined on the control plane and synced to the sidecar daemon, which holds a warm in-memory cache and answers in microseconds — no per-request network call.
How syncing works
Control plane
│ push on change + periodic poll (default: 30 s)
▼
Sidecar daemon ──── in-memory flag cache
│
│ local IPC (unix socket / loopback)
▼
Your SDK call → flag value returned synchronouslyIf the sidecar loses connectivity to the control plane, it continues serving evaluations from its last known cache.
Basic flag evaluation (planned API)
from coresdk import CoreSDKClient, SDKConfig
_sdk = CoreSDKClient(SDKConfig.from_env())
# Boolean flag — default False when flag is unknown
new_dashboard = _sdk.flags.bool("new-dashboard", default=False)
# String flag
search_backend = _sdk.flags.string("search-backend", default="elasticsearch")
# Number flag
rate_limit = int(_sdk.flags.number("rate-limit-rps", default=100))
if new_dashboard:
serve_v2_dashboard()Targeting rules (planned API)
Pass a context dict to scope evaluation to a specific user or tenant:
user = request.state.coresdk_user
flag_ctx = {
"tenant_id": user.tenant_id,
"user_id": user.sub,
"role": user.role,
}
# Enabled for enterprise tenants only
ai_enabled = _sdk.flags.bool("ai-summaries", default=False, ctx=flag_ctx)
# In a 20% rollout — stable per user_id hash
new_editor = _sdk.flags.bool("new-editor", default=False, ctx=flag_ctx)Supported targeting dimensions:
| Dimension | Type | Example |
|---|---|---|
tenant_id | string | "acme", "globex" |
user_id | string | "usr_01HX7KQ..." |
role | string | "admin", "viewer" |
plan | string | "free", "pro", "enterprise" |
percentage | 0–100 | Sticky hash on user_id |
Kill-switches (planned API)
Gate risky code paths behind a boolean flag from day one. Flip the switch from the dashboard; traffic falls back to the safe path within the sync interval (default 30 s), no redeploy required.
use_new_processor = _sdk.flags.bool("payment-processor-v2", default=False, ctx=flag_ctx)
if use_new_processor:
result = await payment_processor_v2.charge(order)
else:
result = await payment_processor_v1.charge(order)Testing with local overrides (planned API)
from coresdk.testing._mock import MockSDK
mock = MockSDK(flag_overrides={
"ai-summaries": True,
"search-backend": "typesense",
})
response = get_document_handler(mock, mock_request())
assert "AI Summary" in response.bodyEnvironment variable reference
| Variable | Default | Description |
|---|---|---|
CORESDK_SIDECAR_ADDR | 127.0.0.1:50051 | Sidecar address |
CORESDK_SYNC_INTERVAL_SECONDS | 30 | Flag sync interval |
Next steps
- Middleware Pipeline — evaluate flags once in middleware and pass results to handlers
- Request Context — claims available for flag targeting
- Offline Mode — how the cache behaves when the control plane is unreachable
Offline Mode
How CoreSDK behaves when the control plane or sidecar is unreachable. CORESDK_FAIL_MODE=open/closed. HMAC-verified cache. No application code changes required.
Intent Annotations
Attach semantic intent to traced functions using the @trace(intent="...") decorator. Captured as an OTel span attribute, works with sync and async Python functions.