LiteLLM journey: DB mode — 3 tables, config.yaml overlay, 60s auto-reload
สารบัญ
- TL;DR
- 1. 3 tables หลัก — เก็บอะไรที่ไหน
LiteLLM_Config— settings ทั้งหมดLiteLLM_ProxyModelTable— modelsLiteLLM_SpendLogs— tracking- Tables อื่นๆ (ไม่ใช้บ่อย)
- 2. config.yaml vs DB — overlay order (Insight ใหม่)
- ในทางปฏิบัติ
- Example (จริงที่ผมเจอ)
- 3. Hierarchy —
router_settings>litellm_settings - 4. 60s auto-reload — scope จาก Part 1 + 2 สรุป
- 5. Auto-register — เพิ่ม model ผ่าน UI ก็ได้
- 6. Production tip — disable spend_logs เมื่อไม่ใช้
- สรุป
- อ้างอิง
"ผม assume ว่า config.yaml เป็น source of truth — จนกว่าจะไปอ่าน docs เจอบรรทัดนี้: 'DB rows overlay config.yaml on every refresh'"
Part 1 ผมเล่าเรื่อง drop_params ต้อง recreate
Part 2 ผมเล่าเรื่อง 3 flags ที่ใช้บ่อย
Part 3 คือภาพของ DB mode — เก็บอะไรไว้ที่ไหน, config.yaml กับ DB ตัวไหนมีลำดับสูงกว่า, auto-reload ทำอะไรได้บ้าง
TL;DR
ตอนผมตั้ง LiteLLM ครั้งแรก — assume ว่า "แก้ config.yaml = แก้ทุกอย่าง" มันไม่ใช่ — DB rows overlay config.yaml ทุกครั้งที่ refresh
3 tables หลักที่ LiteLLM ใช้:
LiteLLM_Config— settings ทั้งหมด (litellm / router / general / environment)LiteLLM_ProxyModelTable— model + deployment configsLiteLLM_SpendLogs— per-request tracking
Insight ใหม่ที่หลายคนไม่รู้: ลำดับความสำคัญเมื่อ config.yaml กับ DB ขัดแย้งกัน
config.yaml (base) → DB rows (overlay)
DB มีลำดับสูงกว่าเมื่อค่าขัดแย้ง
1. 3 tables หลัก — เก็บอะไรที่ไหน
LiteLLM_Config — settings ทั้งหมด
เก็บเป็น JSONB แยกตาม section:
SELECT param_name, param_value
FROM "LiteLLM_Config";
| param_name | เนื้อหา |
|---|---|
litellm_settings | drop_params, cache, callbacks, success_callback, failure_callback |
router_settings | routing_strategy, num_retries, allowed_fails, cooldown_time |
general_settings | master_key, disable_env_credential_login, alerting |
environment_variables | API keys ของพวก model providers |
→ ทุก flag ที่เขียนใน config.yaml มี row อยู่ใน LiteLLM_Config
LiteLLM_ProxyModelTable — models
เก็บ model_name + litellm_params เป็น JSON:
| Column | เนื้อหา |
|---|---|
model_name | virtual name เช่น M3-CHATx-256k |
litellm_params | model, api_base, api_key, rpm, tpm, max_input_tokens |
model_info | metadata |
ทุก model ที่ลูกค้าเรียกผ่าน proxy = row ในตารางนี้ (16 models ตอนนี้)
LiteLLM_SpendLogs — tracking
ทุก request = 1 row:
SELECT
count(*) FILTER (WHERE cache_hit = true) AS hits,
count(*) FILTER (WHERE cache_hit = false) AS misses,
count(*) FILTER (WHERE cache_hit IS NULL) AS untracked
FROM "LiteLLM_SpendLogs";
| Field | เนื้อหา |
|---|---|
cache_hit | true / false / NULL (record เก่า) |
model | deployment model |
spend | cost ที่คิด |
startTime, endTime | duration |
prompt, completion | token + content (เก็บ debug) |
ผมเก็บ ~17,000 rows ใน 2 สัปดาห์ = data ที่น่าเชื่อถือพอทำ analysis
Tables อื่นๆ (ไม่ใช้บ่อย)
จาก docs.db_info:
| Category | Table | ใช้เมื่อ |
|---|---|---|
| Auth | LiteLLM_VerificationToken | virtual keys + RBAC |
| Budget | LiteLLM_BudgetTable | rate limits per user/team |
| RBAC | LiteLLM_OrganizationTable | org-level configs |
LiteLLM_TeamTable | team-level settings | |
LiteLLM_UserTable | individual user | |
LiteLLM_EndUserTable | end-user tracking |
ตอนนี้ผมไม่ได้ใช้ RBAC + virtual keys — ใช้แค่ master_key ตรงๆ — แต่ถ้าจะ scale ต้องใช้
2. config.yaml vs DB — overlay order (Insight ใหม่)
จาก docs official:
"On startup and on every config refresh, the proxy loads your config.yaml first and then overlays the database rows for
general_settings,router_settings,litellm_settings, andenvironment_variables"
ดังนั้น:
1. config.yaml → base
2. DB rows → overlay (DB มีลำดับสูงกว่า)
ในทางปฏิบัติ
ลำดับ practical ของผม:
- ตั้งค่า config.yaml ครั้งแรก (initial setup)
- แก้ค่าผ่าน UI admin /
psqlUPDATE — DB rows จะเก็บ - config.yaml จะถูก overwritten เมื่อมีการ save ผ่าน UI
ดังนั้น ถ้าแก้ config.yaml ด้วยมือ หลังจากเคยแก้ผ่าน UI ค่าใน config.yaml จะถูก UI แทนที่
Example (จริงที่ผมเจอ)
ผมเขียน failure_callback: ["database"] ใน config.yaml
แต่ UI ก็มี failure_callback: ["database"] แล้ว
→ LiteLLM merge แล้วเกิดซ้ำ log 2 ครั้ง
Rule: ถ้าจะแก้ — เลือกที่เดียว (UI หรือ config.yaml) ไม่ใช่ทั้งสองที่
3. Hierarchy — router_settings > litellm_settings
จาก docs:
"If you see overlapping values, settings on
router_settingswill override those onlitellm_settings"
ยกตัวอย่าง:
litellm_settings:
num_retries: 5 # จะถูก override
router_settings:
num_retries: 2 # priority สูงกว่า litellm_settings
→ ลำดับชั้น: router_settings > litellm_settings > general_settings
ในตอนนี้ผมตั้ง num_retries: 2 ใน router_settings (DB) — เลยไม่ต้องไปยุ่งใน litellm_settings
4. 60s auto-reload — scope จาก Part 1 + 2 สรุป
proxy_config_reload_interval_seconds (default 60s) job 3 อย่าง:
| Job | Scope | Auto-reload |
|---|---|---|
check_periodic_reloads | model cost map, anthropic beta headers | ✅ |
get_credentials | DB credentials + virtual keys | ✅ |
add_deployment | models จาก LiteLLM_ProxyModelTable | ✅ |
ที่ไม่ apply (ต้อง recreate):
drop_paramsrouting_strategy- Image upgrade
- Critical callbacks
ผมเคยทำเรื่องนี้เต็มใน Part 1 + 2 แล้ว — link อยู่ข้างบน
5. Auto-register — เพิ่ม model ผ่าน UI ก็ได้
# ผ่าน UI admin panel: Settings > Models
# ใส่ model_name + litellm_params
# Save
# → LiteLLM apply ทันที (60s)
ไม่ต้องแก้ config.yaml ไม่ต้อง recreate
ครั้งหนึ่งที่ผมทำ: เพิ่ม model ใหม่ qwen3.8-27b-kongvut (self-host vLLM)
- ไป UI → Models → Add model
- ใส่
model_name: qwen3.8-27b-kongvut - ใส่
litellm_params: { api_base: http://..., rpm: ... } - Save → auto-register ทันที
- ทดสอบ:
curl /v1/chat/completions -d '{"model":"qwen3.8-27b-kongvut"...}'→ 200
แต่ ถ้าจะ set default/general_settings (เช่น master_key, alerting) → แก้ config.yaml ดีกว่า (DB UI ไม่ให้แก้)
6. Production tip — disable spend_logs เมื่อไม่ใช้
ถ้าไม่ใช้ SpendLogs (เช่น dev environment) — disable:
general_settings:
disable_spend_logs: true
หรือ
general_settings:
disable_error_logs: true
ประหยัด disk + เร็วขึ้น — แต่ผม เปิดไว้ เพราะต้อง debug
สรุป
| Table | เก็บอะไร |
|---|---|
LiteLLM_Config | settings JSONB (litellm/router/general/env) |
LiteLLM_ProxyModelTable | model + litellm_params |
LiteLLM_SpendLogs | per-request tracking |
3 lessons จาก web research ที่ผมเพิ่งเรียนรู้:
- config.yaml เป็น base, DB rows overlay — DB มีลำดับสูงกว่าเมื่อค่าขัดแย้ง
router_settings>litellm_settings(hierarchy ที่ชัดเจน)- UI สามารถ auto-register model ใหม่ได้ — ไม่ต้องแก้ config.yaml
ทำไมต้องรู้เรื่องนี้? เพราะถ้าแก้ config.yaml + DB ขัดแย้งกัน โดยไม่รู้ว่า DB มีลำดับสูงกว่า → งง สองชั่วโมง ได้ — เหมือน Part 1
Part 4 → vLLM integration + streaming + reasoning_effort edge case
อ้างอิง
- LiteLLM — configs (config.yaml เป็น base) — เอกสารที่บอกว่า "DB rows overlay config.yaml"
- LiteLLM — db_info (full tables) — รายการ tables ครบ
- LiteLLM — config_settings — ทุก flag + hierarchy
- LiteLLM — production best practices — disable_spend_logs + bound DB connections
- LiteLLM — proxy_config_reload_interval_seconds — 3 jobs ของ auto-reload
- schema.prisma — full DB schema — table ทั้งหมดใน Postgres
- Part 1 — drop_params recreate — prerequisite
- Part 2 — 3 flags — prerequisite
เนื้อหานี้มีประโยชน์ไหม? ช่วยสนับสนุนค่ากาแฟให้ผู้เขียนสักแก้ว
Buy Me a Coffee