nuthatch dev is the serve command: it backfills, follows the tip, and serves the HTTP API on
127.0.0.1:8288 (change with --listen). There is no separate server to deploy - a nest that’s
indexing is a nest that’s serving.
The surface
Three kinds of read, one process:
- Point-reads -
/entity/{id},/balance/{address}: sub-millisecond lookups against the redb hot store. - Analytical SQL -
/sql?q=…: read-only DuckDB queries over the live tip ∪ sealed history. Every event is a view named{alias}__{event}. See The SQL surface. - Introspection -
/,/tables,/schema,/nest,/metrics: what this nest is, what it holds, and how it’s doing.
The full route list is in the HTTP API reference.
The guards
/sql is guarded so a bad query can’t take the node down - these are self-protection, not knobs to
raise:
- 30-second timeout per query. A runaway is interrupted, not left to spin.
- 50,000-row cap per result (requests can ask for less via
max_rows; the MCP bridge asks for much less so an agent’s context isn’t flooded). - 64 MiB result-byte cap per query. A row cap bounds count, not width - a wide-cell
SELECTwould otherwise materialise unbounded Rust-side (outside DuckDB’s memory limit); this keeps a query inside the footprint budget. Hitting it flags the result truncated, same as the row cap. - 2 concurrent analytical queries. A third gets a
503- retry, don’t remove the gate. - SELECT/WITH only. The query surface is read-only by construction; the ingest thread is the only writer.
DuckDB itself runs with a per-query memory cap and a bounded thread count, so the analytical path stays inside the footprint budget.
Exposure
The API has no authentication. Bound to localhost (the default) that’s the point. Bound off
localhost, dev logs a loud warning: the guards bound how much a query can cost, but who may
query is your gateway’s job. Put a reverse proxy with auth in front before exposing a nest publicly.
Shutdown is graceful: on SIGTERM/SIGINT axum drains in-flight requests, the ingest task checkpoints its progress, and a restart resumes cleanly.
The admin UI
Every nest serves a built-in, read-only dashboard at /_admin/ - a single self-contained page
embedded in the binary. It talks only to the same-origin API and loads no external resources:
no CDN, no fonts, no analytics. Live activity streams over server-sent events from
/_admin/events.
Access follows the exposure rule:
- On localhost the page is open.
- Off localhost it requires
NUTHATCH_ADMIN_TOKENto be set and each request to present it as?token=…- otherwise the routes self-disable with a log line. The comparison is constant-time, so the token can’t be recovered through a timing side-channel. --no-adminremoves the routes entirely, for hosted deployments fronting their own dashboard.
In a roost, each nest’s UI lives under its prefix: /<name>/_admin/.