Self-hosted SQL analytics & dashboard platform for data-driven teams.
Connect your databases, write SQL, visualize results, and share dashboards β all in one place.
MetricFlow is a self-hosted, open-source business intelligence platform that lets you:
- π Connect to PostgreSQL, MySQL, SQL Server, SQLite, CSV, BigQuery, and Snowflake
- π§ Write SQL in a rich Monaco editor with live query execution
- π Build charts β bar, line, pie, KPI cards, and data tables
- ποΈ Compose dashboards with drag-and-drop widget layouts
- π Share and Embed dashboards publicly via secure share tokens and customizable
<iframe>snippets - π‘οΈ Granular Access Control β administrator, editor, and reader capabilities with row and column policies
- π’ Self-hosted workspace β one organization per installation with role-based access
- π Secure β AES-256 encrypted datasource credentials, JWT authentication
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 5, TypeScript, TailwindCSS v4 |
| State / Data | TanStack Query v5, Zustand v5 |
| Charts | Recharts v3 |
| SQL Editor | Monaco Editor |
| Backend | NestJS 11, TypeScript |
| ORM | Prisma 6 |
| Database | PostgreSQL 15 (primary store) |
| Auth | JWT + Passport.js, bcrypt |
| Drivers | pg, mysql2, mssql, sqlite3, csv-parse, @google-cloud/bigquery, snowflake-sdk |
| Infra | Docker Compose |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser (React 19) β
β Setup Β· Login Β· Datasources Β· SQL Editor Β· β
β Query Library Β· Dashboard Builder Β· Widget Creator β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β HTTP / REST
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β NestJS API (port 3000) β
β auth Β· organizations Β· datasource Β· queries Β· β
β query-engine Β· dashboard Β· widget β
ββββββββ¬ββββββββββββββββββββββββββββββ¬βββββββββββββββββ
β Prisma ORM β Driver per datasource
βΌ βΌ
PostgreSQL 15 PostgreSQL / MySQL / SQL Server /
(metadata store) SQLite / CSV / BigQuery / Snowflake (user data)
- One organization per installation β the setup assistant creates the organization and first owner once; public registration and additional organization creation are disabled.
- Encrypted credentials β datasource connection strings are stored AES-256 encrypted at rest; never exposed through the API.
- Query Engine β a dedicated
query-enginemodule proxies SQL execution against user datasources and returns typed{ columns, rows }payloads. - Execution Audit Log β every SQL run is recorded in the
executionstable (query, user, duration, row count, status). - Public dashboard sharing β dashboards can be toggled public and accessed via a unique
shareTokenwithout authentication.
Organization ββ< Membership >ββ User
β
βββ< Datasource
β
βββ< Query ββββββββββββββββββ< Execution
β βββ< Widget
β
βββ< Dashboard ββ< Widget
- Node.js β₯ 20
- Docker & Docker Compose (for the local PostgreSQL instance)
- npm β₯ 10
git clone https://github.com/setohe0909/metric-flow.git
cd metric-flowdocker compose up -dThis starts a PostgreSQL 15 instance on port 5432 with database metricflow.
cd backend
cp .env.example .envEdit backend/.env β minimum required variables:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/metricflow"
JWT_SECRET="your-super-secret-jwt-key"
ENCRYPTION_KEY="32-char-hex-key-for-aes-256"
PORT=3000JWT_SECRET and ENCRYPTION_KEY are mandatory, must be different, and do not
have fallback values. Generate independent random values before starting the
backend.
# Inside backend/
npm install
npx prisma migrate deploy
npx prisma generatenpm run start:dev
# API available at http://localhost:3000cd ../frontend
npm install
npm run dev
# App available at http://localhost:5173Open http://localhost:5173/setup on a new installation. The setup assistant
creates the organization and first owner exactly once. Existing installations
are marked as initialized automatically by the database migration and continue
to use /login.
metric-flow/
βββ backend/ # NestJS API
β βββ src/
β β βββ auth/ # JWT authentication and login
β β βββ setup/ # One-time installation bootstrap
β β βββ organizations/ # Org management & membership
β β βββ datasource/ # Datasource CRUD + connection test
β β βββ query-engine/ # Proxy SQL execution against user DBs
β β βββ queries/ # Saved query library
β β βββ dashboard/ # Dashboard CRUD + public sharing
β β βββ widget/ # Widget CRUD + layout persistence
β β βββ common/ # Guards, decorators, pipes
β βββ prisma/
β βββ schema.prisma # Full data model
β
βββ frontend/ # React 19 + Vite SPA
β βββ src/
β βββ features/ # Feature modules (auth, dashboards, widgetsβ¦)
β βββ pages/ # Route-level page components
β βββ components/ # Shared UI components
β βββ layouts/ # App shell & nav layout
β βββ store/ # Zustand global stores
β
βββ docker-compose.yml # Local PostgreSQL service
βββ docs/
βββ logo.png
cd backend
npm run lint # ESLint
npm run build # TypeScript build check
npm test # Unit tests (Jest)
npm run test:e2e # End-to-end tests
npm run test:cov # Coverage reportcd frontend
npm run lint # ESLint
npm run build # Vite production build- Datasource passwords and connection strings are AES-256 encrypted before being stored in PostgreSQL.
- JWT tokens are signed with the mandatory
JWT_SECRET. - Datasource credentials use the mandatory, independent
ENCRYPTION_KEY. - PostgreSQL and MySQL queries are parsed and executed in read-only transactions.
ADMINmanages users, settings, datasources, and content.EDITORmanages datasources and creates analytical content using read-only SQL.READERconsumes published analytical content and cannot administer the installation.- New and reset accounts receive a one-time temporary password and must replace it before accessing tenant resources.
- Password changes, resets, and user disabling revoke existing JWT sessions.
- Public dashboard share tokens are UUID-based and revocable by the dashboard owner.
- Never commit your
.envfile. It is listed in.gitignoreby default.
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create your feature branch:
git checkout -b feat/my-feature - Commit your changes following Conventional Commits:
git commit -m "feat: add X" - Push to your fork:
git push origin feat/my-feature - Open a Pull Request β describe what changed and why
Please read AGENTS.md for our working agreements and validation checklist before submitting a PR.
Open an issue with:
- Steps to reproduce
- Expected vs actual behavior
- MetricFlow version and OS
MetricFlow is evolving toward a hybrid BI platform: open-source and self-hosted first, with an architecture that can also support managed or hosted deployments later.
- Role-based column/row filtering per datasource
- Scheduled query execution & email delivery
- Dashboard embed via
<iframe>snippet - BigQuery and Snowflake drivers
- Initial SQL Server connector support
- SAML / SSO integration
- Dark mode toggle in the UI
- Installation bootstrap and single-workspace setup flow
- Secure datasource storage with encrypted credentials
- SQL editor, saved queries, widgets, dashboards, and sharing
- Execution audit trail and read-only SQL protections
- Row and column security policies per datasource
- Dataset refresh orchestration with retries, history, and failure surfacing
- Query result caching and invalidation controls
- Export flows for CSV, Excel, PDF, and image snapshots
- Dashboard filters, drill-down, drill-through, and cross-widget interactions
- Reusable semantic layer for metrics, dimensions, and governed business definitions
- Versioned dashboard publishing and rollback support
- SAML / SSO and SCIM-style user lifecycle management
- Multi-workspace or tenant isolation model for hosted deployments
- Secrets rotation, connection health monitoring, and background job observability
- Usage analytics, audit exports, retention controls, and governance reports
- Fine-grained admin controls for sharing, public embeds, and external access
- Backup, restore, migration, and disaster-recovery playbooks
- Public plugin or connector SDK
- Custom visualization extension model
- Admin API and automation webhooks
- Template gallery for dashboards, widgets, and datasource presets
- Contributor-ready docs for connector development and deployment patterns
MetricFlow is released under the MIT License.
MetricFlow includes a local command and a GitHub Actions workflow that run the durable TestSprite project suite alongside the backend and frontend quality checks. TestSprite remains an infrastructure adapter and does not participate in application or domain logic.
Create or select a project in TestSprite, then configure:
- Local environment:
TESTSPRITE_API_KEYandTESTSPRITE_PROJECT_ID. - GitHub Actions secret:
TESTSPRITE_API_KEY. - GitHub Actions repository variable:
TESTSPRITE_PROJECT_ID.
Never commit the API key. If a key has been shared in chat, logs, or source control, revoke it and create a replacement before using this integration.
Node.js 20 or newer is required.
export TESTSPRITE_API_KEY="your-new-key"
export TESTSPRITE_PROJECT_ID="proj_..."
npm run release:test:testspriteThe command strictly replays all durable frontend and backend tests in the TestSprite project with frontend auto-healing disabled, and writes:
reports/testsprite/testsprite-result.jsonreports/testsprite/testsprite-cli.logreports/testsprite/release-decision.md
An exit code of 0 produces a GO decision. Test failures produce NO-GO and
exit 1; missing configuration exits 2.
To run the complete local gate, use:
npm run release:checkThis starts the backend build/tests, frontend build, and TestSprite suite in
parallel. Its consolidated decision is written to
reports/pre-release/release-decision.md.
Open Actions β Pre-release verification β Run workflow. Backend validation,
frontend validation, and the TestSprite cloud suite run in parallel. The final
Release decision job blocks on any failure and publishes a summary. TestSprite
reports are retained as a workflow artifact for 30 days.
Built with β and SQL by the MetricFlow team.
