Architecture & tech stack
PulseDeck is a small, conventional stack with one external dependency (PostgreSQL) and one optional one (Redis). Nothing exotic to operate.
Monorepo layout
Section titled “Monorepo layout”A pnpm workspace:
| Path | What it is |
|---|---|
apps/api | The HTTP server — ingestion, auth, reads, realtime, retention. |
apps/web | The single-page web app. |
packages/schema | The report wire contract (shared by API, web, and agents). |
packages/sdk | Typed agent helper (reference; the HTTP API is the contract). |
packages/demo | A complete reference agent that dogfoods the public protocol. |
Tech stack
Section titled “Tech stack”- API — Fastify on Node.js 22, Drizzle ORM over PostgreSQL 16, better-auth for sessions/OAuth, and Zod for schema validation. Optional Redis for multi-replica realtime.
- Web — React 19 with TanStack Router + Query, Radix UI primitives, Tailwind CSS, and Recharts, built with Vite.
- Schema — pure TypeScript/Zod, versioned (
SCHEMA_VERSION = "1.0"). One source of truth validates ingestion on the server and informs the UI and agents.
How data flows
Section titled “How data flows”- An agent
POSTs a report to the API over plain HTTP. - The API authenticates the source, validates the payload against the Zod schema, and persists it to Postgres. Reports are immutable.
- Metric values are extracted on write so dashboards can query time series cheaply.
- The API pushes the new report to connected web clients over SSE; clients without SSE poll instead.
Database migrations are applied automatically when the API boots — there is no separate migration step.
Realtime
Section titled “Realtime”The API exposes a per-workspace Server-Sent Events stream. A heartbeat every
25 seconds keeps the connection alive through proxies (see the SSE proxy
settings in Self-hosting). For a single instance this
works with no extra infrastructure. To run multiple API replicas, set
REDIS_URL: replicas fan ingestion events to each other over Redis pub/sub. If
Redis is unavailable the API logs a warning and degrades to single-instance
behavior — it never blocks.
Retention
Section titled “Retention”When RETENTION_DAYS > 0, a periodic sweep deletes reports older than the
window. The sweep takes a Postgres advisory lock, so across multiple
replicas at most one runs per tick (the others simply skip — no queue, no double
delete). The timer never blocks process shutdown. RETENTION_DAYS = 0 keeps
everything forever.