How PanDev Metrics on-prem is architected
TL;DR. PanDev Metrics on-prem is a three-component stack: a Spring backend, a React frontend, and PostgreSQL 17. The backend is the brain — everything reads and writes through it. PostgreSQL is the system of record. Redis is optional and only needed when you want to share sessions across horizontally scaled backends. This page explains how the components fit together, how a typical request flows, and how the data model isolates state inside a single organization.
The stack at a glance
PanDev Metrics on-prem deploys as three mandatory runtime components. Only the database is meant to live on its own machine; the rest co-locate comfortably on a single application host.
The reverse proxy terminates TLS and routes traffic. The backend is a Spring Boot application running on Java 17, exposing the REST API on port 8080 and an actuator on port 9090. The frontend is a static React bundle. PostgreSQL stores everything persistent. The backend caches sessions and rate-limit counters in-memory — that is sufficient in single-node mode.
Component responsibilities
Backend (Spring + Java 17)
The backend is the only component that talks to the database. It carries the full domain logic:
- Ingestion. Receives IDE plugin events, syncs Git providers, syncs task trackers, ingests CI/CD signals
- Computation. Calculates DORA metrics, IDE active time, overtime detection, productivity indicators
- Aggregation. Maintains materialized views and rolling aggregates refreshed by scheduled jobs
- API. Serves the REST endpoints used by the frontend and IDE plugins
- Authentication. Validates JWTs, authenticates against LDAP when integration is enabled
- Authorization. Resolves roles (Owner / Maintainer / Viewer) and department-scoped permissions
The backend is intentionally a single deployable. There is no microservice split inside the on-prem distribution. This keeps operations simple and lets PostgreSQL row-level security (RLS) provide a single, auditable enforcement point.
Frontend (React + Vite)
The frontend is a single-page application built with React and Vite. It is shipped as static assets and served behind the reverse proxy. All state is fetched from the backend over the REST API. The frontend contains no business logic — moving computation to the backend keeps the security boundary clean and lets the same UI work for Cloud and on-prem.
PostgreSQL 17
PostgreSQL is the system of record. It holds:
- Employees, departments, and teams
- Connected Git providers, task trackers, and CI/CD signals
- Raw events from IDE plugins and integrations
- Computed metrics and materialized aggregates
- Audit records, system settings, and license state
PanDev Metrics applies its schema and Flyway migrations automatically on backend startup. Row-level security is enabled on multi-tenant tables — the policies always evaluate to "single tenant" on on-prem, but the same enforcement layer runs as defense in depth.
Redis 7 — optional
Redis is not required on-prem. In single-node mode the backend caches sessions and rate-limit counters in its own memory — that is enough for one organization. Add Redis only if you later want to scale the backend horizontally and share sessions across instances; the current on-prem distribution does not support that topology.
How a typical request flows
A representative read request — for example, an admin opening the DORA dashboard — flows through the stack like this:
- Browser to reverse proxy over HTTPS. The proxy terminates TLS and forwards to the backend on port 8080.
- Backend resolves the JWT and looks up the caller's roles. The session lookup hits the in-process cache (or Redis, if it is deployed).
- Backend applies authorization — Owner / Maintainer / Viewer scopes filter the request to allowed departments.
- Backend queries PostgreSQL through materialized views and indexed tables. RLS policies enforce single-tenant scoping.
- Backend serializes the response and returns JSON to the frontend.
- Frontend renders the dashboard with the returned numbers.
Write paths — for example, an IDE plugin pushing an event — follow the same route but terminate at the backend's ingestion endpoints, which buffer and persist into PostgreSQL.
Isolation inside a single organization
On-prem PanDev Metrics runs one organization per installation. There is no Cloud-style multi-tenant separation. Even so, the data model still carries the tenant_id column on every relevant table, and RLS policies still apply. The reason is consistency: the same code that runs on Cloud runs on-prem, with the same enforcement. A single organization becomes a single tenant, and every query is scoped accordingly.
Inside that one tenant, isolation is logical:
- Departments group employees and define organizational hierarchy
- Teams nest inside departments
- Roles (Owner, Maintainer, Viewer) limit visibility per organization
- Department roles (Owner, Maintainer, Viewer, Finance) refine access within a department
The tenant_id column is the technical safety net. The roles and department hierarchy are the everyday access model.
Trade-offs
Every architecture choice is a trade-off. PanDev Metrics on-prem makes the following choices explicitly:
| Decision | Pro | Con |
|---|---|---|
| Single deployable backend | Simple to operate, one place to debug | No service-level isolation between subsystems |
| PostgreSQL as the system of record | Mature, well-known, easy to back up with pg_dump | One database host carries all storage |
| In-memory session cache, Redis optional | Fewer moving parts in single-node on-prem | Users have to log in again after a restart |
| RLS even on single-tenant on-prem | Defense in depth, same code as Cloud | Tiny per-query overhead |
| Vertical scaling | Predictable cost and topology | Horizontal scaling needs roadmap work |
These choices reflect what works in production today across PanDev Metrics customers.
What is not in the on-prem architecture today
A few components are present in Cloud and not yet present in on-prem:
- Multi-tenant tenancy plane — multi-organization workspaces are Cloud-only
- Google sign-in — Cloud-only; on-prem authenticates through LDAP / AD
These are not architectural gaps so much as deliberate scoping. The on-prem stack is intentionally smaller than Cloud because customers prefer fewer moving parts.
FAQ
Why is PostgreSQL on its own host?
PostgreSQL benefits from independent CPU, memory, and storage sizing. Separating it from the application host lets you scale the two profiles independently, perform database maintenance without disturbing the application, and isolate I/O patterns. For a small evaluation install you can co-locate them; for production we recommend separating them.
Can I run two backends behind a load balancer?
The on-prem distribution is single-instance per organization. Horizontal scaling is not part of the supported topology today. If you outgrow vertical scaling, contact your account manager — that conversation typically happens at hundreds-of-engineers scale.
Where do IDE plugin events live before they become metrics?
IDE plugins POST events to the backend. The backend writes raw events to PostgreSQL immediately. Aggregation jobs read those events on a schedule, build materialized views, and the dashboards read from the views. Raw events are retained — there is no retention policy today.
How does PanDev Metrics handle row-level security with one organization?
PanDev Metrics enables RLS on multi-tenant tables and runs the same policy machinery as Cloud. On-prem has exactly one tenant, so the policy resolves to "always allow within this tenant". The benefit is identical code paths across Cloud and on-prem — the same defense holds if a customer migrates from on-prem to Cloud or vice versa.
Is the architecture different on Kubernetes?
No, the components are identical — same backend, frontend, PostgreSQL (plus Redis, if enabled). The Helm chart packages the same env vars in values.yaml instead of .env. Networking is handled by Services and Ingress instead of Compose's bridge network.
Related
- How-to: Install PanDev Metrics on-prem
- Reference: System requirements
- Reference: Network and ports