Documentation

SLOTLINE DOCS

01Overview

SLOTLINE watches Solana RPC endpoints: latency, error rate and slot lag versus a reference endpoint you choose. It stores seven days of checks in SQLite and raises threshold alerts that resolve themselves.

02Quick start

npm i
npm run dev
# → http://localhost:3000/dashboard

Add an endpoint, set it as reference, and press PROBE NOW — or let the scheduler run.

03Concepts

Reference — the endpoint every other endpoint is compared against for slot lag. Set it in the dashboard controls or via PUT /api/settings.

Commitment — processed, confirmed or finalized. Passed to getSlot for every probe.

Slot difference — ref_slot − endpoint_slot. Positive means the endpoint is behind the reference.

Windows — aggregates are computed over 5m, 1h or 24h of checks; alert evaluation always uses the last 5 minutes.

04Alerts

Four kinds, evaluated each cycle over the trailing 5 minutes:

  • · down — last 3 checks all failed
  • · latency — window p95 > threshold_latency_ms
  • · error_rate — window error % > threshold_error_rate_pct (≥5 checks)
  • · slot_diff — latest diff > threshold_slot_diff

Alerts dedupe on (endpoint, kind): a new alert is inserted only if no unresolved alert of that kind exists. When the condition clears, the open alert's resolved_ts is set.

05API reference

MethodPathDescription
GET/api/endpointsList endpoints
POST/api/endpointsAdd endpoint — body {name, url}
DELETE/api/endpoints/[id]Remove endpoint + its checks/alerts
GET/api/settingsRead settings
PUT/api/settingsPartial update; validates enum/ranges
POST/api/probeRun a probe cycle now; returns the checks
GET/api/metrics?window=5m|1h|24hPer-endpoint aggregates + status + settings
GET/api/history?endpoint=<id>&window=≤300 downsampled points
GET/api/alerts?limit=50Alerts, newest first, with endpoint name
GET /api/metrics?window=5m →
{ "endpoints": [{ "endpoint": {...}, "last": {"ts","ok","latency_ms","slot","slot_diff","error"},
    "latency_p50": 99, "latency_p95": 115, "error_rate_pct": 0,
    "avg_slot_diff": 0, "checks_count": 12, "status": "ok" }],
  "focus_endpoint_id": 2, "settings": {...} }

06Configuration

SLOTLINE_DB_PATHdata/slotline.dbSQLite file path (local mode)
SLOTLINE_INTERVAL_SEC10Default probe interval (sec)
TURSO_DATABASE_URLlibsql://… — switches DB to remote Turso
TURSO_AUTH_TOKENAuth token for TURSO_DATABASE_URL
CRON_SECRETBearer secret protecting GET /api/cron

See .env.example for the full list.

07Deployment

Self-hosted — Node ≥ 20, npm run build && npm start. The built-in scheduler probes every interval_sec. The SQLite file lives at SLOTLINE_DB_PATH (default ./data/slotline.db) — persist that directory. Run a single instance: the scheduler and the DB assume one writer.

Vercel — the in-process scheduler is disabled automatically (VERCEL env). Hobby plans allow only daily crons, so vercel.json registers a daily keep-alive (0 0 * * *) hitting GET /api/cron. Probing is on-demand: any GET /api/metrics call runs a cycle if the newest check is older than the effective interval (min 15s) — an open dashboard keeps probes flowing. For true background probing, self-host or point an external pinger at /api/cron with the CRON_SECRET bearer token (Vercel sends it automatically for cron requests). Since the filesystem is ephemeral, use Turso for the DB: set TURSO_DATABASE_URL + TURSO_AUTH_TOKEN. Deploy with vercel --prod.

vercel --prod
# env vars to set in the Vercel project:
#   TURSO_DATABASE_URL, TURSO_AUTH_TOKEN, CRON_SECRET

08Brand

graphite#0B1119Page background
panel#111A24Card / panel background
line#1F2B38Borders
glacier#7FD1F7Accent / OK status
chalk#F4F6F8Primary text
muted#8A9BADSecondary text
warn#F7C97FDegraded status
bad#F77F7FDown status / open alerts