64 docs indexed

Postgres Schema

All Postgres tables used by obleth, their columns, and the migration file that introduced each.

The base schema lives in schema/postgres/0001_init.sql. Incremental migrations are applied in order:

FileWhat it adds
schema/postgres/0001_init.sqlFull initial schema (all tables and indexes)
schema/postgres/0002_tracing_flag.sqltracing_enabled column on tenants and api_keys

Every statement is idempotent (create … if not exists / add column if not exists) and is applied automatically when the gateway boots, so all files are safe to re-run against an existing database.

Tables

tenants

Stores all tenants.

ColumnTypeNotes
idUUID PRIMARY KEY
nameTEXT NOT NULL UNIQUEHuman-readable name
weightBIGINT NOT NULL DEFAULT 100Fairshare weight (>= 1)
tokens_per_minuteBIGINT NOT NULL DEFAULT 60000TPM token-bucket rate (>= 0)
max_in_flightBIGINTOptional per-tenant concurrency cap; null = only the global limit applies
fairshare_groupTEXT NOT NULL DEFAULT 'default'FK → fairshare_groups.name
descriptionTEXT NOT NULL DEFAULT ''Operator note
organizationTEXT NOT NULL DEFAULT ''Optional org metadata
contact_emailTEXT NOT NULL DEFAULT ''Optional contact metadata
statusTEXT NOT NULL DEFAULT 'active'active, suspended, or archived — only active admits traffic
tracing_enabledBOOLEAN NOT NULL DEFAULT falseWhen true, every request from any key in this tenant is span-traced to the ClickHouse spans table (added by 0002_tracing_flag.sql)
timezoneTEXT NOT NULL DEFAULT 'UTC'IANA timezone for access windows
active_fromTIMESTAMPTZOptional activation start; null = no bound
active_untilTIMESTAMPTZOptional expiry cutoff; null = no bound
weekly_windowsJSONBRecurring windows [{day:0-6, start_min, end_min}]; null/empty = any time
budget_tokensBIGINTOptional cumulative token cap for the term
budget_cost_usdDOUBLE PRECISIONOptional cumulative USD cap for the term
budget_periodTEXTlifetime, monthly, or term
budget_started_atTIMESTAMPTZWhen the current term began
allowed_modelsJSONBOptional model-name allowlist; null/empty = all models permitted
created_atTIMESTAMPTZAuto-set
updated_atTIMESTAMPTZAuto-updated

Indexed by fairshare_group and by status (partial, where status <> 'active').

api_keys

Stores API key hashes. The raw key is never stored.

ColumnTypeNotes
idUUID PRIMARY KEY
tenant_idUUID NOT NULLFK → tenants.id (ON DELETE CASCADE)
nameTEXT NOT NULLDisplay name
key_prefixTEXT NOT NULLFirst 18 chars (safe to display)
key_hashTEXT NOT NULL UNIQUESHA-256 of the full secret
disabledBOOLEAN NOT NULL DEFAULT false
tracing_enabledBOOLEAN NOT NULL DEFAULT falseWhen true, requests using this key are span-traced to the ClickHouse spans table; overrides the tenant default when set per-key (added by 0002_tracing_flag.sql)
created_atTIMESTAMPTZ

Indexed by tenant_id (api_keys_tenant_id_idx).

models

Model registry: client-facing names mapped to upstream OpenAI-compatible endpoints.

