Migration: Custom Gateway to LiteLLM Proxy Server
Documentation: Migration: Custom Gateway to LiteLLM Proxy Server
Migration: Custom Gateway to LiteLLM Proxy Server
Migration journey from custom FastAPI gateway to LiteLLM Proxy Server as the main app.
Timeline
Phase 1: Custom FastAPI (Jun 2026)
Original gateway in gateway.py:
- FastAPI app with manual Tier x Effort routing
router.py(304L) —(Tier, Effort) → Backendtablehandlers/messages.py— manual HTTP forwardingservices/forwarding.py+services/fallback.py— custom proxycore/translation.py— manual Anthropic to OpenAI translation- MiMo provider registered via monkey-patch in
ProviderConfigManager
Phase 2: LiteLLM Router as Library
litellm_router.py— singleton loadingmodel_listfrom YAMLrouter.acompletion()replaces manual forwarding- Hooks registered in
hooks/pipeline.py(pre_call, post_call) - Still a separate FastAPI app using LiteLLM as a library
Phase 3: Proxy Server as Main App (Jul 2026)
app = litellm.proxy.proxy_server.app— the proxy IS the gateway- 65+ native routes:
/v1/messages,/v1/models,/health,/ui,/key/*,/user/*,/spend/* - Custom routes added: voice WS, MCP, search, API handlers
- ~2400 lines of dead code deleted
- Functional admin UI with PostgreSQL
Critical Discoveries
CONFIG_FILE_PATH
The proxy reads CONFIG_FILE_PATH at startup, NOT LITELLM_CONFIG_PATH.
This was the bug that caused "Model list not initialized" for hours.
# proxy_server.py, linha ~786:
env_config_yaml = get_secret_str("CONFIG_FILE_PATH")
if env_config_yaml is not None and os.path.isfile(env_config_yaml):
llm_router, llm_model_list, general_settings = await proxy_config.load_config(
router=llm_router, config_file_path=env_config_yaml
)
Prisma + PostgreSQL
- LiteLLM's schema.prisma uses
provider = "postgresql"— SQLite doesn't work prisma generateneeds to run with thelitellm_proxy_extrasschemalibatomic1required in Dockerfile (Node.js binaries)- Migrations:
prisma migrate deploycreates 71 tables
Model list in YAML vs model_info
model_listin config YAML defines the modelsmodel_infoin each entry defines capabilities (supports_vision, supports_function_calling, supports_1m)- Proxy serves
/v1/modelsin OpenAI format; middleware translates to Anthropic - Capabilities derived from
model_info+ tier (haiku→low/med, sonnet→+high, opus→all)
Admin UI
- Served at
/uiby the proxy - Login:
UI_USERNAME/UI_PASSWORDfrom .env - Internal routes (
/v2/model/info,/model/cost_map/source,/key/list,/spend/logs/ui) allowed_routesis an Enterprise feature — remove to avoid blocking internal routes
MiMo Provider
Registered BEFORE the proxy app import:
from providers.mimo import register_mimo_provider
register_mimo_provider() # patch ProviderConfigManager
import litellm.proxy.proxy_server
app = litellm.proxy.proxy_server.app
MiMoAnthropicMessagesConfig:
- Uses
x-api-keyheader (notAuthorization: Bearer) - API base:
https://token-plan-sgp.xiaomimimo.com/anthropic - Strips
[1m]from model name before sending - Full URL:
.../anthropic/v1/messages
DeepSeek Provider:
- Uses
deepseek/deepseek-v4-pro(notdeepseek/anthropic/) - The
/anthropic/prefix in model name was rejected by the API - API base:
https://api.deepseek.com/anthropic
References
- fitalabs-gateway-1p-jornada — overview
- fitalabs-gateway-modelos — model configuration
- fitalabs-gateway-modelos — original routing table