feat(python)!: New python provider with inprocess support#4861
feat(python)!: New python provider with inprocess support#4861thomaspoignant wants to merge 21 commits intomainfrom
Conversation
✅ Deploy Preview for go-feature-flag-doc-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
5a902c8 to
f61df4a
Compare
There was a problem hiding this comment.
Code Review
This pull request introduces a significant refactoring of the Python provider, adding support for in-process evaluation via WASM, and includes architectural improvements like the AbstractEvaluator interface and a switch to uv for dependency management. A high-severity security issue was identified in the WASM memory management logic: the current implementation uses raw pointers to WASM linear memory without proper bounds checking, which could allow a compromised or malicious WASM module to escape its sandbox and read or write host process memory. It is recommended to use the built-in safe memory access methods from the wasmtime SDK to ensure the integrity of the sandbox. Additionally, several critical issues need attention: the WASM binary required for in-process evaluation is not included in the final package distribution due to the exclude configuration in pyproject.toml; the async methods in InProcessEvaluator are not truly asynchronous and should use asyncio.to_thread; the AGENTS.md file is outdated; and the removal of the provider-level LRU cache is a breaking change that requires explicit documentation. Addressing these points will ensure a more secure and smoother experience for users and contributors.
openfeature/providers/python-provider/gofeatureflag_python_provider/wasm/evaluate_wasm.py
Outdated
Show resolved
Hide resolved
...ure/providers/python-provider/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py
Outdated
Show resolved
Hide resolved
076aa6f to
b8dc83a
Compare
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
b8dc83a to
6c2d65e
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4861 +/- ##
=======================================
Coverage 85.81% 85.81%
=======================================
Files 153 153
Lines 6541 6541
=======================================
Hits 5613 5613
Misses 698 698
Partials 230 230 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a significant and valuable feature: in-process flag evaluation using WASM for the GO Feature Flag Python provider. While the refactoring is well-executed with clear abstractions like AbstractEvaluator and the move to uv and hatchling is a positive modernization step, two critical security vulnerabilities have been identified. The use of a non-thread-safe wasmtime.Store across multiple threads in the in-process evaluator can lead to application crashes, and the EventPublisher is vulnerable to thread exhaustion and unbounded memory growth if the data collector becomes unreachable. Addressing these issues is critical for stability and security. Additionally, improvements are needed for outdated documentation, a potential regression in data collection for the remote evaluator, and async handling in the new in-process evaluator.
...ure/providers/python-provider/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py
Show resolved
Hide resolved
openfeature/providers/python-provider/gofeatureflag_python_provider/services/event_publisher.py
Outdated
Show resolved
Hide resolved
...eature/providers/python-provider/gofeatureflag_python_provider/evaluator/remote_evaluator.py
Show resolved
Hide resolved
...ure/providers/python-provider/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py
Outdated
Show resolved
Hide resolved
...ure/providers/python-provider/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py
Show resolved
Hide resolved
….to_thread Async resolve_*_details_async methods now use asyncio.to_thread() to run sync evaluation in a thread, avoiding event loop blocking. Update test docstring to match.
…rel) from pyproject
… evaluator When a flag is not found in _is_trackable, log warning and return True so unknown flags remain visible in exporters. Update uv.lock.
…evaluation - Add wasm_pool_size option (default 10) to control number of wasmtime Store instances; Store is not thread-safe, so a pool allows parallel evaluations. - Refactor EvaluateWasm to use a Queue of Store slots and _create_slot helper. - InProcessEvaluator passes pool_size into EvaluateWasm (default 4 when unset). - Add test_evaluate_concurrent_threads to assert concurrent evaluation works.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a major refactoring to the Python provider, adding support for in-process evaluation using WASM. The architecture is now split into InProcessEvaluator and RemoteEvaluator (wrapping OFREP), which is a significant improvement in modularity. The introduction of an EventPublisher service also cleans up the data collection logic. However, there are a few critical points to address. The WASM binary required for in-process evaluation is not included in the package distribution, which will cause failures for users. Additionally, data collection appears to be disabled for remote evaluations, which is a significant change in functionality. The documentation in AGENTS.md is also outdated and needs to be updated to reflect the new architecture.
...eature/providers/python-provider/gofeatureflag_python_provider/evaluator/remote_evaluator.py
Show resolved
Hide resolved
The file had several outdated references: phantom ffclient/ directory, non-existent modules/evaluation, missing providers (PHP, Ruby, Swift), missing exporters (Logs, OpenTelemetry), incorrect Exporter interface signature, and missing Makefile targets. Co-authored-by: Cursor <cursoragent@cursor.com>
Port the Java InProcessEvaluation test class to Python, exercising the full provider stack (provider -> InProcessEvaluator -> WASM) with mock flag configurations for all flag types, disabled flags, error paths, and scheduled rollouts. Co-authored-by: Cursor <cursoragent@cursor.com>
|
/gemini review |
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
There was a problem hiding this comment.
Code Review
This pull request introduces in-process evaluation using WASM and migrates the remote evaluation to the OFREP standard, featuring a clean and modular Evaluator abstraction. No security vulnerabilities were found. However, there are several critical points to address: the packaging for the in-process mode appears broken as the WASM binary is not included, the default evaluation mode has been switched to INPROCESS which is a breaking change, data collection for the remote evaluator seems disabled, and there's a minor issue with error handling in the in-process evaluator. Additionally, the move to OFREPProvider for remote evaluation results in the loss of the custom caching mechanism, a performance characteristic change that should be communicated to users.
openfeature/providers/python-provider/gofeatureflag_python_provider/options.py
Show resolved
Hide resolved
...eature/providers/python-provider/gofeatureflag_python_provider/evaluator/remote_evaluator.py
Show resolved
Hide resolved
...ure/providers/python-provider/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py
Show resolved
Hide resolved
|
@kouk @michaelmyc |
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
|
So, @thomaspoignant my understanding is that with this update as a user I get to use bypass the middleman (aka relay-proxy) by using the in process provider, and all the storage mechanism details get put inside the WASM module right? And then the main disadvantage is the lack of a local cache. Right now if I was a user and wanted to update to this new provider I would go with remote evaluation because it would be unclear if and how I would retain all the integrations I have with my relay-proxy. But I would lose caching, so my relay proxy would be on the critical path of each application transaction (Resulting in different behavior of my app based on the availability of the proxy). Am I missing something? |
…details' argument
|
|
@kouk sorry for the delay. It means that the evaluation happens inside the provider (removing network ops and assuring a faster and more reliable evaluation). The remote evaluation still has no caching because if you want a more accurate way you can always use the inprocess implementation. Does it answer all your doubts? |
|
Didn't have time to check everything. Looks like this is adding a wasm resolver locally that syncs with the remote flag system. Not sure why we need wasm? I like the idea that when the remote relay-proxy is down the system could use the local resolver with a recent result (compared to cache which is the last query result that could be ages ago). But I'm not sure how much extra resources it's going to use. It could become a resource hog for relay proxies with a ton of flags, and in a micro-services architecture where each service is designed to be lightweight, it might not be a good default option. |
|
My intuition is that wasm is serving the purpose of a common code base that
would work across different providers (python, JS, etc.) so that the
project doesn't have to maintain fully separate implementations. Perhaps
the wasm module is implemented in Golang or something in another repo?
In any case, what I wanted to ask is, if the relay proxy is still just
serving the configuration does the WASM module keep the last config in
memory in case it cannot reach the proxy?
…---
|/ |/ Konstantinos ***@***.***>
|\ |\ Koukopoulos <https://keybase.io/kouk>
On Fri, Mar 13, 2026, 09:14 Michael Mao ***@***.***> wrote:
*michaelmyc* left a comment (thomaspoignant/go-feature-flag#4861)
<#4861 (comment)>
Didn't have time to check everything. Looks like this is adding a wasm
resolver locally that syncs with the remote flag system. Not sure why we
need wasm?
—
Reply to this email directly, view it on GitHub
<#4861 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADPKRYTVGFSP5P32V7L6HT4QOYM3AVCNFSM6AAAAACV2YSHEWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DANJTGI2TANJXGM>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Ah, if that's the case, I think WASM would be a great addition. More code reuse is welcome. I concur that the caching mechanism should be the key focus of our discussions. My main concerns about pre-emptive caching for local evaluation:
Again, this PR is quite large and I'm not sure if my understanding of the caching mechanism is correct, so not sure if my concerns are valid. |
|
Hey sorry for the late reply @kouk you are totally right, the WASM module is used accross languages, the goal is to be certain that all the evaluation is exactly the same cross languages. FYI, this is already the default implementation in Java, .NET and node.
What would be an ideal compromise for you to work well with this provider? |



Summary
Adds in-process evaluation support to the GO Feature Flag Python provider, allowing flag evaluation without requiring a relay proxy when using WASM.
Changes
AbstractEvaluatorwith two implementations:wasm/module withevaluate_wasm.pyand bundled WASI binary for in-process evaluationGoFeatureFlagProvidernow delegates to the chosen evaluator; logic split into evaluators and servicesservices/package (API client, event publisher, models) used by the remote evaluatorhooks/pyproject.toml+uv.lock);poetry.lockremoved.github/workflows/release-python-provider.ymlupdated for the new layoutAGENTS.mdandCLAUDE.mdfor the Python providerChecklist
Signed-off-by: Thomas Poignant thomas.poignant@gofeatureflag.org