Skip to content

set_provider() should be non-waiting #594

Closed

Description

@dd-oleksii

tl;dr: the default set_provider() / recommended way to initialize should be non-blocking. Blocking-by-default may lead to hard-to-debug denial of service.

Requirement 1.1.2.4

The API SHOULD provide functions to set a provider and wait for the initialize function to complete or abnormally terminate.

This function not only sets the provider, but ensures that the provider is ready (or in error) before returning or settling.

// default provider
OpenFeatureAPI.getInstance().setProviderAndWait(myprovider); // this method blocks until the provider is ready or in error
// client uses the default provider
Client client = OpenFeatureAPI.getInstance().getClient(); 

// provider associated with domain-1
OpenFeatureAPI.getInstance().setProviderAndWait('domain-1', myprovider); // this method blocks until the provider is ready or in error
// client uses provider associated with the domain named 'domain-1'
Client client = OpenFeatureAPI.getInstance().getClient('domain-1');

Requirement 1.1.2.4 implies that the default set_provider() should not wait for the provider to initialize.

Having the waiting implementation being the default has a couple of issues. The recommended api.set_provider(MyProvider()) blocks the rest of the application from proceeding. This turns a provider hanging during initialization into an application denial of service.

This can be exaggerated further by something like gunicorn which has an default 30s worker initialization timeout. If the provider takes 30+ seconds to initialize, this leads to gunicorn killing the worker with a cryptic WORKER TIMEOUT message which may be hard to debug.

If set_provider() is non-waiting, the worst case scenario is evaluations returning default values which is much safer. For users who do want to wait, we should provide set_provider_and_wait()

Activity

  1. beeme1mr commented on May 20, 2026

    @beeme1mr
    Member

    Good catch, @dd-oleksii. This is a significant behavioral change that we should get in prior to a v1 release.

  2. jonathannorris commented on May 20, 2026

    @jonathannorris
    Member

    I agree with this. Did a quick cross-SDK comparison and this is the only SDK where set_provider() is blocking by default:

    SDK Default Wait variant
    Go non-blocking (goroutine) SetProviderAndWait()
    JS/TS non-blocking (Promise fire-and-forget) setProviderAndWait()
    Java non-blocking (thread pool) setProviderAndWait()
    Ruby non-blocking (Thread.new) set_provider_and_wait()
    Python blocking missing

    Ruby is probably the closest reference for the fix. configuration.rb has a set_provider_internal method that branches on a wait_for_init flag: set_provider spawns a Thread.new, set_provider_and_wait runs init on the calling thread and re-raises on error.

    The gunicorn scenario in the issue is a real production concern. A provider that blocks during init doesn't just hang; it gets the worker killed with a cryptic timeout message. Non-blocking default is definitely the right call, and the fix looks straightforward to implement.

    One note on versioning: this changes the default behavior of set_provider(), so anyone relying on the provider being ready immediately after the call returns would be affected. Since it's tagged 1.0-release and the SDK is still pre-1.0 (currently at v0.9.0), this is the right time to make the change rather than carry it as a breaking change post-1.0.

  3. beeme1mr commented on May 20, 2026

    @beeme1mr
    Member

    There's a draft PR to add set_provider_and_wait.

    #567

  4. jonathannorris commented on May 20, 2026

    @jonathannorris
    Member

    Took a stab at implementing the changes myself too 🤭 will review the other one: #595

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    1.0-releaseRequired for a 1.0 releasehelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions