PostgreSQL Integration
The PostgreSQL integration enables you to ingest performance and health metrics from your PostgreSQL instance(s) into Middleware, allowing you to track blocks read versus hits, table/index sizes, transactions (including commits/rollbacks), per-statement activity, and more.
Prerequisites#
- Middleware Host Agent is installed on the host that can reach your PostgreSQL instance. See Installing the Agent
Setup#
1 Enable pg_stat_statements#
pg_stat_statements exposes per-statement stats that the integration relies on.
- Edit postgresql.conf. (path example below; adjust for your distro/version)This ensures the extension is preloaded and IO timing is captured for accurate statement metrics. Save the file.
# /etc/postgresql/14/main/postgresql.conf shared_preload_libraries = 'pg_stat_statements' pg_stat_statements.track = all pg_stat_statements.max = 10000 track_io_timing = on - (Alternative via SQL): As a superuser, you can also set the preload parameter from SQL (still requires a restart to take effect):
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements'; - Restart PostgreSQL for the preload to take effect:
sudo systemctl restart postgresql - Verify the extension and data flow (as superuser):
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; SELECT calls, query FROM pg_stat_statements LIMIT 1;
You should see a row like:
calls | query
------+-------------------------------
8 | SELECT * FROM t WHERE field = ?(Your values will differ. This view reflects your executed statements.)
2 (optional): Create a least-privileged user#
If you don’t want to use the superuser for monitoring, create a read-only user with just what’s needed:
- Create the userVerify:
CREATE USER lpu WITH PASSWORD 'pass';You should see lpu in the roles listing.\du - Grant minimal access
-- allow connections to the database you'll monitor GRANT CONNECT ON DATABASE <your_db_name> TO lpu; -- permit reading statement stats GRANT SELECT ON pg_stat_statements TO lpu; -- permit reading global stats where needed GRANT pg_read_all_stats TO lpu;
Test with the lpu account:
SELECT calls, query FROM pg_stat_statements LIMIT 1;(The output will reflect queries observed under your workload.)
3 Open the Integration in Middleware#
In Middleware, go to Installations → All Integrations → PostgreSQL.

4 Fill the Integration Form#
In the PostgreSQL integration form:
- Select the host (from the dropdown) where the database is reachable.
- Enter the required connection details:
- Database name
- Endpoint
- Username
- Password
- (Optional) Query Collection:
- Query Sample Collection captures sampled query activity (query text, state, wait events, and client/application details) for troubleshooting.
- Top Query Collection captures aggregated high-impact query metrics (calls, rows, block I/O, and planning/execution timings) from
pg_stat_statements.
- (Optional) Schema Collection captures database schema and table metadata for schema visibility in Middleware.
- TLS Settings:
- If
Allow InsecureisfalseandSkip Certificate Verificationisfalse, provide:- Client certificate file path
- Client key file path
- CA certificate file path
- If
5 Save and Enable the Integration#
- Click Save.

