Skip to content

Architecture & tech stack

PulseDeck is a small, conventional stack with one external dependency (PostgreSQL) and one optional one (Redis). Nothing exotic to operate.

Redis optional · multi-replica fan-out Agent script · automation API · Fastify validate (Zod) persist · serve PostgreSQL reports · retention Web · React dashboards · live feed POST /reports SSE
Agents POST reports over HTTP; the API validates and stores them, then pushes live updates to the web app over SSE.

A pnpm workspace:

PathWhat it is
apps/apiThe HTTP server — ingestion, auth, reads, realtime, retention.
apps/webThe single-page web app.
packages/schemaThe report wire contract (shared by API, web, and agents).
packages/sdkTyped agent helper (reference; the HTTP API is the contract).
packages/demoA complete reference agent that dogfoods the public protocol.
  • APIFastify 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.
  1. An agent POSTs a report to the API over plain HTTP.
  2. The API authenticates the source, validates the payload against the Zod schema, and persists it to Postgres. Reports are immutable.
  3. Metric values are extracted on write so dashboards can query time series cheaply.
  4. 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.

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.

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.