Project: OpenFeature (Observability and Analysis / Feature Flagging)
File: 05-events.md

title: Events description: Specification defining event semantics tocmaxheading_level: 4 ](https://github.com/open-feature/spec/tree/main/specification#experimental) `Events` allow consumers (application integrator, application author, integration author) to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. A provider may emit events or run a callback indicating that it received a certain event, optionally providing data associated with that event. Handlers registered on the `client` or the global `API` are then invoked with this data. The data that providers supply in event payloads may include a list of `flag keys` changed, error messages, and possibly updated flag values. ```mermaid graph P(Provider) -->|emit event| A[API] A -->|run handlers| AH("API (global) event handlers") A --> C[Client] C -->|run handlers| CH(Client event handlers) ``` The `domain` of a provider constitutes a logical scope for events. Clients associated to a particular provider through a `domain`, run event handlers only when that provider emits events, or one of its lifecycle functions terminates. see: The `provider` MAY define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDERREADY`, `PROVIDERERROR`, `PROVIDERCONFIGURATIONCHANGED` and `PROVIDER_STALE`, with a `provider event details` payload. Providers cannot emit `PROVIDERCONTEXTCHANGED` or `PROVIDER_RECONCILING` event. These are emitted only by the SDK during context reconciliation. If available, native event-emitter or observable/observer language constructs can be used. When a provider is unable to evaluate flags (perhaps due to loss of connection with a remote service) the provider can signal this by emitting a `PROVIDER_ERROR` event. When it recovers, it can emit a `PROVIDER_READY` event. If the error state is irrecoverable, the `PROVIDER_FATAL` error code can be used. If a provider caches rules-sets or previously evaluated flags, and such states cannot be considered up-to-date, the provider can signal this by emitting a `PROVIDER_STALE` event. see: , , When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers MUST run. Client event handlers respect the dynamic binding of clients to providers via `domains`. Client event handlers run when a lifecycle function terminates on the associated provider, or the associated provider emits an event. see: and . When a `provider` signals the occurrence of a particular `event`, event handlers on clients which are not associated with that provider MUST NOT run. Client event handlers respect the dynamic binding of clients to providers via `domains`. Client event handlers do not run when a lifecycle function terminates on an unassociated provider, or an unassociated provider emits an event. see , for details. `PROVIDER_ERROR` events SHOULD populate the `provider event details`'s `error message` field. The error message field should contain an informative message as to the nature of the error. See `PROVIDER_ERROR` events SHOULD populate the `provider event details`'s `error code` field. See The `client` MUST provide a function for associating `handler functions` with a particular `provider event type`. ```java // run the myClientOnReadyHandler function when the PROVIDER_READY event is fired

myClientOnReadyHandler); ``` see: , The `API` MUST provide a function for associating `handler functions` with a particular `provider event type`. ```java // run the myGlobalErrorHandler function when the PROVIDER_READY event is fired OpenFeature.addHandler(ProviderEvents.Error, myGlobalErrorHandler); ``` see: , The `event details` MUST contain the `provider name` associated with the event. The `provider name` indicates the provider from which the event originated. This is especially relevant for global event handlers used for general monitoring, such as alerting on provider errors. See , . The `handler function` MUST accept a `event details` parameter. see: If a `handler function` terminates abnormally, other `handler functions` MUST run. Event handlers MUST persist across `provider` changes. If the underlying provider is changed, existing client and API event handlers will still fire. This means that the order of provider configuration and event handler addition is independent. The `API` and `client` MUST provide a function allowing the removal of event handlers. ```java // remove an existing handler for a PROVIDERCONFIGURATIONCHANGED event client.removeHandler(ProviderEvents.ConfigurationChanged, myClientOnChangedHandler); ``` Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. Implementations automatically emit `PROVIDERREADY` or `PROVIDERERROR` events depending on the outcome of the `initialize` function, if the provider has implemented one (if none is implemented, `PROVIDER_READY` runs unconditionally). Application authors and application integrators use these events to wait for proper initialization of the provider and to do basic monitoring and error handling. If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run. See and . If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run. A failed initialization could represent an unrecoverable error, such as bad credentials or a missing file. If a failed initialization could also represent a transient error. A provider which maintains a persistent connection to a remote `flag management system` may attempt to reconnect, and emit `PROVIDER_READY` after a failed initialization. See and . Handlers attached after the provider is already in the associated state, MUST run immediately. Handlers may be attached at any point in the application lifecycle. Handlers should run immediately if the provider is already in the associated state. For instance, application authors may attach readiness handlers to be confident that system is ready to evaluate flags. If such handlers are attached after the provider underlying the client has already been initialized, they should run immediately. See , . Providers built to conform to the static context paradigm feature two additional events: `PROVIDERRECONCILING` and `PROVIDERCONTEXT_CHANGED`. When the provider is reconciling its internal state (the `on context changed` function is running and not yet terminated), the SDK emits `PROVIDER_RECONCILING` and transitions the provider into state `RECONCILING`. This can be particularly useful for displaying loading indicators while the is being reconciled. If the `on context changed` function terminates normally, the SDK emits (`PROVIDERCONTEXTCHANGED`) and transitions the provider into the `READY` state, otherwise it emits `PROVIDER_ERROR` and transitions the provider into `ERROR`

