fix(router): release a deployment's cost-map key when it is deleted

The ownership ledger only grew. A deleted deployment kept its claim, so if a
later catalog refresh started publishing a model under that same name, the next
registration would treat the catalog entry as the deployment's own and evict it.

Deleting a deployment now gives the key back, which also stops the ledger
growing for the life of the process.
This commit is contained in:
yuneng-jiang 2026-09-06 10:55:34 +00:00
parent 315b098a1e
commit d4d29d237c
No known key found for this signature in database
2 changed files with 36 additions and 1 deletions

View file

@ -615,7 +615,8 @@ RETRY_BREADCRUMB_LIMIT: Final = 4
# Cost-map keys created by _register_deployment_in_model_cost, which shares one flat
# namespace with the built-in model catalog. Only a key it created may be evicted, or a
# deployment whose id names a real model would strip that model's pricing and
# capabilities for every other deployment of it.
# capabilities for every other deployment of it. delete_deployment gives a key back, so a
# later catalog refresh that starts serving that name is not treated as a deployment's own.
_DEPLOYMENT_COST_MAP_KEYS: Final[set[str]] = set() # mutable-ok: ownership of shared cost-map keys
@ -9874,6 +9875,7 @@ class Router:
_budget_limiter: Final = self._get_router_deployment_budget_limiter()
if _budget_limiter is not None:
_budget_limiter.unregister_deployment_budget(model_id=id)
_DEPLOYMENT_COST_MAP_KEYS.discard(id)
try:
self._unregister_pre_routing_strategy_for_deployment(
deployment=item if isinstance(item, Deployment) else Deployment(**item)

View file

@ -315,6 +315,39 @@ def test_should_drop_a_stale_price_even_when_the_deployment_declares_a_provider(
_restore_model_cost_entries(original)
def test_should_give_a_cost_map_key_back_when_the_deployment_is_deleted():
"""Deleting a deployment releases its claim on the shared cost-map key.
Held forever, a later catalog refresh that starts publishing a model under that same
name would be treated as the deleted deployment's own entry and evicted.
"""
from litellm.router import _DEPLOYMENT_COST_MAP_KEYS
model_id = "deployment-to-delete"
original = {model_id: litellm.model_cost.get(model_id)}
router = Router(
model_list=[
{
"model_name": "to-delete",
"litellm_params": {"model": "gpt-4o-mini", "mock_response": "ok"},
"model_info": {"id": model_id, "input_cost_per_token": 0.005},
}
]
)
try:
assert model_id in _DEPLOYMENT_COST_MAP_KEYS
assert router.delete_deployment(id=model_id) is not None
assert model_id not in _DEPLOYMENT_COST_MAP_KEYS, (
"a deleted deployment kept its claim on the shared cost-map key"
)
finally:
_DEPLOYMENT_COST_MAP_KEYS.discard(model_id)
_restore_model_cost_entries(original)
def test_should_preserve_builtin_pricing_regardless_of_deployment_order():
"""
The built-in pricing should be preserved no matter which deployment