#5678·BentoML

bug: Service.inject_config() mutates global BentoMLContainer.config instead of using isolated configuration

Author: atharv0oCreated Jul 28, 2026Updated Jul 28, 2026
Labelsbug

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:

python
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

python
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

python
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