This guide contains common integration steps that apply to all Confidence OpenFeature providers in this repository.
For language-specific installation and quick start instructions, see your provider's README:
- Getting Your Credentials
- Error Handling
- Sticky Assignments
- Deferred Apply and Resolve Token Security
Before integrating any Confidence provider, you'll need a client secret from your Confidence account:
- Log into the Confidence dashboard
- In the Clients section, create a new client secret for the client you intend to use (or start by creating a new client)
- Make sure to select Backend as integration type. Never expose your Backend client secret outside your organization
All Confidence providers use a default value fallback pattern to ensure your application continues to function even when flag evaluation fails.
When you request a flag value, you always provide a default:
// Pseudocode
value = client.getFlagValue("my-flag", DEFAULT_VALUE, context)
If anything goes wrong, the provider returns DEFAULT_VALUE instead of throwing an error.
| Scenario | What Happens | Common Causes |
|---|---|---|
| Flag doesn't exist | Returns default | Flag not created, wrong name, not enabled for the client |
| Type mismatch | Returns default | Requesting boolean for string or object property. Or requesting boolean for the flag. Flags are objects in Confidence |
| Network failure | Returns default | Confidence API unreachable (Ruby only) |
| Initialization failure | Returns default | CDN unreachable, invalid credentials not backend type |
| Invalid context | Returns default | Malformed attributes, missing targeting key |
| Provider not ready | Returns default | Called before initialization complete |
For debugging, use the details methods to get error information:
Error codes:
FLAG_NOT_FOUND: The flag doesn't exist in ConfidenceTYPE_MISMATCH: Wrong value type requested (e.g., boolean for string)PROVIDER_NOT_READY: Provider still initializingPARSE_ERROR: Response couldn't be parsedGENERAL_ERROR: Other errors (network, timeout, etc.)
Reasons (standard OpenFeature reasons):
TARGETING_MATCH: Flag evaluated successfully and matched targeting rulesDEFAULT: Default value returned (no segment/variant matched)DISABLED: Flag is disabled or archivedSTALE: Stale cached valueERROR: Evaluation failed (see error code)UNKNOWN: Reason could not be determined
-
Choose safe defaults Example:
✅ GOOD: Default to "off" for risky features ❌ BAD: Default to "on" for untested code -
Log errors for debugging
- Track evaluation failures in your monitoring system. You can use OpenFeature hooks for this.
- Include flag key, error code, and context in logs
- Set up alerts for elevated error rates
-
Monitor error rates
- Track
errorCode != nullmetrics - Alert if error rate exceeds threshold (e.g., >5%)
- Investigate spikes (may indicate misconfigured flag setup or SDK integration)
- Track
-
Test error scenarios
- Verify app works when Confidence is unreachable
- Test with invalid credentials
- Test with non-existent flags
- Verify graceful handling of type mismatches
-
Document your defaults
// Default: false - feature is opt-in for safety const enabled = getFlag("new-payment-flow", false) // Default: 1000ms - conservative timeout const timeout = getFlag("api-timeout", 1000)
Confidence provides sticky flag assignments to ensure users receive consistent variant assignments across evaluations. It can be used for two things:
- Pause intake of new entities to an experiment
- Ensure that entities are assigned the same variant throughout an experiment even if some of their targeting attributes change during the experiment.
When a flag is evaluated for a user, Confidence creates a materialization — a snapshot of which variant that user was assigned. On subsequent evaluations, the same variant is returned even if:
- The user's context attributes change (e.g., different country, device type)
- The flag's targeting rules are modified
- New assignments are paused (controlled rollouts)
By default, sticky assignments are managed by Confidence servers:
- First, the local WASM resolver attempts to resolve the flag
- If sticky assignment data is needed, the provider makes a network call to Confidence's cloud resolvers
- Materializations are stored on Confidence servers with a 90-day TTL (automatically renewed on access)
- No local storage or database setup required
- Zero configuration: Works out of the box with no additional setup
- Managed storage: Confidence handles all storage and consistency
- Global availability: Materializations are available across all your services that are using this flag
When a sticky assignment is needed, the provider makes a network call to Confidence's cloud resolvers. This introduces additional latency (the network latency between your location and Confidence servers) compared to local WASM evaluation.
Some providers support custom storage backends to eliminate network calls for sticky assignments. Check your provider's README for availability and implementation details:
- Java Provider - Supports custom
MaterializationRepository - JavaScript Provider - Coming soon
- Go Provider - Coming soon
For technical details on how sticky assignments work at the protocol level, including flowcharts, behavior matrices, and configuration patterns, see the Sticky Assignments Technical Guide.
Currently supported in the Go, JavaScript, and Java providers.
When you resolve flags with apply=false, the response includes a resolve token that you later pass to the apply call to record exposure. This pattern is useful when resolution happens earlier than exposure — for example, resolving on the server but only logging exposure once the client actually renders the experience (see the JS React integration for a typical RSC flow).
The resolve token is not encrypted. It is a serialized payload that includes, among other things:
- The full evaluation context used during resolution (targeting key and any attributes you passed in)
- Which variant each flag was resolved to
If any of that data is sensitive (PII in the evaluation context, variant assignments you don't want exposed to end users), do not let the raw token leave your backend. Encrypt the token at the trust boundary and decrypt it again before handing it back to the provider's apply call:
backend ──[ resolve(apply=false) ]──► resolve token (plaintext)
backend ──[ encrypt ]──► opaque token ──► client / storage / queue
client ──► opaque token ──► backend ──[ decrypt ]──► resolve token ──► provider.applyFlag(...)
The provider only needs to see the original token at apply time — anything you wrap around it in transit is up to you.