• Home
  • Integrations
  • SDKs
  • Guides
  • API docs
    No results for ""
    EXPAND ALL

    EDIT ON GITHUB

    Subscribing to flag changes

    Read time: 6 minutes
    Last edited: Aug 02, 2022

    Overview

    This topic explains how to configure each SDK to allow applications to subscribe to flag change notifications. This feature is available for both client-side and server-side SDKs.

    Subscribing to flag change notifications

    Details about each SDK's configuration are available in the SDK-specific sections below.

    • Client-side SDKs
    • Server-side SDKs

    Client-side SDKs

    This feature is available in the following client-side SDKs:

    .NET (client-side)

    Expand .NET (client-side) code sample

    The client uses an event pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to feature flag changes, register listeners for change events from the SDK:

    client.FlagTracker.FlagChanged += (sender, eventArgs) => {
    if (eventArgs.Key == "key-for-flag-i-am-watching") {
    DoSomethingWithNewFlagValue(eventArgs.NewBoolValue);
    }
    };

    To learn more, read IFlagTracker.

    Android

    Expand Android code sample

    The client uses a listener pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to feature flag changes, register listeners for change events from the SDK:

    String flagKey = "yourFlagKey";
    FeatureFlagChangeListener listener = new FeatureFlagChangeListener() {
    @Override
    public void onFeatureFlagChange(String flagKey) {
    boolean newValue = LDClient.get().boolVariation(flagKey, false);
    }
    };
    LDClient.get().registerFeatureFlagListener(flagKey, listener);

    The flag key passed to onFeatureFlagChange is the key of the updated flag, which lets a single listener be registered for multiple flags.

    You can also disable listeners by unregistering them:

    LDClient.get().unregisterFeatureFlagListener(flagKey, listener);

    Availability

    These calls have been available since v2.8.0:

    • LDAllFlagsListener
    • LDClient.registerAllFlagsListener
    • LDClient.unregisterAllFlagsListener

    Additionally, we provide an update listener interface for when you want to be notified when the flag cache is updated. The application provides a class implementing LDAllFlagsListener which provides the SDK with the method onChange. Whenever the SDK's flag cache is updated, it calls the onChange method with a list of flag keys for flags that were updated during the update to the flag cache. If no flag values changed, this list is empty.

    Here is an example:

    LDAllFlagsListener listener = new LDAllFlagsListener() {
    @Override
    public void onChange(List<String> flagKeys) {
    // Get new values for flagKeys or other operations
    }
    };
    // register all flags listener
    LDClient.get().registerAllFlagsListener(listener);
    // when done with all flags listener it should be unregistered
    LDClient.get().unregisterAllFlagsListener(listener);

    Electron

    Expand Electron code sample

    The client uses an event emitter pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to feature flag changes, register listeners for change events from the SDK:

    client.on('change:YOUR_FEATURE_KEY', (newValue, oldValue) => {
    console.log('The flag was ' + oldValue + ' and now it is ' + newValue);
    });

    Or, you can listen for all feature flag changes:

    client.on('change', (allFlagChanges) => {
    Object.keys(allFlagChanges).forEach((key) => {
    console.log('Flag ' + key + ' is now ' + allFlagChanges[key]);
    });
    });

    Subscribing to change events automatically turns on streaming mode, unless you have explicitly set streaming to false.

    Flutter

    Expand Flutter code sample

    The client uses an observer pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to feature flag changes, register listeners for change events from the SDK:

    LDFlagUpdatedCallback listener = (String flagKey) {
    LDClient.boolVariation(flagKey, false).then((bool val) {
    print('${flagKey}: ${val}');
    });
    };
    await LDClient.registerFeatureFlagListener('yourFlagKey', listener);

    The flag key passed to your LDFlagUpdatedCallback is the key of the updated flag, which allows a single listener to be registered for multiple flags.

    You can also disable listeners by unregistering them:

    await LDClient.unregisterFeatureFlagListener(flagKey, listener);

    Additionally, we provide a listener interface if you want to be notified any time the flag cache is updated. The application provides a callback that is activated whenever the SDK receives new flag data from the service. It calls with a list of flag keys that were updated. If no flag values changed, this list is empty.

    LDFlagsReceivedCallback listener = (List<String> flagKeys) {
    print(flagKeys.toString());
    };
    await LDClient.registerFlagsReceivedListener(listener);
    await LDClient.unregisterFlagsReceivedListener(listener);

    iOS

    Expand iOS code sample

    The client uses an observer pattern which allows your app to subscribe to feature flag changes in real time. To subscribe to feature flag changes, register listeners for change events from the SDK.

    The SDK provides methods for listening to a single flag, all flags, or no change to any flag. observeFlagsUnchanged is called when the SDK successfully receives an update or comes back online but no flags have changed. If the value of the flag changes, the method executes the handler. It passes in the changedFlag containing the old and new flag values, and old and new flag value source.

    The SDK retains only weak references to the owner, which lets the client app freely destroy owners without issues. Client apps should use a capture list specifying [weak self] inside handlers to avoid retain cycles causing a memory leak.

    The SDK executes handlers on the main thread. LDChangedFlag does not know the type of oldValue or newValue. The client app should cast the value into the type needed.

    LDObserverOwner Lifecycle

    The lifetime of the LDObserverOwner must extend for at least as long as you want to receive flag change notifications.

    To configure the client:

    let flagKey = "MY_OBSERVE_FLAG_KEY"
    let flagObserverOwner = flagKey as LDObserverOwner
    let client = LDClient.get()!
    client.observe(keys: [flagKey], owner: flagObserverOwner, handler: { changedFlags in
    if changedFlags[flagKey] != nil {
    // Your code here
    }
    })
    client.stopObserving(owner: flagObserverOwner)
    client.observeFlagsUnchanged(owner: self) {
    client.stopObserving(owner: self as LDObserverOwner)
    }
    client.observeAll(owner: self) {_ in
    client.stopObserving(owner: self as LDObserverOwner)
    }

    JavaScript

    Expand JavaScript code sample

    The client uses an event emitter pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to all feature flag changes, register listeners for change events from the SDK:

    client.on('change', (settings) => {
    console.log('flags changed:', settings);
    });

    The settings object contains a map of updated feature flag keys and values. The map only contains the keys to flags that have changed. You can also subscribe to specific flags.

    Here's how:

    client.on('change:YOUR_FLAG_KEY', (value, previous) => {
    console.log('YOUR_FLAG_KEY changed:', value, '(' + previous + ')');
    });

    Node.js (client-side)

    Expand Node.js (client-side) code sample

    The client uses an event emitter pattern which allows your app to subscribe to feature flag changes in real time.

    To subscribe to all feature flag changes, register listeners for change events from the SDK:

    client.on('change', allChanges => {
    console.log('flags changed:', JSON.stringify(allChanges));
    });

    The allChanges object contains a map of updated feature flag keys and values. The map only contains the keys to flags that have changed. You can also subscribe to specific flags.

    Here's how:

    client.on('change:YOUR_FLAG_KEY', (value, previous) => {
    console.log('YOUR_FLAG_KEY changed:', value, '(was ' + previous + ')');
    });

    React Native

    Expand React Native code sample

    For an app to perform real-time updates, it must register listeners for updates from the SDK for each flag you want it to watch.

    Here's how:

    if (this.state.listeners.hasOwnProperty(key)) {
    return;
    }
    let listener = value => Alert.alert('Listener Callback', value);
    client.registerFeatureFlagListener('MY_LISTEN_FLAG_KEY', listener);
    this.setState({listeners: {...this.state.listeners, ...{['MY_LISTEN_FLAG_KEY']: listener}}});

    You can also disable listeners by unregistering them:

    this.state.client.unregisterFeatureFlagListener('MY_LISTEN_FLAG_KEY', this.state.listeners['MY_LISTEN_FLAG_KEY']);
    let {['MY_LISTEN_FLAG_KEY']: omit, ...newListeners} = this.state.listeners;
    this.setState({listeners: newListeners});

    Server-side SDKs

    This feature is available in the following server-side SDKs:

    .NET (server-side)

    Expand .NET (server-side) code sample
    This feature is not available in all SDK versions

    The .NET SDK only supports subscribing to flag changes in versions 6.0.0 and higher.

    The SDK provides an event-based mechanism to notify you when flag configurations change. LDClient.FlagTracker returns an interface for this mechanism, IFlagTracker.

    Any event handler that you add to the IFlagTracker.FlagChanged event will be called with a FlagChangeEvent whenever there is a change in any feature flag's configuration, or in anything else that could indirectly affect the flag value, such as a prerequisite flag or a user segment that the flag uses.

    The event data consists only of the flag key. It does not contain a flag value, because in server-side SDKs, there is no such thing as a flag value except when it is evaluated for a specific set of user properties.

    The listener method is called synchronously from a background task.

    Here's how:

    void LogWheneverAnyFlagChanges(LdClient client) {
    client.FlagTracker.FlagChanged += (sender, event) =>
    {
    Console.WriteLine("Flag \"{0}\" has changed", event.Key);
    };
    }

    To listen for changes in flag values for a specific flag key and user, use IFlagTracker.FlagValueChangeHandler(). It calls your code with a FlagValueChangeEvent. This is equivalent to re-evaluating the flag for that user whenever there is a change in that flag. Because flag values can have different data types, the value is reported using the general type LdValue.

    void LogWheneverOneFlagChangesForOneUser(LdClient client, string flagKey, User user) {
    client.FlagTracker.FlagChanged += client.FlagTracker.FlagValueChangeHandler(
    flagKey,
    user,
    (sender, event) =>
    {
    Console.WriteLine(
    "Flag \"{0}\" for user \"{1}\" has changed from {2} to {3}",
    flagKey,
    user.Key,
    event.OldValue,
    event.NewValue
    );
    });
    }

    Go

    Expand Go code sample
    This feature is not available in all SDKs or versions

    The Go SDK only supports subscribing to flag changes in versions 5.0.0 and higher.

    The Go SDK provides a channel-based mechanism to notify you when flag configurations change. The LDClient.GetFlagTracker() method returns an interface for this mechanism called FlagTracker.

    Calling GetFlagTracker().AddFlagChangeListener() provides a channel that receives a FlagChangeEvent whenever there is a change in any feature flag's configuration. These changes include anything that could indirectly affect the flag value, such as a prerequisite flag or a user segment that the flag uses.

    The event data consists only of the flag key. It does not contain a flag value, because in server-side SDKs, flags only have values when they are evaluated for a specific set of user properties.

    import (
    "log"
    ld "gopkg.in/launchdarkly/go-server-sdk.v5"
    )
    func logWheneverAnyFlagChanges(client *ld.LDClient) {
    updateCh := client.GetFlagTracker().AddFlagChangeListener()
    go func() {
    for event := range updateCh {
    log.Printf("Flag %q has changed", event.Key)
    }
    }()
    }

    To listen for changes in flag values for a specific flag key and user, use GetFlagTracker().AddFlagValueChangeListener(), which provides FlagValueChangeEvents. This is equivalent to re-evaluating the flag for that user whenever AddFlagChangeListener() reports a change in that flag. Because flag values can have different data types, the value is reported using the general type ldvalue.Value.

    import (
    "log"
    ld "gopkg.in/launchdarkly/go-server-sdk.v5"
    "gopkg.in/launchdarkly/go-sdk-common.v2/lduser"
    "gopkg.in/launchdarkly/go-sdk-common.v2/ldvalue"
    )
    func logWheneverOneFlagChangesForOneUser(client *ld.LDClient, flagKey string, user lduser.User) {
    updateCh := client.GetFlagTracker().AddFlagValueChangeListener(flagKey, user, ldvalue.Null())
    go func() {
    for event := range updateCh {
    log.Printf("Flag %q for user %q has changed from %s to %s", event.Key,
    user.GetKey(), event.OldValue, event.NewValue)
    }
    }()
    }

    With both of these methods, it is the caller's responsibility to consume values from the channel. Letting values accumulate in the channel can cause an SDK goroutine to be blocked.

    Java

    Expand Java code sample
    This feature is not available in all SDK versions

    The Java SDK only supports subscribing to flag changes in versions 5.0.0 and higher.

    The SDK provides a listener-based mechanism to notify you when flag configurations change. The LDClient.getFlagTracker() method returns an interface for this mechanism, FlagTracker.

    Calling getFlagTracker().addFlagChangeListener calls your listener with a FlagChangeEvent whenever there is a change in any feature flag's configuration, or in anything else that could indirectly affect the flag value, such as a prerequisite flag or a user segment that the flag uses.

    The event data consists only of the flag key. It does not contain a flag value, because in server-side SDKs, there is no such thing as a flag value except when it is evaluated for a specific set of user properties.

    The listener method is called from a worker thread.

    Here's how:

    void logWheneverAnyFlagChanges(LDClient client) {
    client.getFlagTracker().addFlagChangeListener(event -> {
    System.out.printf("Flag \"%s\" has changed\n", event.getKey());
    });
    }

    To listen for changes in flag values for a specific flag key and user, use getFlagTracker().addFlagValueChangeListener, which provides FlagValueChangeEvents. This is equivalent to re-evaluating the flag for that user whenever addFlagChangeListener() reports a change in that flag. Because flag values can have different data types, the value is reported using the general type LDValue.

    void logWheneverOneFlagChangesForOneUser(LDClient client, string flagKey, LDUser user) {
    client.getFlagTracker().addFlagValueChangeListener(flagKey, user, event -> {
    System.out.printf("Flag \"%s\" for user \"%s\" has changed from %s to %s\n", event.getKey(),
    user.getKey(), event.getOldValue(), event.getNewValue());
    });
    }

    Node.js (server-side)

    Expand Node.js (server-side) code sample

    The SDK provides an event-based mechanism to notify you when flag configurations change.

    For example, imagine you have a feature flag named EXAMPLE_FLAG_KEY. If the SDK detects a change in EXAMPLE_FLAG_KEY's configuration, or in anything else that could indirectly affect the flag value, such as a prerequisite flag or a user segment that EXAMPLE_FLAG_KEY uses, it emits two events.

    These events are:

    • "update" and
    • "update:EXAMPLE_FLAG_KEY"

    You can listen for "update:EXAMPLE_FLAG_KEY" if you only want to know about updates affecting that flag specifically, or "update" if you want to be notified about all updates.

    For both of these event kinds, an extra parameter is sent to event listeners. This object has the single property key, with its value set to the flag key. If you listened for the general "update" event, this lets you know which flag changed.

    The event parameter does not contain the flag value. In server-side SDKs, there is no such thing as a flag value except when it is evaluated for a specific set of user properties.

    To find out what the effect, if any, of the configuration change was, call variation() after receiving an update event.

    Here is an example:

    client.on('update', (param) => {
    console.log('a flag was changed: ' + param.key);
    });
    client.on('update:EXAMPLE_FLAG_KEY', () => {
    console.log('the EXAMPLE_FLAG_KEY flag was changed');
    });