Describe the bug
Describe the bug
Service.inject_config() currently retrieves the process-wide configuration from BentoMLContainer.config, merges service-specific settings into it, and writes the modified configuration back to the container.
Simplified implementation:
existing = t.cast(dict[str, t.Any], BentoMLContainer.config.get())
deep_merge(existing, {
"api_server": api_server_config,
**rest_config,
})
BentoMLContainer.config.set(existing)
Because inject_config() updates the shared container configuration, every invocation operates on the configuration produced by previous calls rather than an isolated base configuration.
This raises concerns about configuration isolation during service initialization.
Observed behavior
inject_config() modifies the process-wide BentoMLContainer.config.
- Service-specific configuration becomes part of the shared global state.
- Later calls to
inject_config() inherit modifications made by previous services.
- The current behavior makes it difficult to determine whether service configuration is intended to be isolated or globally persistent.
This report is not about concurrent execution or race conditions. The behavior can be observed with sequential calls within the same Python process.
Steps to reproduce
service_a = Service(...)
service_a.inject_config()
config_after_a = BentoMLContainer.config.get()
service_b = Service(...)
service_b.inject_config()
config_after_b = BentoMLContainer.config.get()
Observe that the global container configuration has been modified by both service injections.
Expected behavior
The expected behavior depends on the intended design of BentoMLContainer.config.
Either:
inject_config() is expected to mutate the global configuration, in which case this behavior should be documented.
or
- Each service should be configured using an isolated configuration object without polluting the process-wide container state.
Clarifying the intended lifecycle of BentoMLContainer.config would help determine the correct implementation.
Additional context
Before implementing a fix, it would be helpful to clarify whether BentoMLContainer.config is intended to represent:
- Process-wide mutable configuration
- Build-local configuration
- Service-local configuration
The appropriate solution depends on the intended ownership and lifetime of this configuration object.
To reproduce
from _bentoml_sdk import service
from bentoml._internal.configuration.containers import BentoMLContainer
@service(name="service_a", workers=2)
class ServiceA:
pass
@service(name="service_b", workers=3)
class ServiceB:
pass
ServiceA.inject_config()
config_after_a = BentoMLContainer.config.get()
ServiceB.inject_config()
config_after_b = BentoMLContainer.config.get()
print(config_after_a)
print(config_after_b)
Observe that BentoMLContainer.config is modified after each call to
inject_config(), meaning subsequent service configuration starts from
the previously mutated global configuration.
Expected behavior
Service.inject_config() should have clearly defined configuration
ownership.
Either:
- The mutation of
BentoMLContainer.config is intentional and should be
documented as process-wide state.
or
- Each service should configure itself using an isolated configuration
object so that service initialization does not depend on mutations
introduced by previous services.
The expected lifecycle of BentoMLContainer.config is currently
unclear.
Environment
python -m bentoml env
Describe the bug
Describe the bug
Service.inject_config()currently retrieves the process-wide configuration fromBentoMLContainer.config, merges service-specific settings into it, and writes the modified configuration back to the container.Simplified implementation:
Because
inject_config()updates the shared container configuration, every invocation operates on the configuration produced by previous calls rather than an isolated base configuration.This raises concerns about configuration isolation during service initialization.
Observed behavior
inject_config()modifies the process-wideBentoMLContainer.config.inject_config()inherit modifications made by previous services.This report is not about concurrent execution or race conditions. The behavior can be observed with sequential calls within the same Python process.
Steps to reproduce
Observe that the global container configuration has been modified by both service injections.
Expected behavior
The expected behavior depends on the intended design of
BentoMLContainer.config.Either:
inject_config()is expected to mutate the global configuration, in which case this behavior should be documented.or
Clarifying the intended lifecycle of
BentoMLContainer.configwould help determine the correct implementation.Additional context
Before implementing a fix, it would be helpful to clarify whether
BentoMLContainer.configis intended to represent:The appropriate solution depends on the intended ownership and lifetime of this configuration object.
To reproduce
Observe that
BentoMLContainer.configis modified after each call toinject_config(), meaning subsequent service configuration starts fromthe previously mutated global configuration.
Expected behavior
Service.inject_config()should have clearly defined configurationownership.
Either:
BentoMLContainer.configis intentional and should bedocumented as process-wide state.
or
object so that service initialization does not depend on mutations
introduced by previous services.
The expected lifecycle of
BentoMLContainer.configis currentlyunclear.
Environment
python -m bentoml env