Local Development

How to run obleth, the mock backend, and the control-plane dashboard locally outside Docker for fast iteration.

Running outside Docker gives you faster rebuild cycles and easier debugger attachment. You still need Redis, Postgres, and ClickHouse running somewhere — the easiest approach is to start only the datastores from Compose while running the application code natively.

Start only the datastores

cd obleth-gateway

# Start Postgres, Redis, ClickHouse only (no application services)
docker compose -f deploy/docker/docker-compose.yml \
  up postgres redis clickhouse -d

Wait for healthchecks to pass:

docker compose -f deploy/docker/docker-compose.yml ps
# All three should show "healthy"

Run the mock backend

The mock backend is a Node.js OpenAI-compatible server that simulates TTFT and token streaming without a GPU:

cd obleth-gateway
node mock-backend/server.mjs
# Listening on :8081

Run obleth

cd obleth-gateway/obleth
cargo run --release 2>&1 | tee obleth.log

With the right environment:

# PowerShell
$env:OBLETH_DATABASE_URL = "postgres://obleth:obleth@localhost:5432/obleth"
$env:OBLETH_REDIS_URL = "redis://localhost:6379"
$env:OBLETH_CLICKHOUSE_URL = "http://localhost:8123"
$env:OBLETH_UPSTREAM_BASE_URL = "http://localhost:8081"
$env:OBLETH_ADMIN_TOKEN = "dev-admin-token"
$env:OBLETH_FAIL_OPEN = "true"
$env:OBLETH_FAIRSHARE_ALGORITHM = "hierarchical"
$env:RUST_LOG = "obleth=debug,info"
cargo run
# Bash
export OBLETH_DATABASE_URL=postgres://obleth:obleth@localhost:5432/obleth
export OBLETH_REDIS_URL=redis://localhost:6379
export OBLETH_CLICKHOUSE_URL=http://localhost:8123
export OBLETH_UPSTREAM_BASE_URL=http://localhost:8081
export OBLETH_ADMIN_TOKEN=dev-admin-token
export OBLETH_FAIL_OPEN=true
export RUST_LOG=obleth=debug,info
cargo run

obleth applies its embedded schema on first boot. After a few seconds you should see:

INFO obleth_proxy: postgres connected + schema applied
INFO obleth_proxy: redis connected
INFO obleth_proxy: clickhouse connected + schema applied
INFO obleth_proxy: warmed key cache count=0
INFO obleth_proxy: listening: proxy=0.0.0.0:8080, admin=0.0.0.0:9090, metrics=0.0.0.0:9091

Run the control-plane dashboard

cd obleth-gateway/control-plane
cp .env.example .env
# Edit .env: set OBLETH_ADMIN_BASE_URL=http://localhost:9090
npm install
npm run dev
# Dashboard available at http://localhost:3000

Quick smoke test

# Create a tenant
TID=$(curl -s -X POST http://localhost:9090/api/v1/tenants \
  -H "Authorization: Bearer dev-admin-token" \
  -H "Content-Type: application/json" \
  -d '{"name":"dev","weight":100,"tokens_per_minute":100000}' | jq -r .id)

# Mint a key
SECRET=$(curl -s -X POST "http://localhost:9090/api/v1/tenants/$TID/keys" \
  -H "Authorization: Bearer dev-admin-token" \
  -H "Content-Type: application/json" \
  -d '{"name":"local"}' | jq -r .secret)

# Call the data plane
curl -s http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer $SECRET" \
  -H "Content-Type: application/json" \
  -d '{"model":"mock-model","messages":[{"role":"user","content":"hi"}],"max_tokens":16}'

Useful env vars for development

VariableDev defaultNotes
RUST_LOGinfoSet to obleth=debug,info for verbose data plane tracing
OBLETH_BROWNOUT_WAIT_MS750Lower (e.g. 100) to see brownout in tests faster
OBLETH_GLOBAL_MAX_IN_FLIGHT256Lower (e.g. 4) to force queue saturation in tests
OBLETH_FAIRSHARE_ALGORITHMhierarchicalSwitch to weighted to test flat scheduling
OBLETH_FAIL_OPENtrueSet false to test fail-closed behavior
OBLETH_OTEL_ENDPOINT(unset)Set to http://localhost:4318 if you run Jaeger locally

Running tests

cd obleth-gateway/obleth
cargo test

Tests are mostly unit tests on the fairshare algorithm, Redis scripts, and tokenizer. Integration tests require the datastores to be running.