Once saved, the integration starts ingesting metrics.
Visualise your Data#
Default PostgreSQL Dashboard#
After setup, Middleware adds a PostgreSQL dashboard to the Dashboard Builder. Use it as a starting point to explore key DB metrics without building widgets from scratch.
Create Custom Widgets#
When adding a widget, choose data source postgresql to browse all exposed metrics and craft charts for your SLOs or run-book checks.
Alerts#
You can alert on any PostgreSQL metric. Create a rule using Database as the detection method and PostgreSQL as the database type; the Metrics dropdown then lists all available metrics for this integration. Configure conditions, thresholds and recipients as usual.
Metrics Collected#
The following metrics are emitted when enabled in the PostgreSQL receiver (names and descriptions align with the integration’s metric definitions).
Core Engine & Storage#
| Metric Name | Description |
|---|---|
postgresql.backends | The number of backends. |
postgresql.blocks_read | The number of blocks read (tagged by block read source). |
postgresql.buffer_hit | The number of disk block hits in the buffer cache, thereby avoiding database reads, tagged with database name. |
postgresql.db_size | The database disk usage. |
postgresql.database.count | Number of user databases. |
Tables, Indexes & Maintenance#
| Metric Name | Description |
|---|---|
postgresql.table.count | Number of user tables in a database. |
postgresql.table.size | Disk space used by a table. |
postgresql.table.vacuum.count | Number of times a table has manually been vacuumed. |
postgresql.table_bloat | Estimated table bloat ratio (actual pages / expected pages); 1.0 indicates no bloat. |
postgresql.analyzed | Number of times a table has been manually analyzed. |
postgresql.autoanalyzed | Number of times a table has been automatically analyzed. |
postgresql.autovacuumed | Number of times a table has been automatically vacuumed. |
postgresql.index.scans | The number of index scans on a table. |
postgresql.index.size | The size of the index on disk. |
postgresql.index.blocks_read | The number of disk blocks read by this index (tagged by source). |
postgresql.index.rows_read | The number of index entries returned by scans on this index. |
postgresql.index_bloat | Estimated index bloat ratio (actual pages / expected pages); 1.0 indicates no bloat. |
TOAST#
| Metric Name | Description |
|---|---|
postgresql.toast.blocks_hit | Number of TOAST block hits. |
postgresql.toast.index.blocks_read | Number of TOAST index block reads. |
postgresql.toast.size | Size of TOAST table. |
Transactions & Row Activity#
| Metric Name | Description |
|---|---|
postgresql.commits | The number of commits. |
postgresql.rollbacks | The number of rollbacks. |
postgresql.rows | The number of rows in the database (tagged by row state). |
postgresql.rows_deleted | Rows deleted by queries in this database, tagged with relation name. |
postgresql.rows_fetched | Rows fetched by queries in this database, tagged with relation name. |
postgresql.rows_inserted | Rows inserted by queries in the database, tagged with relation name. |
postgresql.rows_updated | Rows updated by queries in the database, tagged with relation name. |
postgresql.operations | The number of database row operations (tagged by operation: ins, upd, del, hot_upd). |
Checkpointing & Background Writer#
| Metric Name | Description |
|---|---|
postgresql.bgwriter.checkpoint.count | The number of checkpoints performed (tagged by checkpoint type). |
postgresql.bgwriter.duration | Total time spent writing and syncing files to disk by checkpoints (tagged by duration type). |
postgresql.bgwriter.maxwritten | Number of times the background writer stopped a cleaning scan because it had written too many buffers. |
postgresql.bgwriter.buffers.writes | Number of buffers written (tagged by buffer source). |
postgresql.bgwriter.buffers.allocated | Number of buffers allocated. |
Connections & Limits#
| Metric Name | Description |
|---|---|
postgresql.connection.count | The number of active connections to this database; when DBM is enabled, tagged with state, application name, database, and user. |
postgresql.connection.max | Configured maximum number of client connections allowed. |
Statement-level (via pg_stat_statements)#
| Metric Name | Description |
|---|---|
postgresql.query.count | Number of times the statement was executed (tagged with query_text, query_id). |
postgresql.query.total_exec_time | Total wait time of the normalised timed events (nanoseconds; tagged with query_text, query_id). |
Replication & WAL#
| Metric Name | Description |
|---|---|
postgresql.replication.data_delay | The amount of data delayed in replication (tagged with replication client). |
postgresql.wal.age | Age of the oldest WAL file (requires WAL with at least one replica). |
postgresql.wal.count | Number of WAL files. |
postgresql.wal.lag | Time between flushing recent WAL locally and receiving notification that the standby completed an operation (tagged by operation and replication client; requires WAL with at least one replica). |
postgresql.wal.size | Total size of WAL files. |
Live Row Estimates#
| Metric Name | Description |
|---|---|
postgresql.live_rows | The approximate number of live rows, tagged with relation name. |
Active Transaction Duration#
| Metric Name | Description |
|---|---|
postgresql.transactions.duration.max | Max duration of active transactions. |
postgresql.transactions.duration.sum | Sum of duration of active transactions. |
AWS RDS PostgreSQL#
If you use AWS RDS for PostgreSQL, monitoring is host-agent-based: run the Middleware Host Agent on an EC2 instance that can reach your RDS endpoint and complete the same PostgreSQL integration steps in Middleware. For RDS-specific setup (parameter groups, connection details in AWS, and networking), see the AWS RDS PostgreSQL integration.
Azure Database for PostgreSQL#
If you use Azure Database for PostgreSQL, monitoring is host-agent-based: run the Middleware Host Agent on an Azure VM that can reach your PostgreSQL server endpoint and complete the same PostgreSQL integration steps in Middleware. For Azure-specific setup (server parameters, firewall rules, and networking), see the Azure Database for PostgreSQL integration.
GCP Cloud SQL for PostgreSQL#
If you use GCP Cloud SQL for PostgreSQL, monitoring is host-agent-based: run the Middleware Host Agent on a GCE VM that can reach your Cloud SQL endpoint and complete the same PostgreSQL integration steps in Middleware. For Cloud SQL-specific setup (database flags, SSL client certificates, and networking), see the GCP Cloud SQL for PostgreSQL integration.
Troubleshooting#
“Integrations” menu not visible
If you don’t see Integrations in Middleware, your account probably lacks Installation permissions. Ask an admin to add Installation to your role in Settings.
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.