You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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()
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.
Activity
beeme1mr commentedon May 20, 2026
Good catch, @dd-oleksii. This is a significant behavioral change that we should get in prior to a v1 release.
jonathannorris commentedon May 20, 2026
I agree with this. Did a quick cross-SDK comparison and this is the only SDK where
set_provider()is blocking by default:SetProviderAndWait()setProviderAndWait()setProviderAndWait()Thread.new)set_provider_and_wait()Ruby is probably the closest reference for the fix. configuration.rb has a
set_provider_internalmethod that branches on await_for_initflag:set_providerspawns aThread.new,set_provider_and_waitruns 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 tagged1.0-releaseand 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.beeme1mr commentedon May 20, 2026
There's a draft PR to add
set_provider_and_wait.#567
jonathannorris commentedon May 20, 2026
Took a stab at implementing the changes myself too 🤭 will review the other one: #595