Skip to content

flagd Providers

Note

This document serves as both a specification and general documentation for flagd providers. For language-specific details, see the README.md for the provider in question.

flagd providers are as essential as the flagd daemon itself, acting as the "bridge" between the OpenFeature SDK and flagd. In fact, flagd providers may be the most crucial part of the flagd framework, as they can be used without an active flagd instance. This document outlines their behavior and configuration.

Naming

Consistent with our naming conventions, the flagd provider name (no matter what language or runtime is in use) is flagd.

In-Process vs RPC Evaluation

There are two modes of operation (resolvers) for flagd providers; in-process and RPC. Both modes have their advantages and disadvantages. For more information on the architectural implications of these different modes, see the RPC vs In-Process Evaluation page.

flagd Provider Lifecycle

flagd providers are built to adhere to the provider lifecycle defined in the OpenFeature specification. Understanding the flagd provider lifecycle is helpful in configuring and optimizing your flagd deployment, and critical to implementing a flagd provider.

The lifecycle is summarized below:

  • on initialization, attempt to connect the appropriate stream according to the resolver type (sync stream for in-process vs event stream for RPC) and in the case of in-process, fetch the sync-metadata
    • if stream connection succeeds within the time specified by deadline, return from initialization (SDK will emit PROVIDER_READY) and for in-process providers, store the flag set rules
    • if stream connection fails or exceeds the time specified by deadline, abort initialization (SDK will emit PROVIDER_ERROR), and attempt to reconnect
  • while connected:
    • flags are resolved according to resolver mode; either by calling evaluation RPCs, or by evaluating the stored flag set rules
    • for RPC providers, flags resolved with reason=STATIC are cached
    • if flags change the associated stream (event or sync) indicates flags have changed, flush cache, or update flag set rules respectively and emit PROVIDER_CONFIGURATION_CHANGED
  • if stream disconnects:
    • reconnect with exponential backoff offered by GRPC.
      • if disconnected time <= retryGracePeriod
        • emit PROVIDER_STALE
        • RPC mode resolves STALE from cache where possible
        • in-process mode resolves STALE from stored flag set rules
      • if disconnected time > retryGracePeriod
        • emit PROVIDER_ERROR
        • RPC mode evaluation cache is purged
        • in-process mode resolves STALE from stored flag set rules
  • on stream reconnection:
    • emit PROVIDER_READY and PROVIDER_CONFIGURATION_CHANGED
    • in-process providers store the latest flag set rules
  • emit PROVIDER_CONFIGURATION_CHANGED event and update flag set rules when a configuration_change message is received on the streaming connection
  • on shutdown, close the streaming connection in theshutdown function
stateDiagram-v2
    [*] --> NOT_READY
    NOT_READY --> READY: initialize
    NOT_READY --> ERROR: initialize
    READY --> ERROR: disconnected, disconnected period == 0
    READY --> STALE: disconnected, disconnect period < retry grace period
    STALE --> ERROR: disconnect period >= retry grace period
    ERROR --> READY: reconnected
    ERROR --> [*]: shutdown

    note right of STALE
        stream disconnected, attempting to reconnect,
        resolve from cache*
        resolve from flag set rules**
        STALE emitted
    end note

    note right of READY
        stream connected,
        evaluation cache active*,
        flag set rules stored**,
        metadata fetched**
        READY emitted
        CHANGE emitted with stream messages
    end note

    note right of ERROR
        stream disconnected, attempting to reconnect,
        evaluation cache purged*,
        ERROR emitted
    end note

%% * RPC providers only
%% ** In-Process providers only
*   RPC providers only
**  In-Process providers only

Stream Reconnection

When either stream (sync or event) disconnects, whether due to the associated deadline being exceeded, network error or any other cause, the provider attempts to re-establish the stream immediately, and then retries with an exponential back-off. We always rely on the integrated functionality of GRPC for reconnection and utilize Wait-for-Ready to re-establish the stream. We are configuring the underlying reconnection mechanism whenever we can, based on our configuration. (not all GRPC implementations support this)

language/property min connect timeout max backoff initial backoff jitter multiplier
GRPC property grpc.initial_reconnect_backoff_ms max_reconnect_backoff_ms min_reconnect_backoff_ms 0.2 1.6
Flagd property deadlineMs retryBackoffMaxMs retryBackoffMs 0.2 1.6
--- --- --- --- --- ---
default [^1] 0.2 1.6
js 0.2 1.6
java 0.2 1.6

[^1] : C++, Python, Ruby, Objective-C, PHP, C#, js(deprecated)

When disconnected, if the time since disconnection is less than retryGracePeriod, the provider emits STALE when it disconnects. While the provider is in state STALE the provider resolves values from its cache or stored flag set rules, depending on its resolver mode. When the time since the last disconnect first exceeds retryGracePeriod, the provider emits ERROR. The provider attempts to reconnect indefinitely, with a maximum interval of retryBackoffMaxMs.

RPC Evaluation

RPC providers use the evaluation protocol to connect to flagd, initiate the event stream, listen for changes in the flag definitions, and evaluate flags remotely by calling flagd. RPC providers are relatively simple to implement since they essentially call a remote flagd instance with relevant parameters, and then flagd responds with the resolved flag value. Of course, this means there's latency associated with RPC providers, though this is mitigated somewhat by caching.

Flag Evaluation Caching

In RPC mode, flagd uses a caching mechanism which greatly reduces latency for static flags (flags without targeting rules). Evaluations for flags with targeting rules are never cached.

Note

Evaluation caching is only relevant to when the RPC resolver is used; the in-process resolver stores a complete set of rules for a flag set, which means evaluation can be done locally, with low latency.

Cacheable flags

flagd sets the reason of a flag evaluation as STATIC when no targeting rules are configured for the flag. A client can safely store the result of a static evaluation in its cache indefinitely (until the configuration of the flag changes, see cache invalidation).

Put simply in pseudocode:

if reason == "STATIC" {
    isFlagCacheable = true
}

Cache invalidation

flagd emits events to the server-to-client stream, among these is the configuration_change event. The structure of this event is as such:

{
    "type": "delete", // ENUM:["delete","write","update"]
    "source": "/flag-configuration.json", // the source of the flag configuration
    "flagKey": "foo"
}

A client should invalidate the cache of any flag found in a configuration_change event to prevent stale data. If the connection drops all cache values must be cleared (any number of events may have been missed).

Client Side Providers

Client side flagd providers (used in mobile and front-end web applications) have unique security and performance considerations. These flagd providers only support the RPC resolver mode (so that flag set rules, which might contain sensitive information, are never sent to the client). Instead, these do bulk evaluations of all flags in the flag set, and cache the results until they are invalidated. Bulk evaluations take place when:

  • the provider is initialized
  • the context is changed
  • a change in the definition notifies the provider it should re-evaluate the flags

This pattern is consistent with OpenFeature's static context paradigm.

Note

To support easy integration with mobile and browser use cases, flagd's evaluation protocol is accessible over both gRPC and HTTP

Note

flagd supports the OFREP protocol, meaning client-side OFREP providers can also be used for client-side use-cases.

Provider Metadata

The provider metadata includes properties returned from the provider_ready event payload data.

In-Process Evaluation

In-process providers use the sync schema to connect to flagd, initiate the sync stream, and download the flag-set rules to evaluate them locally. In-process providers are relatively complex (compared to RPC providers) to implement since they essentially must implement more of flagd's logic to evaluate flags locally. Local evaluation has the impact of much lower latency and almost no serialization compared to RPC providers.

JsonLogic Evaluation

An in-process flagd providers provide the feature set offered by JsonLogic to evaluate flag resolution requests for a given context.

Custom JsonLogic Evaluators

In addition to the built-in evaluators provided by JsonLogic, the following custom targeting rules are implemented by the provider:

Targeting Key

Similar to the flagd daemon, in-process providers map the targeting-key into a top level property of the context used in rules, with the key "targetingKey".

$flagd Properties in the Evaluation Context

Similar to the flagd daemon, in-process flagd providers add the following properties to the JsonLogic evaluation context so that users can use them in their targeting rules. Conflicting properties in the context will be overwritten by the values below.

