pg-dash
AI-native PostgreSQL health checker with 26 MCP tools for query analysis, bloat detection, migration safety, and CI integration.
README
pg-dash
The AI-native PostgreSQL health checker. Three commands cover ~90% of day-to-day use β check-migration, check, bloat. Plus 26 MCP tools for deeper analysis (including pgvector health), Streamable HTTP transport for shared team servers, and a web dashboard for continuous monitoring.
π Read the full writeup on Dev.to
Daily drivers
Three commands cover the 80/20 case. Wire them into your workflow and you'll rarely need the rest:
| Command | When to run |
|---|---|
pg-dash check-migration <file> <conn> |
Before every migration deploy (CI or pre-commit) |
pg-dash check <conn> (alias health) |
Pre-deploy checklist |
pg-dash bloat <conn> |
Scheduled cleanup (unused indexes, dead tuples) |
For anything deeper β EXPLAIN analysis, schema diff, pgvector health, activity monitoring, query stats export β see the full command list below or call the 26 MCP tools from your AI agent.
Not another monitoring dashboard β pg-dash is built to fit into your AI coding workflow:
Developer writes a migration β pg-dash check-migration (pre-flight) β
CI runs pg-dash check β Finds missing indexes β
MCP tool suggests fix β PR comment
# One-shot health check
npx @indiekitai/pg-dash check postgres://user:pass@host/db
# Check migration safety before running it
npx @indiekitai/pg-dash check-migration ./migrations/015_add_index.sql
# EXPLAIN ANALYZE a slow query in the terminal
npx @indiekitai/pg-dash explain "SELECT * FROM orders WHERE user_id = 1" postgres://...
# Real-time lock + long-query monitor (Ctrl+C to exit)
npx @indiekitai/pg-dash watch-locks postgres://...
# Analyze slow queries from pg_stat_statements
npx @indiekitai/pg-dash slow-queries postgres://... --limit 20 --min-calls 5
# Analyze table/index bloat
npx @indiekitai/pg-dash bloat postgres://...
# Compare two environments (local vs staging)
npx @indiekitai/pg-dash diff-env --source postgres://localhost/db --target postgres://staging/db
# AI assistant (Claude/Cursor) via MCP
pg-dash-mcp postgres://user:pass@host/db
# CI pipeline with diff
npx @indiekitai/pg-dash check $DATABASE_URL --ci --diff --format md
Philosophy
Developer tools are use-and-go. You don't stare at a PostgreSQL dashboard all day. You run a check, fix the issues, and move on. pg-dash embraces this:
- Health check β Find problems, get actionable SQL fixes, done
- MCP tools β Let your AI assistant query and fix your database directly (unique β pganalyze/pgwatch don't have this)
- CI integration β Catch issues automatically on every migration, not when production is on fire
- Smart diff β See what changed since last run, track your progress
The Dashboard is there when you need it. But the real power is in the CLI, MCP, and CI.
Why pg-dash?
| Tool | Price | Setup | AI-native | CI-ready |
|---|---|---|---|---|
| pganalyze | $149+/mo | SaaS signup | β | β |
| Grafana+Prometheus | Free | 3 services | β | β |
| pgAdmin | Free | Complex UI | β | β |
| pg-dash | Free | One command | 25 MCP tools | --ci --diff |
Security: SQL Safety by Design
Note: The official Anthropic PostgreSQL MCP server has a known SQL injection vulnerability that bypasses its read-only transaction wrapper. pg-dash takes a different approach.
pg-dash enforces SQL safety at multiple layers:
- Read-only by default β All MCP query tools run inside
SET TRANSACTION READ ONLYwith parameterized queries. No raw SQL passthrough. - Strict write allowlist β The
pg_dash_fixtool only executes pre-approved operations:VACUUM,ANALYZE,REINDEX,CREATE INDEX CONCURRENTLY,DROP INDEX CONCURRENTLY. Everything else is rejected. - No arbitrary SQL execution β Unlike servers that expose a generic
querytool, pg-dash exposes purpose-built tools (pg_dash_health,pg_dash_explain,pg_dash_bloat, etc.) that construct their own SQL internally. - Connection string isolation β Each MCP session is bound to the connection string provided at startup. No tool can connect to a different database.
Features
π Real-time Monitoring
- Live connection count, TPS, cache hit ratio, DB size
- Time-series charts with range selector (5m β 7d)
- WebSocket-powered auto-refresh
- Active query list with cancel support
- π UI available in English and δΈζ (simplified Chinese); per-browser preference saved to localStorage
π₯ Health Advisor
- 46+ automated checks across performance, maintenance, schema, and security
- A-F health grade with category breakdown
- One-click fixes β not just "here's what's wrong" but "click to fix it"
- SQL allowlist (only safe operations: VACUUM, ANALYZE, REINDEX, etc.)
π Schema Browser
- Browse all tables, columns, indexes, constraints, foreign keys
- Sample data preview
- Index usage stats
- Extension and enum type listing
π Schema Change Tracking
- Automatic schema snapshots (every 6 hours)
- Detects: tables added/removed, columns changed, indexes modified
- Timeline view with diff comparison
- The sticky feature β gets more valuable over time
π Alerts
- 7 default alert rules (connection utilization, cache ratio, long queries, etc.)
- Custom rules via API
- Cooldown support (no alert spam)
- Webhook notifications
- Alert history
π EXPLAIN Plan Visualization
- Click any query in the Queries tab to see its execution plan
- Tree view of the EXPLAIN output for easy analysis
π Query Time-Series Trends
- Trends tab with historical pg_stat_statements snapshots
- Track query performance over time
πΎ Disk Space Monitoring
- Disk tab with per-table size breakdown
- Growth prediction using linear regression
- "Days until disk full" estimate
π£ Slack & Discord Notifications
- Webhook notifications for alerts
- Auto-detects Slack vs Discord webhook URLs
- Configure via
--slack-webhookor--discord-webhook
π¬ EXPLAIN ANALYZE CLI
pg-dash explain "SELECT * FROM orders WHERE user_id = 1" postgres://...
Query: SELECT * FROM orders WHERE user_id = 1
Limit cost=3.01..3.04 actual=0.060ms rows=10/10
ββ Sort cost=3.01..3.09 actual=0.057ms rows=10/32
ββ Seq Scan on users cost=0.00..2.32 actual=0.023ms rows=32/32
βββ Summary ββββββββββββββββββββββββββββββββββββ
Execution time: 0.087ms
Planning time: 0.756ms
Seq Scans: users
βββ Recommendations ββββββββββββββββββββββββββββ
βΉ Sort on [created_at DESC]. An index might eliminate this.
- Color-coded node types: π΄ Seq Scan, π’ Index Scan, π‘ Hash Join, π£ Sort
- Shows actual vs estimated rows β catches bad planner estimates
- Flags Seq Scans > 1000 rows, Sort nodes, Hash Join memory spills
--no-analyzefor dry EXPLAIN (no actual execution)--jsonfor scripting
π watch-locks
pg-dash watch-locks postgres://...
Real-time lock wait monitor β refreshes every 3 seconds. Shows:
- Blocked queries with PID, wait time, and the blocking query
- Long-running queries (configurable threshold via
--long-query-threshold) - Table and lock type for each wait
π query-stats (PG 18+)
# Export query statistics from production
pg-dash query-stats export postgres://prod-server/db --file prod-stats.json
# Import to development environment
pg-dash query-stats import prod-stats.json postgres://localhost/db
Export/import PostgreSQL query statistics (requires PG 18+). Enables "production query plans without production data" workflow:
- Export stats from production:
pg-dash query-stats export prod - Import to dev:
pg-dash query-stats import prod-stats.json dev - Run
EXPLAINlocally β now uses production statistics for accurate query plans
The exported JSON is typically <1MB regardless of database size.
π‘οΈ Migration Safety Check
- Analyze a migration SQL file for risks before running it
- Detects:
CREATE INDEXwithoutCONCURRENTLY(lock risk),ADD COLUMN NOT NULLwithoutDEFAULT,ALTER COLUMN TYPE(full table rewrite),DROP COLUMN(app breakage risk),ADD CONSTRAINTwithoutNOT VALID(full table scan),CREATE INDEX CONCURRENTLYinside a transaction (runtime failure),DROP TABLE,TRUNCATE,DELETE/UPDATEwithoutWHERE - Dynamic checks: connects to DB to verify referenced tables exist, estimates lock time based on actual row counts
- CI-ready:
--ciflag emits::error::/::warning::GitHub Actions annotations
π§ Query Intelligence
pg_dash_analyze_queryβ runsEXPLAIN ANALYZE, detects Seq Scans on large tables, auto-generatesCREATE INDEX CONCURRENTLYsuggestions with benefit ratingspg_dash_query_regressionsβ finds queries that got >50% slower vs historical baseline (requirespg_stat_statements)- EXPLAIN Modal in dashboard shows index suggestions inline
π Multi-Env Diff
- Compare schema and health between two PostgreSQL environments (local vs staging, staging vs prod)
- Detects: missing/extra tables, missing/extra columns, column type mismatches, missing/extra indexes, foreign key and CHECK constraints, enum type differences
--healthflag adds health score comparison and unique issues per environmentpg_dash_compare_envMCP tool: ask your AI "what's different between local and staging?"
π§ Production Readiness Audit
- Unused indexes β Find indexes with 0 scans since last stats reset; suggests safe
DROP INDEX CONCURRENTLYSQL - Table bloat β Dead tuple ratio per table (β₯10%); surfaces both
last_autovacuumandlast_vacuumtimestamps - Autovacuum health β Classifies each table as
ok/stale/overdue/never; shows autovacuum settings with units - Lock monitoring β Active lock-wait chains (who is blocking whom) + long-running queries >5s
- Config recommendations β Audits
shared_buffers,work_mem,checkpoint_completion_target,random_page_cost,idle_in_transaction_session_timeout, and 5 more settings with severity-tagged recommendations
𧬠pgvector Health Check
pg-dash pgvector postgres://...
Checks pgvector installation and index health:
- Installed version and upgrade recommendations
- Vector columns with dimension analysis (flags >2000d for performance)
- Index types (IVFFlat vs HNSW) with parameter tuning suggestions
- IVFFlat
listsvs row count validation (should be ~βrows) - HNSW
ef_constructionvsmratio check - Missing vector indexes on large tables
- Index size vs table size ratio
MCP tool: pg_dash_pgvector
π€ MCP Server
- 26 tools for AI agent integration
- Stdio (default):
pg-dash-mcp postgres://...β local use with Claude, Cursor, etc. - Streamable HTTP:
pg-dash-mcp postgres://... --httpβ shared team server, compatible with MCP 2026-07-28 stateless spec
# Remote mode β shared team server on port 8768
pg-dash-mcp postgres://... --http
# Custom port
MCP_PORT=9000 pg-dash-mcp postgres://... --http
MCP client config for remote mode:
{
"mcpServers": {
"pg-dash": {
"type": "streamable-http",
"url": "http://your-server:8768/mcp"
}
}
}
π₯οΈ CLI
# Start dashboard
pg-dash postgres://user:pass@host/db
# Health check (great for CI/CD)
pg-dash check postgres://user:pass@host/db
pg-dash check postgres://... --format json --threshold 70
# Migration safety check
pg-dash check-migration ./migrations/015_add_index.sql
pg-dash check-migration ./migrations/015_add_index.sql postgres://... --ci
# Multi-env schema diff
pg-dash diff-env --source postgres://localhost/db --target postgres://staging/db
pg-dash diff-env --source postgres://... --target postgres://... --health --format md
# Schema changes
pg-dash schema-diff postgres://user:pass@host/db
Quick Start
# Using npx (no install needed)
npx @indiekitai/pg-dash postgres://user:pass@localhost/mydb
# Or install globally
npm install -g @indiekitai/pg-dash
pg-dash postgres://user:pass@localhost/mydb
# With individual options
pg-dash --host localhost --user postgres --db mydb --port 3480
Opens your browser at http://localhost:3480 with the full dashboard.
Documentation
- Real-world example β pg-dash running against a production database
- Migration safety guide β catching lock risks before they hit production
- MCP setup guide β connecting to Claude Desktop and Cursor
- CI integration guide β automated checks in GitHub Actions
CLI Options
pg-dash <connection-string> Start dashboard
pg-dash check <connection-string> Run health check and exit
pg-dash check-migration <file> [conn] Analyze migration SQL for risks
pg-dash diff-env --source <url> --target <url> Compare two environments
pg-dash schema-diff <connection-string> Show schema changes
Options:
-p, --port <port> Dashboard port (default: 3480)
--no-open Don't auto-open browser
--json Dump health check as JSON and exit
--host <host> PostgreSQL host
-u, --user <user> PostgreSQL user
--password <pass> PostgreSQL password
-d, --db <database> PostgreSQL database
--pg-port <port> PostgreSQL port (default: 5432)
--data-dir <dir> Data directory (default: ~/.pg-dash)
-i, --interval <sec> Collection interval (default: 30)
--threshold <score> Score threshold for check command (default: 70)
-f, --format <fmt> Output format: text|json|md (default: text)
--query-stats-interval <min> Query stats snapshot interval in minutes (default: 5)
--slack-webhook <url> Slack webhook URL for alert notifications
--discord-webhook <url> Discord webhook URL for alert notifications
--ci Output GitHub Actions annotations (check, check-migration, diff-env)
--diff Compare with last snapshot (check command)
--ai-suggest Use AI to generate fix suggestions (requires LLM config)
--ai-explain Use AI to explain schema diff business impact (requires LLM config)
--snapshot-path <path> Path to snapshot file for --diff
--health Include health comparison (diff-env)
-v, --version Show version
MCP Server
For AI agent integration:
# Start MCP server
pg-dash-mcp postgres://user:pass@host/db
# Or with env var (PG_DASH_CONNECTION_STRING or DATABASE_URL)
PG_DASH_CONNECTION_STRING=postgres://... pg-dash-mcp
Available Tools (26)
| Tool | Description |
|---|---|
pg_dash_overview |
Database overview (version, uptime, size, connections) |
pg_dash_health |
Health advisor report with score, grade, and issues |
pg_dash_tables |
List all tables with sizes and row counts |
pg_dash_table_detail |
Detailed info about a specific table |
pg_dash_activity |
Current database activity (active queries, connections) |
pg_dash_schema_changes |
Recent schema changes |
pg_dash_fix |
Execute a safe fix (VACUUM, ANALYZE, REINDEX, etc.) |
pg_dash_alerts |
Alert history |
pg_dash_explain |
Run EXPLAIN ANALYZE on a SELECT query (read-only) |
pg_dash_batch_fix |
Get batch fix SQL for issues, optionally filtered by category |
pg_dash_slow_queries |
Top slow queries from pg_stat_statements |
pg_dash_table_sizes |
Table sizes with data/index breakdown (top 30) |
pg_dash_export |
Export full health report (JSON or Markdown) |
pg_dash_diff |
Compare current health with last saved snapshot |
pg_dash_check_migration |
Analyze migration SQL for lock risks, missing tables, destructive ops |
pg_dash_analyze_query |
Deep EXPLAIN analysis with automatic index suggestions |
pg_dash_query_regressions |
Detect queries that degraded >50% vs historical baseline |
pg_dash_compare_env |
Compare schema and health between two database environments |
pg_dash_unused_indexes |
Find unused indexes that waste space and slow down writes |
pg_dash_bloat |
Detect table bloat (dead tuples) that slow down queries |
pg_dash_autovacuum |
Check autovacuum health β which tables are stale or never vacuumed |
pg_dash_locks |
Show active lock waits and long-running blocking queries |
pg_dash_config_check |
Audit PostgreSQL configuration and get tuning recommendations |
pg_dash_pgvector |
pgvector health β installed version, vector columns, index types (IVFFlat/HNSW), dimension analysis, tuning |
fetch_db_context |
Comprehensive DB context for AI agents: all table structures, columns, types, PKs/FKs, indexes, business intent inference, and health summary (single call for full context) |
pg_dash_query_natural |
Query database using natural language β LLM converts your question to SQL and returns results |
ci_health_summary |
CI-friendly health summary with AI-powered prioritization |
MCP Setup
Connect pg-dash to Claude Desktop or Cursor for AI-assisted database management.
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"pg-dash": {
"command": "npx",
"args": ["-y", "-p", "@indiekitai/pg-dash", "pg-dash-mcp", "postgresql://user:pass@host/db"]
}
}
}
Claude Code
Add to ~/.claude/mcp.json (global) or .mcp.json (project-level):
{
"mcpServers": {
"pg-dash": {
"command": "npx",
"args": ["-y", "-p", "@indiekitai/pg-dash", "pg-dash-mcp", "postgresql://user:pass@host/db"]
}
}
}
Cursor
Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"pg-dash": {
"command": "npx",
"args": ["-y", "-p", "@indiekitai/pg-dash", "pg-dash-mcp", "postgresql://user:pass@host/db"]
}
}
}
Example Conversations
Once connected, you can ask your AI assistant:
Diagnosis:
- "What's wrong with my database right now?"
- "Why is my
userstable slow? Check for missing indexes." - "Show me the top 5 slowest queries this week."
Optimization:
- "Generate SQL to fix all missing FK indexes in one go."
- "EXPLAIN this query for me: SELECT * FROM orders WHERE user_id = 123"
- "Which tables are taking up the most space?"
Pre-migration check:
- "Run a health check and tell me if it's safe to deploy."
- "What changed in the schema since last week?"
- "Check if there are any idle connections blocking my migration."
CI Integration
GitHub Actions
Add --ci and --diff flags to integrate with CI pipelines:
# GitHub Actions annotations (::error::, ::warning::)
pg-dash check postgres://... --ci
# Markdown report for PR comments
pg-dash check postgres://... --ci --format md
# Compare with previous run
pg-dash check postgres://... --diff
# All together
pg-dash check postgres://... --ci --diff --format md
Sample workflow (.github/workflows/pg-check.yml):
name: Database Health Check
on:
push:
paths: ['migrations/**', 'prisma/**', 'drizzle/**', 'supabase/migrations/**']
pull_request:
paths: ['migrations/**', 'prisma/**', 'drizzle/**', 'supabase/migrations/**']
schedule:
- cron: '0 8 * * 1' # Weekly Monday 8am UTC
jobs:
db-health:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Cache snapshot across ephemeral runners for --diff to work
- name: Restore health snapshot
uses: actions/cache@v4
with:
path: .pg-dash-cache
key: pg-dash-snapshot-${{ github.ref }}
restore-keys: pg-dash-snapshot-
- name: Run pg-dash health check
id: pg-check
run: |
mkdir -p .pg-dash-cache
npx @indiekitai/pg-dash check ${{ secrets.DATABASE_URL }} \
--ci --diff --snapshot-path ./.pg-dash-cache/last-check.json \
--format md > pg-dash-report.md
echo "exit_code=$?" >> $GITHUB_OUTPUT
continue-on-error: true
- name: Save health snapshot
uses: actions/cache/save@v4
if: always()
with:
path: .pg-dash-cache
key: pg-dash-snapshot-${{ github.ref }}-${{ github.run_id }}
- name: Fail if unhealthy
if: steps.pg-check.outputs.exit_code != '0'
run: exit 1
See examples/github-actions-pg-check.yml for a full workflow with PR comments.
Health Checks
pg-dash runs 46+ automated checks:
Performance
- Missing indexes (high sequential scans on large tables)
- Bloated indexes (index size vs table size)
- Table bloat (dead tuple ratio)
- Cache efficiency per table
- Slow queries (from pg_stat_statements)
Maintenance
- VACUUM overdue
- ANALYZE overdue
- Transaction ID wraparound risk
- Idle connection detection
- Idle in transaction detection
Schema
- Missing primary keys
- Unused indexes (0 scans, >1MB)
- Duplicate indexes
- Missing foreign key indexes
Security
- Remote superuser connections
- SSL disabled
- Trust authentication (no password)
CI/CD Integration
# Fail pipeline if health score < 70
pg-dash check postgres://... --threshold 70 --format json
# Example GitHub Actions
- name: Database Health Check
run: npx @indiekitai/pg-dash check ${{ secrets.DATABASE_URL }} --threshold 70
Data Storage
pg-dash stores metrics locally in ~/.pg-dash/:
metrics.dbβ Time-series metrics (7-day retention)schema.dbβ Schema snapshots and change historyalerts.dbβ Alert rules and history
All SQLite. No external dependencies. Delete the folder to reset.
Tech Stack
- Backend: Hono + Node.js
- Frontend: React + Tailwind CSS (bundled)
- Storage: SQLite (better-sqlite3)
- Charts: Recharts
- Zero external services required
Requirements
- Node.js 18+
- PostgreSQL 12+ (some features require 15+)
License
MIT
Built by IndieKit β open-source developer tools with MCP support.
History
pg-dash has consolidated functionality from several earlier packages, all now archived:
- pg-inspect β schema introspection (use
pg-dash schema-diffor inspection routes) - pg-top β realtime activity monitor (use
pg-dash watch-locks) - pg-explain β EXPLAIN ANALYZE visualization (use
pg-dash explain) - pg-horizon β MVCC horizon monitoring (covered by pg-dash's
Transaction ID Agecheck)
If you've installed any of these as standalone npm packages, switch to pg-dash β same functionality, one install, one upgrade path.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.