Know the moment your API breaks.
Live request metrics, error tracking, and AI-written incident summaries — wired up with one line of middleware.
Open source. Self-hostable. No agents, no sidecars.
Quick Start · Features · Screenshots · Architecture · SDKs · Roadmap
Liveboard is a self-hostable API observability platform — the open-source pieces you'd otherwise assemble from Datadog and Sentry. Drop one line of middleware into an Express or FastAPI app and get live request metrics, per-endpoint latency percentiles, error tracking, and AI-generated incident summaries — all streaming in real time over WebSockets/SSE.
- 60-second onboarding —
npm install liveboard-sdkorpip install liveboard-sdk, one line of middleware, data on the dashboard in under 90 seconds. - User-centric observability — every event is tagged with
user_id, so you can see exactly which users are hitting errors, not just aggregate rates. - AI incident summaries — a rolling z-score detector flags anomalies in error rate and p99 latency, then an LLM (Cerebras
llama-3.3-70b) writes a plain-English summary of what happened. - Built for throughput — events land in a Redis Stream and a consumer-group worker bulk-writes them into TimescaleDB with the
COPYprotocol, sized for 120K events/min on one box. - Multi-tenant from day one — organizations, per-project API keys, and Postgres Row-Level Security as a database-level isolation backstop.
| 📊 Live dashboard | Request volume, stacked 2xx/4xx/5xx response codes, animated stat cards with sparklines, and a tailing request log — all pushed over WebSockets/SSE as traffic happens. |
| 🔎 Endpoint explorer | Sortable per-route table with p50/p95/p99 latency, error rate and a derived health score, filterable by route and HTTP method. |
| 🤖 AI anomaly detection | Rolling 24h z-score on error rate & p99 latency; anomalies trigger a rate-limited, deduplicated LLM incident summary (Cerebras llama-3.3-70b). |
| ⚡ Real-time everything | Socket.io for live metrics + incidents, SSE with Last-Event-ID resume for the live log tail — zero missed events on reconnect. |
| 🏢 Multi-tenant by default | Organizations, memberships, and per-project API keys with Postgres Row-Level Security as a DB-level tenant-isolation backstop. |
| 🔐 Google OAuth + sessions | NextAuth/Auth.js sign-in; the browser never sees a raw ingest key — reads go through a session-scoped BFF proxy. |
| 📦 Two official SDKs | JavaScript/TypeScript (Express) and Python (FastAPI/ASGI), both with automatic route normalisation and background batching that never blocks your app. |
The whole stack — Postgres/TimescaleDB, Redis, the ingest API, the aggregation worker, and the dashboard — comes up with one command.
git clone https://github.com/ryzrr/liveboard.git
cd liveboard
# Copy the env template and fill in every REQUIRED_change_me value.
# openssl rand -hex 32 is perfect for the secret fields.
cp .env.example .env
cd infra
docker compose --env-file ../.env up --build| Service | URL |
|---|---|
| Dashboard | http://localhost:3000 |
| Ingest API + Swagger docs | http://localhost:8000/docs |
| Postgres (TimescaleDB) | localhost:5432 (bound to 127.0.0.1) |
| Redis | localhost:6379 (bound to 127.0.0.1) |
Sign in, and Liveboard auto-provisions your personal organization, a default project, and an API key — no manual setup step. Drop the key into one of the SDKs below and watch events land on the dashboard in real time.
Without
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETset, keepDISABLE_DEV_LOGIN=falselocally to sign in with any email for testing. Always setDISABLE_DEV_LOGIN=trueoutside local development — see.env.examplefor the full, documented list of variables.
Both SDKs batch events in the background, flush on an interval or when the buffer fills, and never throw or block your app if Liveboard is unreachable.
| JavaScript / TypeScript | Python |
|---|---|
npm install liveboard-sdkimport liveboard from "liveboard-sdk";
app.use(liveboard.middleware({ apiKey }));Works with your existing Express app. |
pip install liveboard-sdkfrom liveboard.asgi import LiveBoardMiddleware
app.add_middleware(LiveBoardMiddleware, api_key=key)Works with FastAPI and any other ASGI framework (Starlette). |
Both adapters normalise dynamic route segments (/users/507f191e... → /users/:id), echo an x-trace-id correlation header, and tag events with the authenticated user_id when they can find one — powering the endpoint explorer and per-user error breakdowns out of the box.
flowchart LR
subgraph SDKs["Client SDKs"]
JS["liveboard-sdk JS<br/>Express"]
PY["liveboard-sdk Python<br/>FastAPI / ASGI"]
end
JS -->|"x-api-key, batched events"| INGEST
PY -->|"x-api-key, batched events"| INGEST
INGEST["FastAPI Ingest<br/>POST /v1/ingest"] --> STREAM[["Redis Streams<br/>events:project_id"]]
STREAM --> WORKER["Aggregation Worker<br/>asyncpg COPY, at-least-once"]
WORKER --> DB[("TimescaleDB<br/>events · events_1min · incidents")]
METRICS["Metrics Worker<br/>1s tick"] --> DB
METRICS -->|pub/sub| RT["Socket.io + SSE"]
ANOMALY["Anomaly Worker<br/>z-score + Cerebras LLM"] --> DB
ANOMALY -->|pub/sub| RT
DB --> BFF["Next.js BFF<br/>session-scoped read proxy"]
RT --> WEB["Next.js Dashboard"]
BFF --> WEB
| Layer | Tech |
|---|---|
| Client SDKs | TypeScript → npm · Python 3.9+ → PyPI |
| Ingest API | FastAPI + Uvicorn (async) |
| Message bus | Redis Streams (XADD / XREADGROUP) |
| Aggregation worker | Python asyncio + TimescaleDB COPY protocol |
| AI worker | Python + Cerebras SDK (llama-3.3-70b) |
| Database | PostgreSQL 16 + TimescaleDB (hypertables, continuous aggregates, RLS) |
| Realtime | Socket.io (WebSocket) + Server-Sent Events |
| Frontend | Next.js App Router + Tailwind + Framer Motion + Recharts |
| Auth | NextAuth/Auth.js (Google OAuth) + server-only internal service token |
| Infra | Docker Compose, GitHub Actions CI |
Two auth planes, by design: SDKs write with a per-project x-api-key; the dashboard never sees one. Browser sessions read through a same-origin BFF (app/api/lb/[...path]) that checks the signed-in user's org membership before forwarding to the API with a server-only internal token — backstopped by Postgres Row-Level Security scoped to project_id, so a compromised session can't read another tenant's rows even if the app-layer check is bypassed.
Full reference with generation instructions lives in .env.example — copy it to .env before running Docker Compose. Highlights:
| Variable | Required | Notes |
|---|---|---|
POSTGRES_PASSWORD, REDIS_PASSWORD |
✅ | openssl rand -hex 32 |
API_SECRET_KEY |
✅ | Ingest master key; rejected outright if weak/default when ENVIRONMENT=production |
AUTH_SECRET |
✅ | NextAuth/Auth.js session encryption secret |
INTERNAL_SERVICE_TOKEN |
recommended | Separate BFF↔API token; falls back to API_SECRET_KEY if unset |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
for real sign-in | Required in production unless DISABLE_DEV_LOGIN=false |
CEREBRAS_API_KEY |
optional | Enables AI incident write-ups; anomaly detection still runs without it |
ALLOWED_EMAILS / ALLOWED_EMAIL_DOMAIN |
optional | Restrict sign-up; leave empty for open sign-up |
DISABLE_DEV_LOGIN |
✅ | Kill-switch for the unverified dev-login bypass — always true outside local dev |
Prefer running services natively instead of rebuilding containers on every change:
# Frontend (Next.js, Turbopack dev server)
npm install
npm run dev # http://localhost:3000
# API + worker (needs Postgres/TimescaleDB + Redis reachable — spin those
# two up with `docker compose up postgres redis` from infra/ and point
# DATABASE_URL / REDIS_URL at them)
cd apps/api
pip install -r requirements.txt
uvicorn main:app --reload --port 8000
# in a second terminal
python -m worker.main# Lint / typecheck, same checks CI runs
npm run lint && npx tsc --noEmit # frontend
cd apps/api && ruff check . # API
cd packages/sdk-js && npx tsc --noEmit && npm run build
cd packages/sdk-python && ruff check liveboard/liveboard/
├── app/ # Next.js App Router — dashboard, auth, BFF routes
│ ├── (dashboard)/ # overview · endpoints · settings
│ └── api/ # lb/[...path] BFF proxy, auth, projects, realtime-token
├── components/ # React components (charts, dashboard, endpoints, landing…)
├── hooks/ # useMetrics, useLiveLog, useWebSocket, useApiQuery, …
├── lib/ # api-client, socket, realtime helpers
├── apps/api/ # FastAPI backend
│ ├── api/routes/ # ingest · query · projects · internal
│ ├── worker/ # aggregator · metrics · anomaly (AI)
│ ├── realtime/ # socket_server · sse · pubsub · tokens
│ ├── streams/ # Redis Streams producer
│ └── migrations/ # Alembic migrations (001 → 004)
├── packages/
│ ├── sdk-js/ # liveboard-sdk (npm) — Express
│ └── sdk-python/ # liveboard-sdk (PyPI) — FastAPI / ASGI
├── infra/
│ └── docker-compose.yml # postgres · redis · api · worker · frontend
└── .env.example # every config variable, documented
Liveboard is shipped through self-hosted, multi-tenant SaaS foundations (organizations, per-project API keys, Postgres RLS tenant isolation). What's next:
- CLI (
liveboard-cli) for local onboarding and key management - Hosted Mintlify docs site — quick start, SDK reference, self-hosting guide, architecture
- Alerting: threshold rules with Slack/webhook delivery
- Public status pages with 90-day uptime history
- Distributed tracing: flame graphs and a service dependency map
- Per-tenant retention policies and plan-gated quotas
- Billing (Stripe) — free/pro tiers
- Production deploy guide (Railway for API/worker, Vercel for the dashboard)
- npm / PyPI publish of
liveboard-sdkfor outside consumers
Check open issues or open one — good-first-issue-sized SDK adapters (Fastify, Django, Flask, Go) are great starting points.
Contributions are welcome. Every PR runs the same CI as main: frontend lint + typecheck, ruff on the API, and a typecheck + build of sdk-js.
- Fork the repo and create a branch off
main - Make your change, and run the lint/typecheck commands from Local Development
- Open a PR with a clear description of what changed and why
Liveboard is MIT licensed.