ColumnTypeNotes
idUUID PRIMARY KEY
model_nameTEXT NOT NULL UNIQUEName used in client requests
descriptionTEXT NOT NULL DEFAULT ''Operator-facing model description
model_typeTEXT NOT NULL DEFAULT 'chat'Modality: chat, embedding, audio_transcription, audio_speech, or image
upstream_modelTEXTModel name sent to upstream
api_baseTEXTPer-model upstream override (provider base ending in /v1)
api_keyTEXTInjected upstream credential
input_cost_per_tokenFLOAT8For billing (chat, embedding)
output_cost_per_tokenFLOAT8For billing (chat)
cost_per_imageFLOAT8 NOT NULL DEFAULT 0Per-image billing (image, × n)
cost_per_audio_secondFLOAT8 NOT NULL DEFAULT 0Per-audio-second billing (audio_transcription; reserved)
cost_per_characterFLOAT8 NOT NULL DEFAULT 0Per-character billing (audio_speech)
context_windowBIGINT
admission_weightFLOAT8 DEFAULT 1.0Scales fairshare cost
max_in_flightBIGINTOptional per-model in-flight cap; null = no cap
capacity_modeTEXT NOT NULL DEFAULT 'static'static or tuned — how max_in_flight was chosen
capacity_tuned_atTIMESTAMPTZWhen auto-tune last applied a slot count; null until tuned
supports_function_callingBOOLEAN NOT NULL DEFAULT false
supports_system_messagesBOOLEAN NOT NULL DEFAULT true
supports_response_schemaBOOLEAN NOT NULL DEFAULT falseRequired for JSON-schema requests in auto routing
supports_tool_choiceBOOLEAN NOT NULL DEFAULT falseRequired for tool_choice requests in auto routing
tagsJSONB NOT NULL DEFAULT '[]'Auto-router tags (fixed vocabulary)
boonsJSONB NOT NULL DEFAULT '[]'Per-model gateway boons opted into (fixed vocabulary: vision, structured_output, compression)
tool_serversJSONB NOT NULL DEFAULT '[]'Registered MCP servers whose tools this model may use (gateway tool loop; operator-defined names)
enabledBOOLEAN DEFAULT true
cache_enabledBOOLEAN DEFAULT falseResponse cache toggle
cache_ttl_secsBIGINTCache TTL
request_timeout_secsBIGINTPer-request upstream timeout; null = use OBLETH_UPSTREAM_TIMEOUT_SECS
max_retriesBIGINT NOT NULL DEFAULT 0Extra attempts per endpoint on retryable failures
retry_backoff_msBIGINT NOT NULL DEFAULT 200Base retry backoff (exponential, capped)
endpoint_selection_modeTEXT NOT NULL DEFAULT 'failover'failover, load_balance, or session_hash across endpoints
energy_slots_per_nodeBIGINT NOT NULL DEFAULT 0Concurrent requests that saturate one node (energy accounting); 0 = opted out
health_checks_enabledBOOLEAN DEFAULT trueScheduled model health checks
health_alerts_enabledBOOLEAN DEFAULT trueSlack alerts for this model
health_check_interval_secsBIGINT DEFAULT 900Per-model check interval
health_failure_thresholdBIGINT DEFAULT 2Consecutive failures before alerting
health_maintenance_untilTIMESTAMPTZSuppress alerts while active
health_maintenance_noteTEXTOperator note for maintenance
health_statusTEXT DEFAULT unknownLatest status
health_consecutive_failuresBIGINT DEFAULT 0Current failure streak
health_alert_stateTEXT DEFAULT okAlert state (ok or firing)
health_next_check_atTIMESTAMPTZNext scheduled check time
health_last_checked_atTIMESTAMPTZLatest check timestamp
health_last_latency_msBIGINTLatest check latency
health_last_http_statusBIGINTLatest upstream/proxy status
health_last_messageTEXTSanitized latest check summary
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

model_health_checks

Append-only history of model health probes.

ColumnTypeNotes
idBIGSERIAL PRIMARY KEY
model_idUUID NOT NULLFK → models.id (ON DELETE CASCADE)
checked_atTIMESTAMPTZProbe timestamp
triggerTEXTscheduled, manual, or bulk
statusTEXThealthy, degraded, unhealthy, or skipped
latency_msBIGINTEnd-to-end proxy latency
http_statusBIGINTHTTP status from the proxy/upstream
messageTEXTSanitized summary
response_excerptTEXTSanitized body excerpt for failures

