<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Qi</title>
    <description>The latest articles on DEV Community by Qi (@indiekitai).</description>
    <link>https://dev.to/indiekitai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3803998%2F7bf0d860-79a2-4b81-905e-e8f32159ae09.jpg</url>
      <title>DEV Community: Qi</title>
      <link>https://dev.to/indiekitai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/indiekitai"/>
    <language>en</language>
    <item>
      <title>I Built a Free PostgreSQL Health Checker with 23 MCP Tools and CI Integration</title>
      <dc:creator>Qi</dc:creator>
      <pubDate>Wed, 04 Mar 2026 03:11:23 +0000</pubDate>
      <link>https://dev.to/indiekitai/i-built-a-free-postgresql-health-checker-with-23-mcp-tools-and-ci-integration-2abc</link>
      <guid>https://dev.to/indiekitai/i-built-a-free-postgresql-health-checker-with-23-mcp-tools-and-ci-integration-2abc</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Free PostgreSQL Health Checker with 23 MCP Tools and CI Integration
&lt;/h1&gt;

&lt;p&gt;After years of working with PostgreSQL in production, I kept running into the same problem: the tooling options are either expensive, complex to set up, or don't fit into a modern AI-assisted workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pganalyze&lt;/strong&gt; — great product, $149/month, cloud-only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana + Prometheus&lt;/strong&gt; — free, but you're maintaining 3 services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pgAdmin&lt;/strong&gt; — good for browsing, useless for automated health checks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;None of them&lt;/strong&gt; work with Claude, Cursor, or any MCP-compatible AI assistant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;strong&gt;pg-dash&lt;/strong&gt; — a self-hosted, zero-config PostgreSQL health checker.&lt;/p&gt;

&lt;h2&gt;
  
  
  One command to start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @indiekitai/pg-dash check postgres://user:pass@host/db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It runs 46+ automated checks across performance, maintenance, schema, and security, grades your database A–F, and gives you executable SQL fixes — not just a list of problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things I haven't seen elsewhere
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Migration safety checker
&lt;/h3&gt;

&lt;p&gt;Before you run a migration, analyze it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg-dash check-migration ./migrations/015_add_index.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It detects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CREATE INDEX&lt;/code&gt; without &lt;code&gt;CONCURRENTLY&lt;/code&gt; — locks the table&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ADD COLUMN NOT NULL&lt;/code&gt; without a &lt;code&gt;DEFAULT&lt;/code&gt; — full table rewrite in older PG versions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ALTER COLUMN TYPE&lt;/code&gt; — another full rewrite&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RENAME TABLE&lt;/code&gt; / &lt;code&gt;RENAME COLUMN&lt;/code&gt; — breaks application code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt; / &lt;code&gt;UPDATE&lt;/code&gt; without &lt;code&gt;WHERE&lt;/code&gt; — obvious but easy to miss under pressure&lt;/li&gt;
&lt;li&gt;And 6 more patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also connects to your database to check actual row counts, so it can say "this lock would affect a 2.4M-row table — expect ~30 seconds of downtime" instead of just flagging the pattern.&lt;/p&gt;

&lt;p&gt;Exits with code 1 in CI if any unsafe patterns are found. Works great as a pre-flight check on every migration PR.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Production readiness audit
&lt;/h3&gt;

&lt;p&gt;These are the things that slowly kill production databases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unused indexes&lt;/strong&gt; — Indexes with 0 scans since the last stats reset. They waste space and slow down every INSERT/UPDATE/DELETE. pg-dash finds them and generates safe &lt;code&gt;DROP INDEX CONCURRENTLY&lt;/code&gt; SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table bloat&lt;/strong&gt; — Dead tuple ratio per table. High bloat means autovacuum can't keep up. Surfaces both &lt;code&gt;last_autovacuum&lt;/code&gt; and &lt;code&gt;last_vacuum&lt;/code&gt; timestamps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Autovacuum health&lt;/strong&gt; — Classifies each table as &lt;code&gt;ok&lt;/code&gt; / &lt;code&gt;stale&lt;/code&gt; / &lt;code&gt;overdue&lt;/code&gt; / &lt;code&gt;never&lt;/code&gt;. If a table has never been vacuumed and has 500K dead tuples, you want to know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lock monitoring&lt;/strong&gt; — Active lock-wait chains (who is blocking whom) and long-running queries over 5 seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Config recommendations&lt;/strong&gt; — Audits your PostgreSQL settings: &lt;code&gt;shared_buffers&lt;/code&gt;, &lt;code&gt;work_mem&lt;/code&gt;, &lt;code&gt;checkpoint_completion_target&lt;/code&gt;, &lt;code&gt;max_connections&lt;/code&gt;, &lt;code&gt;idle_in_transaction_session_timeout&lt;/code&gt;, and more. Flags common misconfigurations with severity levels and documentation links.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 23 MCP tools for AI assistants
&lt;/h3&gt;

&lt;p&gt;This is the part I'm most excited about. Connect pg-dash to Claude Desktop or Cursor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pg-dash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-p"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@indiekitai/pg-dash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pg-dash-mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgresql://user:pass@host/db"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can ask your AI assistant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Which indexes on this database are never used?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Is my autovacuum healthy? Which tables are overdue?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Check this migration file for lock risks"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Compare the schema between staging and production"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What PostgreSQL config changes would help performance?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's the difference between copying query results into chat and your AI actually having access. All 23 tools are read-only by default, with a strict allowlist for write operations (VACUUM, ANALYZE, REINDEX, CREATE INDEX CONCURRENTLY, pg_terminate/cancel_backend — no raw DDL/DML).&lt;/p&gt;

&lt;h2&gt;
  
  
  CI integration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PostgreSQL health check&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx @indiekitai/pg-dash check $DATABASE_URL --ci --diff --format md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--diff&lt;/code&gt; compares against the last saved snapshot. &lt;code&gt;--ci&lt;/code&gt; emits &lt;code&gt;::error::&lt;/code&gt; / &lt;code&gt;::warning::&lt;/code&gt; GitHub Actions annotations and generates a Markdown PR comment. Catch database regressions on every migration, not when production is on fire.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything stays local
&lt;/h2&gt;

&lt;p&gt;No cloud, no signup, no telemetry. Metrics are stored in SQLite on the machine running pg-dash. The dashboard (live metrics, EXPLAIN tree visualization, query trends, disk growth prediction with linear regression) is optional — the CLI is the main workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Health check&lt;/span&gt;
npx @indiekitai/pg-dash check postgres://user:pass@host/db

&lt;span class="c"&gt;# Migration safety check&lt;/span&gt;
npx @indiekitai/pg-dash check-migration ./migrations/add_users_index.sql

&lt;span class="c"&gt;# Compare two environments&lt;/span&gt;
npx @indiekitai/pg-dash diff-env &lt;span class="nt"&gt;--source&lt;/span&gt; postgres://local/db &lt;span class="nt"&gt;--target&lt;/span&gt; postgres://staging/db

&lt;span class="c"&gt;# Start dashboard&lt;/span&gt;
npx @indiekitai/pg-dash postgres://user:pass@host/db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/indiekitai/pg-dash" rel="noopener noreferrer"&gt;indiekitai/pg-dash&lt;/a&gt;&lt;br&gt;
npm: &lt;code&gt;@indiekitai/pg-dash&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Hono, React, SQLite, and TypeScript. 362 tests. Feedback welcome.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>devtools</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
