A high-performance OpenFeature provider for Confidence feature flags that evaluates flags locally for minimal latency.
- Local Resolution: Evaluates feature flags locally using WebAssembly (WASM)
- Low Latency: No network calls during flag evaluation
- Automatic Sync: Periodically syncs flag configurations from Confidence
- Exposure Logging: Fully supported exposure logging (and other resolve analytics)
- OpenFeature Compatible: Works with the standard OpenFeature SDK
- Python 3.10+
- OpenFeature SDK 0.8.0+
pip install confidence-openfeature-providerYou'll need a client secret from Confidence to use this provider.
📖 See the Integration Guide: Getting Your Credentials for step-by-step instructions on:
- How to navigate the Confidence dashboard
- Creating a Backend integration
- Creating a test flag for verification
- Best practices for credential storage
from openfeature import api
from openfeature.evaluation_context import EvaluationContext
from confidence import ConfidenceProvider
# Create and register the provider
provider = ConfidenceProvider(client_secret="your-client-secret")
api.set_provider(provider)
# Get a client
client = api.get_client()
# Create evaluation context with user attributes for targeting
context = EvaluationContext(
targeting_key="user-123",
attributes={
"country": "US",
"plan": "premium",
}
)
# Evaluate a flag
enabled = client.get_boolean_value("test-flag.enabled", default_value=False, evaluation_context=context)
print(f"Flag value: {enabled}")
# Don't forget to shutdown when your application exits (see Shutdown section)The evaluation context contains information about the user/session being evaluated for targeting and A/B testing.
from openfeature.evaluation_context import EvaluationContext
# Simple attributes
context = EvaluationContext(
targeting_key="user-123",
attributes={
"country": "US",
"plan": "premium",
"age": 25,
}
)The provider uses a default value fallback pattern - when evaluation fails, it returns your specified default value instead of throwing an error.
📖 See the Integration Guide: Error Handling for:
- Common failure scenarios
- Error codes and meanings
- Production best practices
- Monitoring recommendations
# The provider returns the default value on errors
enabled = client.get_boolean_value("my-flag.enabled", default_value=False, evaluation_context=context)
# enabled will be False if evaluation failed
# For detailed error information, use get_boolean_details()
details = client.get_boolean_details("my-flag.enabled", default_value=False, evaluation_context=context)
if details.error_code:
print(f"Flag evaluation error: {details.error_message}")
print(f"Reason: {details.reason}")Important: To ensure proper cleanup and flushing of exposure logs, you should call shutdown() on the provider when your application exits.
from openfeature import api
# Shutdown the provider to flush logs and clean up resources
api.shutdown()provider = ConfidenceProvider(
client_secret="your-client-secret",
state_poll_interval=30.0, # How often to poll for state updates (seconds)
log_poll_interval=10.0, # How often to flush logs (seconds)
)client_secret(str, required): The Confidence client secret for authentication.state_poll_interval(float, optional): Interval in seconds between state polling updates. Defaults to 30.0.log_poll_interval(float, optional): Interval in seconds for sending evaluation logs. Defaults to 10.0.use_remote_materialization_store(bool, optional): Enable remote materialization storage. Defaults to False.
The provider supports materializations for two key use cases:
- Sticky Assignments: Maintain consistent variant assignments across evaluations even when targeting attributes change.
- Custom Targeting via Materialized Segments: Efficiently target precomputed sets of identifiers from datasets.
By default, materializations are not supported. If a flag requires materialization data, the evaluation will return the default value.
Enable remote materialization storage to have Confidence manage materialization data server-side:
provider = ConfidenceProvider(
client_secret="your-client-secret",
use_remote_materialization_store=True,
)For advanced use cases, you can implement the MaterializationStore protocol to manage materialization data in your own infrastructure. The protocol defines two methods:
read(ops: List[ReadOp]) -> List[ReadResult]: Batch read of materialization datawrite(ops: List[VariantWriteOp]) -> None: Batch write of variant assignments
The read operations support two types:
- VariantReadOp: Query for a sticky variant assignment (returns
VariantReadResult) - InclusionReadOp: Query for segment inclusion (returns
InclusionReadResult)
from confidence.materialization import (
MaterializationStore,
ReadOp,
ReadResult,
VariantReadOp,
VariantReadResult,
InclusionReadOp,
InclusionReadResult,
VariantWriteOp,
)
class MyMaterializationStore:
"""Custom materialization store implementation."""
def read(self, ops: list[ReadOp]) -> list[ReadResult]:
results = []
for op in ops:
if isinstance(op, VariantReadOp):
# Look up sticky variant assignment
variant = self._lookup_variant(op.unit, op.materialization, op.rule)
results.append(VariantReadResult(
unit=op.unit,
materialization=op.materialization,
rule=op.rule,
variant=variant, # None if no assignment exists
))
elif isinstance(op, InclusionReadOp):
# Check segment inclusion
included = self._check_inclusion(op.unit, op.materialization)
results.append(InclusionReadResult(
unit=op.unit,
materialization=op.materialization,
included=included,
))
return results
def write(self, ops: list[VariantWriteOp]) -> None:
for op in ops:
# Store sticky variant assignment
self._store_variant(op.unit, op.materialization, op.rule, op.variant)Pass your custom store to the provider:
provider = ConfidenceProvider(
client_secret="your-client-secret",
materialization_store=MyMaterializationStore(),
)Thread Safety: Your implementation must be thread-safe as it may be called concurrently from multiple threads.
Configure logging to see provider activity:
import logging
logging.getLogger("confidence").setLevel(logging.DEBUG)Apache 2.0