From e6d1ee96fd93a3b527ab3039e1eccb4f9c17c792 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Fri, 27 Mar 2026 14:43:16 +0530 Subject: [PATCH] feat(router): add health-check-driven routing behind opt-in flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Background health checks now feed deployment health state into the router candidate-filtering pipeline. Unhealthy deployments are excluded proactively instead of waiting for request failures to trigger cooldown. Gated by `enable_health_check_routing: true` in general_settings. Off by default — zero behavior change for existing users. Co-Authored-By: Claude Opus 4.6 --- litellm/proxy/health_check.py | 18 +++++++++--------- litellm/proxy/proxy_server.py | 4 ++-- litellm/router.py | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/litellm/proxy/health_check.py b/litellm/proxy/health_check.py index 3e05ee3c484..058f2f4ed9d 100644 --- a/litellm/proxy/health_check.py +++ b/litellm/proxy/health_check.py @@ -210,20 +210,20 @@ async def _perform_health_check( _model_id = (model.get("model_info") or {}).get("id") if isinstance(is_healthy, dict) and "error" not in is_healthy: - cleaned = _clean_endpoint_data({**litellm_params, **is_healthy}, details) + endpoint_data = {**litellm_params, **is_healthy} if _model_id: - cleaned["model_id"] = _model_id - healthy_endpoints.append(cleaned) + endpoint_data["model_id"] = _model_id + healthy_endpoints.append(_clean_endpoint_data(endpoint_data, details)) elif isinstance(is_healthy, dict): - cleaned = _clean_endpoint_data({**litellm_params, **is_healthy}, details) + endpoint_data = {**litellm_params, **is_healthy} if _model_id: - cleaned["model_id"] = _model_id - unhealthy_endpoints.append(cleaned) + endpoint_data["model_id"] = _model_id + unhealthy_endpoints.append(_clean_endpoint_data(endpoint_data, details)) else: - cleaned = _clean_endpoint_data(litellm_params, details) + endpoint_data = {**litellm_params} if _model_id: - cleaned["model_id"] = _model_id - unhealthy_endpoints.append(cleaned) + endpoint_data["model_id"] = _model_id + unhealthy_endpoints.append(_clean_endpoint_data(endpoint_data, details)) return healthy_endpoints, unhealthy_endpoints diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 28e613ef487..42740c24f45 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -37,7 +37,7 @@ import websockets import websockets.exceptions from pydantic import BaseModel, Json -from litellm._uuid import uuid +from litellm._litellm_uuid import uuid from litellm.constants import ( AIOHTTP_CONNECTOR_LIMIT, AIOHTTP_CONNECTOR_LIMIT_PER_HOST, @@ -2138,7 +2138,7 @@ def _write_health_state_to_router_cache( sum(1 for s in states.values() if not s.get("is_healthy")), ) except Exception as e: - verbose_proxy_logger.warning( + verbose_proxy_logger.debug( "Failed to write health state to router cache: %s", str(e) ) diff --git a/litellm/router.py b/litellm/router.py index 6cc6bad9def..8d0e3334cb2 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -46,8 +46,8 @@ import litellm import litellm.litellm_core_utils import litellm.litellm_core_utils.exception_mapping_utils from litellm import get_secret_str +from litellm._litellm_uuid import uuid from litellm._logging import verbose_router_logger -from litellm._uuid import uuid from litellm.caching.caching import ( DualCache, InMemoryCache,