model_endpoints

One row per upstream cluster that a model can be routed to. A model with no rows here uses its own api_base/api_key (legacy single-upstream path); with rows, the data plane routes across the enabled, healthy ones using the model's endpoint_selection_mode. See Reliability & Failover.

ColumnTypeNotes
idUUID PRIMARY KEY
model_idUUID NOT NULLFK → models.id (ON DELETE CASCADE)
nameTEXT NOT NULLUnique per model (UNIQUE (model_id, name))
api_baseTEXT NOT NULLUpstream base ending in /v1
api_keyTEXTInjected upstream credential (encrypted at rest); inherits the model key when null
priorityBIGINT NOT NULL DEFAULT 100Lower is tried first in failover mode
weightBIGINT NOT NULL DEFAULT 100Traffic share in load_balance mode
enabledBOOLEAN NOT NULL DEFAULT trueDisabled endpoints are removed from rotation
health_statusTEXT NOT NULL DEFAULT 'unknown'Latest per-endpoint probe status
consecutive_failuresBIGINT NOT NULL DEFAULT 0Current failure streak
alert_stateTEXT NOT NULL DEFAULT 'ok'Alert state
last_checked_atTIMESTAMPTZLatest probe timestamp
last_latency_msBIGINTLatest probe latency
last_http_statusBIGINTLatest probe HTTP status
last_messageTEXTSanitized latest probe summary
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

Indexed by model_id (model_endpoints_model_idx).

fairshare_groups

Scheduler groups for hierarchical mode. A default group (weight 100) is seeded on first boot.

ColumnTypeNotes
nameTEXT PRIMARY KEYGroup name
weightBIGINT NOT NULL DEFAULT 100Group-level weight (>= 1)
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

mcp_servers

MCP server registry. obleth reverse-proxies these through its auth + audit layer.

ColumnTypeNotes
idUUID PRIMARY KEY
nameTEXT NOT NULL UNIQUEReached at /mcp/{name}
upstream_urlTEXT NOT NULLSSRF-validated upstream base
auth_headerTEXTInjected auth header value (encrypted at rest)
enabledBOOLEAN DEFAULT true
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

audit_log

Append-only record of all Management API mutations.

ColumnTypeNotes
idBIGSERIAL PRIMARY KEY
tsTIMESTAMPTZ NOT NULL DEFAULT now()When the action occurred
actorTEXT NOT NULLWho performed it (e.g. admin)
actionTEXT NOT NULLe.g. create_tenant, delete_key
entity_typeTEXT NOT NULLe.g. tenant, api_key
entity_idTEXT NOT NULLID of the affected entity
detailJSONB NOT NULL DEFAULT '{}'Structured detail payload

Indexed by ts desc (audit_log_ts_idx), by actor, ts desc (audit_log_actor_idx), and by entity_type, entity_id, ts desc (audit_log_entity_idx) so filtering the trail by who acted or which entity was touched stays fast as the log grows.

app_settings

Key-value store for runtime-reloadable gateway settings. Holds the alerting configuration (Slack webhook + SMTP email) under key alerts, the auto_router classifier settings, the usage-retention window, the model-boon settings (boons), the Slurm provisioner connection (slurm), and the energy accounting configuration (energy). New fields are stored as JSON so they need no schema change.

ColumnTypeNotes
keyTEXT PRIMARY KEYSetting name (e.g. alerts, auto_router)
valueJSONB NOT NULLSetting payload
updated_atTIMESTAMPTZ NOT NULL DEFAULT now()Auto-updated

Applying the schema

The gateway applies all schema files under schema/postgres/ in lexicographic order on boot — there is no per-version migration table to query. All statements are idempotent, so re-running against an existing database is safe. To inspect the live schema, read it from Postgres directly:

-- List obleth's tables
\dt

-- Describe a table
\d+ tenants