Property Description
$flagd.flagKey the identifier for the flag being evaluated
$flagd.timestamp a unix timestamp (in seconds) of the time of evaluation

Changed Flags

When a new flag definition is parsed, the stored flags are compared with the newly parsed flags. Flags which have been removed, added, or mutated (considering, at a minimum, their default variant, targeting rules, and metadata) have their keys added to the flags changed field of the associated PROVIDER_CONFIGURATION_CHANGED event.`

Sync-Metadata Properties in the Evaluation Context

In-process flagd providers also inject any properties returned by the sync-metadata RPC response into the context. This allows for static properties defined in flagd to be added to in-process evaluations. If only a subset of the sync-metadata response is desired to be injected into the evaluation context, you can define a mapping function with the contextEnricher option.

Provider Metadata

The provider metadata includes the top-level metadata properties in the flag definition.

Offline (File) Mode

The in-process resolver mode can also use a file based flag definition. This does not connect to a flagd instance or gRPC sync implementation, and instead polls a flag definition from a file. If the file has been modified since the last poll (based on the file metadata) and flags have changed, a PROVIDER_CONFIGURATION_CHANGED event with the appropriate changed flags field is emitted.

Note

This mode does not support context enrichment via sync-metadata.

Configuration

Configuration options

Most options can be defined in the constructor, or as environment variables, with constructor options having the highest precedence.

Below are the supported configuration parameters (note that not all apply to both resolver modes):

Option name Environment variable name Explanation Type & Values Default Compatible resolver
resolver FLAGD_RESOLVER mode of operation String - rpc, in-process rpc rpc & in-process
host FLAGD_HOST remote host String localhost rpc & in-process
port FLAGD_PORT remote port int 8013 (rpc), 8015 (in-process) rpc & in-process
targetUri FLAGD_TARGET_URI alternative to host/port, supporting custom name resolution string null rpc & in-process
tls FLAGD_TLS connection encryption boolean false rpc & in-process
socketPath FLAGD_SOCKET_PATH alternative to host port, unix socket String null rpc & in-process
certPath FLAGD_SERVER_CERT_PATH tls cert path String null rpc & in-process
deadlineMs FLAGD_DEADLINE_MS deadline for unary calls, and timeout for initialization int 500 rpc & in-process
streamDeadlineMs FLAGD_STREAM_DEADLINE_MS deadline for streaming calls, useful as an application-layer keepalive int 600000 rpc & in-process
retryBackoffMs FLAGD_RETRY_BACKOFF_MS initial backoff for stream retry int 1000 rpc & in-process
retryBackoffMaxMs FLAGD_RETRY_BACKOFF_MAX_MS maximum backoff for stream retry int 120000 rpc & in-process
retryGracePeriod FLAGD_RETRY_GRACE_PERIOD period in seconds before provider moves from STALE to ERROR state int 5 rpc & in-process
keepAliveTime FLAGD_KEEP_ALIVE_TIME_MS http 2 keepalive long 0 rpc & in-process
cache FLAGD_CACHE enable cache of static flags String - lru, disabled lru rpc
maxCacheSize FLAGD_MAX_CACHE_SIZE max size of static flag cache int 1000 rpc
selector FLAGD_SOURCE_SELECTOR selects a single sync source to retrieve flags from only that source string null in-process
offlineFlagSourcePath FLAGD_OFFLINE_FLAG_SOURCE_PATH offline, file-based flag definitions, overrides host/port/targetUri string null in-process
offlinePollIntervalMs FLAGD_OFFLINE_POLL_MS poll interval for reading offlineFlagSourcePath int 5000 in-process
contextEnricher - sync-metadata to evaluation context mapping function function identity function in-process

Custom Name Resolution

Some implementations support gRPC custom name resolution, and abstractions to introduce additional resolvers. Specifically, a custom resolver for envoy has been implemented in some providers, which overrides the authority header with the authority specified in the envoy URL scheme. Below is an example of a custom target string which will use envoy sidecar proxy for name resolution:

envoy://localhost:9211/flagd-sync.service

The custom name resolver provider in this case will use the endpoint name i.e. flagd-sync.service as authority and connect to localhost:9211.