Titandocs

Operations

Health endpoints, the one metric that matters, and how staging is monitored.

Health endpoints

RouteChecksUse for
/healthzProcess is upLiveness probe
/readyzDB reachable + engine reachable + max engine seqReadiness probe, on-call triage
/metricsPrometheusDashboards, alerting
curl -s http://localhost:4000/readyz | jq
{
  "ok": true,
  "db": "ok",
  "engine": "ok",
  "engineMaxSeq": 918342
}

/readyz is the endpoint that distinguishes "no positions" from "no database". Without DATABASE_URL, reads return empty lists happily — /readyz is where the degradation is visible.

The metric that matters

bff_engine_max_seq — the highest engine WAL sequence the BFF has observed.

Compare it against the indexer's own high-water mark. The gap is indexer lag:

GapMeaning
~0Healthy
Growing steadilyIndexer falling behind — reads are stale, live frames are fine
Frozen while trades happenIndexer stalled, or the SSE bridge dropped

Live WebSocket frames come straight from SSE, so live data can be correct while REST reads are stale. A user seeing a fresh order book but an empty position list is this, not a UI bug.

Config reference

VarEffect
DATABASE_URLPostgres (read-only). Unset → empty reads
ENGINE_BASE_URLDefault http://localhost:8080
ENGINE_ADMIN_TOKENBearer for the SSE firehose. Unset → no live frames
WS_ORDERBOOK_POLL_MSOrderbook snapshot poll interval
FAUCET_ENABLEDEnables POST /v1/users/:party/faucet
AUTH_DISABLEDtrue makes authenticate / requireOwnParty no-ops

ENGINE_ADMIN_TOKEN must never reach a browser. It grants the full engine admin firehose. The whole reason the BFF fans out over WebSocket instead of letting clients hit SSE directly is to keep this token server-side.

Staging monitoring

Staging is watched by a Cloudflare Worker uptime monitor plus a status agent on the server, alerting into Discord.

Worker secrets vs plain text vars. The uptime monitor's credentials must be configured as secrets, not as plain-text environment variables. Plain-text vars are readable from the dashboard and get captured in deploy logs. This has been a real footgun on this project — check it after any Worker redeploy.

Local Postgres

The server database user is titanadmin on port 5433 (not the default 5432).

The api's DATABASE_URL must match that user and port. A mismatch does not error loudly — it produces empty candle and market data, which reads as "the market is quiet" rather than "the connection is wrong".

DATABASE_URL='postgres://titanadmin:<password>@localhost:5433/titan'

Deploy checklist

Apply indexer migrations first. Confirm 0014_tpsl_v2 and 0015_fired_limit are present.

Confirm the engine is at or above c879f7f (the market=all floor).

Deploy the api. Hit /readyz and confirm db: ok, engine: ok.

Grep the logs for ordersForUser: live open-orders fetch failed — its absence is the check that the engine version floor is actually satisfied.

Deploy the interface last.

On this page