The `PROVIDERCONTEXTCHANGED` is used to signal that the associated context has been changed, and flags should be re-evaluated. This can be particularly useful for triggering UI repaints in multiple components when one component updates the . ```mermaid title: Provider context reconciliation stateDiagram-v2 direction TB READY --> READY:emit(PROVIDERCONTEXTCHANGED)* READY --> RECONCILING:emit(PROVIDER_RECONCILING) RECONCILING --> READY:emit(PROVIDERCONTEXTCHANGED) RECONCILING --> ERROR:emit(PROVIDER_ERROR) ``` \* Implementations may allow for providers to reconcile synchronously, in which case no `PROVIDER_RECONCILING` event is emitted. ](https://github.com/open-feature/spec/tree/main/specification#experimental) The implementation uses the static-context paradigm. see: While the provider's `on context changed` function is executing, associated `RECONCILING` handlers MUST run. The implementation must run any `RECONCILING` handlers associated with the provider while the provider is reconciling its state. In languages with asynchronous semantics, the emission of this event can be skipped if the `on context changed` function of the provider in question executes synchronously for a given provider, no other operations can take place while it runs. see: , , If the provider's `on context changed` function terminates normally, and no other invocations have yet to terminate, associated `PROVIDERCONTEXTCHANGED` handlers MUST run. The implementation must run any `PROVIDERCONTEXTCHANGED` handlers associated with the provider after the provider has reconciled its state and returned from the `on context changed` function. The `PROVIDERCONTEXTCHANGED` is not emitted from the provider itself; the SDK implementation must run the `PROVIDERCONTEXTCHANGED` handlers if the `on context changed` function terminates normally. It's possible that the `on context changed` function is invoked simultaneously or in quick succession; in this case the SDK will only run the `PROVIDERCONTEXTCHANGED` handlers after all reentrant invocations have terminated, and the last to terminate was successful (terminated normally). see: , , If the provider's `on context changed` function terminates abnormally, and no other invocations have yet to terminate, associated `PROVIDER_ERROR` handlers MUST run. The `PROVIDERERROR` is not emitted from the provider itself; the SDK implementation must run the `PROVIDERERROR` handlers if the `on context changed` throws or otherwise signals an error. It's possible that the `on context changed` function is invoked simultaneously or in quick succession; in this case the SDK will only run the `PROVIDER_ERROR` handlers after all reentrant invocations have terminated, and the last to terminate was unsuccessful (terminated abnormally). see: , , If the provider emits an event, the value of the client's `provider status` MUST be updated accordingly. Some providers may emit events spontaneously, based on changes in their internal state (connections, caches, etc). The SDK must update it's internal representation of the provider's state accordingly: | Event | Associated Status | | -- | - | | `PROVIDER_READY` | `READY` | | `PROVIDER_STALE` | `STALE` | | `PROVIDER_ERROR` | `ERROR`/`FATAL`* | | `PROVIDERCONFIGURATIONCHANGED` | N/A (provider remains in its current state) | | `PROVIDERCONTEXTCHANGED` | N/A (only emitted by SDK during context reconciliation) | | `PROVIDER_RECONCILING` | N/A (only emitted by SDK during context reconciliation) | \* If the `error code` associated with the error indicates `PROVIDER_FATAL`, the state is set to `FATAL` see: ,