Dashboard

What goes in a PostgreSQL monitoring dashboard in Metabase?

A PostgreSQL monitoring dashboard tracks uptime, replication lag, connections, cache hit rate, latency, and storage for one instance or a whole fleet. Metabase connects to PostgreSQL natively, so you can build it straight from the database's own pg_stat views — or from Prometheus and Datadog exporter rollups if you already collect them.

For: DBAs, platform engineers, and application owners. Grain: one snapshot per instance per interval. Source: pg_stat_* views, snapshotted — the raw views are cumulative counters.

What does a PostgreSQL monitoring dashboard look like?

Here’s the layout this guide builds. Instance health sits at the top so a glance tells you whether anything needs a human; connections, latency, and cache come next because that’s where load shows up first; replication, storage, and slow queries sit at the bottom for when you’re diagnosing rather than checking.

PostgreSQL monitoring dashboard in Metabase showing uptime, connections, cache hit rate, query latency, replication lag, and slow statements.

An example PostgreSQL monitoring dashboard in Metabase, built from snapshotted pg_stat views. Figures are illustrative.

Which cards belong on a PostgreSQL monitoring dashboard?

The eight below cover availability, contention, and capacity — the three ways a Postgres instance usually gets into trouble.

  • Server uptime and last restart, per instance (number)
  • Replication lag in bytes and seconds, per standby (line)
  • Storage used and growth rate, with days-to-full (line + number)
  • Connections in use versus max_connections (gauge + line)
  • Query latency, mean and p95, by database (line)
  • Cache hit rate per database, from blks_hit and blks_read deltas (line)
  • Checkpoints requested versus timed, plus buffers written (bar)
  • Top statements by total execution time, from pg_stat_statements (table)

What data does the dashboard need?

  • pg_stat_database for commits, rollbacks, block hits and reads, deadlocks, and backend counts.
  • pg_stat_replication on the primary, or pg_last_xact_replay_timestamp() on standbys, for lag.
  • pg_stat_statements (extension) for per-statement calls, total and mean execution time, and rows.
  • pg_stat_bgwriter for checkpoint behaviour, and pg_database_size() for storage growth.
  • A snapshot table of your own — the views are cumulative, so the dashboard charts deltas between snapshots, not the raw values.

How do you build it?

  1. Create a read-only monitoring role and grant it pg_monitor, so it can see statistics for sessions it does not own.
  2. Schedule a small job that appends the pg_stat_* readings to a snapshot table every minute or five, tagged with instance and timestamp.
  3. Connect that database to Metabase (see the PostgreSQL data source guide) and model the snapshot deltas once, as a shared model.
  4. Build one saved question per card against the model, so every card agrees on what a “rate” means.
  5. Add filters for instance, database, and date range, and set the dashboard to auto-refresh if it goes on a wall display.

Example card SQL

Cache hit rate, connections, and replication lag by snapshot PostgreSQL
SELECT
s.snapshot_at,
s.database_name,
ROUND(
  100.0 * s.blks_hit / NULLIF(s.blks_hit + s.blks_read, 0), 2
)                                                     AS cache_hit_pct,
s.numbackends                                         AS active_connections,
s.max_connections,
ROUND(100.0 * s.numbackends / NULLIF(s.max_connections, 0), 1)
                                                      AS connection_pct,
s.xact_commit + s.xact_rollback                       AS transactions,
ROUND(
  100.0 * s.xact_rollback / NULLIF(s.xact_commit + s.xact_rollback, 0), 3
)                                                     AS rollback_pct,
s.deadlocks,
s.replication_lag_bytes / 1024 / 1024                 AS replication_lag_mb
FROM pg_stat_snapshots s
WHERE s.snapshot_at >= now() - interval '7 days'
ORDER BY s.database_name, s.snapshot_at;

Metrics

Integrations

Dashboards

FAQ

What is a PostgreSQL monitoring dashboard?
A PostgreSQL monitoring dashboard tracks the health of a Postgres instance or fleet — cache hit rate, connections, replication lag, transaction throughput, storage growth, and the slowest statements — in one place. Because Metabase connects to PostgreSQL natively, you can build it directly against the database's own statistics views without shipping metrics anywhere first.
Can Metabase query pg_stat views directly?
Yes. The pg_stat_* views are ordinary relations, so a native SQL question can read pg_stat_database, pg_stat_user_tables, pg_stat_replication, and (with the extension enabled) pg_stat_statements. Two caveats: the monitoring role needs pg_monitor to see other sessions' query text, and most of these views hold cumulative counters since the last stats reset — so a raw reading is a lifetime total, not a rate.
Why are my cache hit and transaction numbers flat?
Because you are charting cumulative counters. blks_hit, xact_commit, and friends only ever climb since the last pg_stat_reset(), so a line chart of them looks like a straight ramp and a percentage computed from them is a lifetime average that barely moves. Snapshot the counters on a schedule into your own table and chart the delta between consecutive snapshots — that is what makes a spike visible on the day it happens.
What is a good cache hit rate for PostgreSQL?
Above roughly 99% on an OLTP workload is the usual rule of thumb, and a sustained drop is worth investigating — it often means the working set has outgrown shared_buffers, or a new query is scanning cold data. Treat it as a directional signal rather than a target to optimize: a warehouse-style database doing large sequential scans will legitimately sit lower, and pairing it with a cache hit rate trend beats staring at a single reading.
How do I monitor replication lag?
On the primary, pg_stat_replication gives you per-standby byte lag via pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn); on a standby, pg_last_xact_replay_timestamp() gives you time lag. Chart both — byte lag catches a standby that has stalled on a burst of writes, time lag catches one that has stopped replaying altogether — and alert on the time lag, since that is what a read-replica user actually experiences.
Should I monitor Postgres with Metabase or with a dedicated tool?
Both, for different jobs. A Prometheus exporter with Grafana, or Datadog's Postgres integration, will page someone at 3 a.m. and hold high-resolution history — Metabase does neither. What Metabase adds is querying those metrics next to your application and business tables, sharing the result with people who do not have Grafana access, and keeping a weekly capacity review in the same place as the rest of the company's reporting.
How do I find slow queries?
Enable the pg_stat_statements extension and rank by total_exec_time rather than mean_exec_time — the query that costs you the most is usually a fast one run ten million times, not the nightly report. Add calls, rows, and cache hit ratio per statement to the table, and remember the view normalizes literals, so each row is a query shape rather than a single execution.