Azure Database for PostgreSQL Integration

Azure Database for PostgreSQL monitoring is essential for tracking database performance, query behavior, and resource utilization in cloud environments. This guide explains how to set up Azure Database for PostgreSQL monitoring in Middleware using an Azure VM host agent, enabling full observability into queries, metrics, and performance bottlenecks. The agent runs on an Azure VM you control and connects to the managed database over the network—not on the database instance itself.

Prerequisites#

  • Middleware Host Agent on Azure VM: Install the Linux Host Agent on an Azure VM that has network connectivity to your Azure Database for PostgreSQL endpoint. Follow Installing the Agent and the Linux Host Agent steps.
  • Managed database: Do not attempt to install the Host Agent on Azure Database for PostgreSQL. It is a managed service; integration is always Azure VM (agent) → Azure Database for PostgreSQL using a credentials file on the VM and the PostgreSQL integration in Middleware.

Retrieve connection details from Azure#

Gather the following before you configure Middleware:

  • Server name and port: In the Azure portal, open your Azure Database for PostgreSQL resource → Overview. Copy the Server name (e.g. your-server.postgres.database.azure.com) and Port (PostgreSQL default is 5432).
  • Database name: The initial database created with the server, or another database you created.
  • Username and password: The server admin login you defined when creating the server, or a dedicated monitoring user you create in SQL (see Step 2). Store passwords securely (for example in Azure Key Vault or your team's vault); rotate them according to your policy.

Network connectivity#

  • Firewall rules: In the Azure portal, go to your PostgreSQL server → Networking. Add the public IP of your Azure VM to the firewall allow list, or enable Allow access to Azure services if both resources are in Azure. For private connectivity, use Azure Private Link.
  • Placement: The Azure VM running the agent should be in a VNet that can reach the PostgreSQL endpoint (same VNet is typical; cross-VNet requires VNet peering and matching NSG rules).
  • Verification: From the Azure VM, test connectivity (for example with psql or nc -zv <server-name> <port>) before relying on the integration.

Setup#

1 Enable pg_stat_statements#

pg_stat_statements exposes per-statement stats that the integration relies on. On Azure Database for PostgreSQL you configure this with Server parameters in the Azure portal.

  • In the Azure portal, go to your PostgreSQL server → Server parameters.
  • Set the following parameters:
    • shared_preload_libraries — include pg_stat_statements (select it from the dropdown list).
    • pg_stat_statements.track = all
    • pg_stat_statements.max = 10000 (or your chosen limit)
    • track_io_timing = on
  • Click Save. Azure will prompt you to restart the server if required for shared_preload_libraries changes to take effect.
  • Connect to the database (for example with psql from the Azure VM) and run as a user with sufficient privileges:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT calls, query FROM pg_stat_statements LIMIT 1;

You should see a row once statements have executed (your values will differ):

calls | query
-------+-------------------------------
     8 | SELECT * FROM t WHERE field = $1

2 (optional): Create a least-privileged user#

If you do not want to use the admin user for monitoring, create a read-only user with minimal privileges. Run against the Azure Database for PostgreSQL endpoint (for example from the Azure VM using psql):

CREATE USER lpu WITH PASSWORD 'pass';

Verify:

\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;

3 Open the integration in Middleware#

In Middleware, go to InstallationsAll IntegrationsPostgreSQL.

Azure Database for PostgreSQL Monitoring with Middleware

4 Fill the integration form#

In the PostgreSQL integration form:

  • Select the Azure VM host (from the dropdown) where the Middleware Host Agent runs.
  • Enter the required connection details:
    • Database name
    • Azure PostgreSQL server name (e.g. your-server.postgres.database.azure.com)
    • 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:
    • Azure Database for PostgreSQL enforces SSL by default. If Allow Insecure is false and Skip Certificate Verification is false, provide the CA certificate file path.
    • Download the DigiCert Global Root CA on the Azure VM and use that server-ca.pem file path in the form:
      curl -o server-ca.pem https://cacerts.digicert.com/DigiCertGlobalRootG2.crt.pem

5 Save and enable the integration#

  • Click Save.
Azure Database for PostgreSQL integration save confirmation in Middleware

Once saved, the integration starts ingesting metrics from your Azure Database for PostgreSQL instance.

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). Azure Database for PostgreSQL uses the same metric set as self-hosted PostgreSQL.

Core Engine & Storage#

Metric NameDescription
postgresql.backendsThe number of backends.
postgresql.blocks_readThe number of blocks read (tagged by block read source).
postgresql.buffer_hitThe number of disk block hits in the buffer cache, thereby avoiding database reads, tagged with database name.
postgresql.db_sizeThe database disk usage.
postgresql.database.countNumber of user databases.

Tables, Indexes & Maintenance#

Metric NameDescription
postgresql.table.countNumber of user tables in a database.
postgresql.table.sizeDisk space used by a table.
postgresql.table.vacuum.countNumber of times a table has manually been vacuumed.
postgresql.table_bloatEstimated table bloat ratio (actual pages / expected pages); 1.0 indicates no bloat.
postgresql.analyzedNumber of times a table has been manually analyzed.
postgresql.autoanalyzedNumber of times a table has been automatically analyzed.
postgresql.autovacuumedNumber of times a table has been automatically vacuumed.
postgresql.index.scansThe number of index scans on a table.
postgresql.index.sizeThe size of the index on disk.
postgresql.index.blocks_readThe number of disk blocks read by this index (tagged by source).
postgresql.index.rows_readThe number of index entries returned by scans on this index.
postgresql.index_bloatEstimated index bloat ratio (actual pages / expected pages); 1.0 indicates no bloat.

TOAST#

Metric NameDescription
postgresql.toast.blocks_hitNumber of TOAST block hits.
postgresql.toast.index.blocks_readNumber of TOAST index block reads.
postgresql.toast.sizeSize of TOAST table.

Transactions & Row Activity#

Metric NameDescription
postgresql.commitsThe number of commits.
postgresql.rollbacksThe number of rollbacks.
postgresql.rowsThe number of rows in the database (tagged by row state).
postgresql.rows_deletedRows deleted by queries in this database, tagged with relation name.
postgresql.rows_fetchedRows fetched by queries in this database, tagged with relation name.
postgresql.rows_insertedRows inserted by queries in the database, tagged with relation name.
postgresql.rows_updatedRows updated by queries in the database, tagged with relation name.
postgresql.operationsThe number of database row operations (tagged by operation: ins, upd, del, hot_upd).

Checkpointing & Background Writer#

Metric NameDescription
postgresql.bgwriter.checkpoint.countThe number of checkpoints performed (tagged by checkpoint type).
postgresql.bgwriter.durationTotal time spent writing and syncing files to disk by checkpoints (tagged by duration type).
postgresql.bgwriter.maxwrittenNumber of times the background writer stopped a cleaning scan because it had written too many buffers.
postgresql.bgwriter.buffers.writesNumber of buffers written (tagged by buffer source).
postgresql.bgwriter.buffers.allocatedNumber of buffers allocated.

Connections & Limits#

Metric NameDescription
postgresql.connection.countThe number of active connections to this database; when DBM is enabled, tagged with state, application name, database, and user.
postgresql.connection.maxConfigured maximum number of client connections allowed.

Statement-level (via pg_stat_statements)#

Metric NameDescription
postgresql.query.countNumber of times the statement was executed (tagged with query_text, query_id).
postgresql.query.total_exec_timeTotal wait time of the normalised timed events (nanoseconds; tagged with query_text, query_id).

Replication & WAL#

Metric NameDescription
postgresql.replication.data_delayThe amount of data delayed in replication (tagged with replication client).
postgresql.wal.ageAge of the oldest WAL file (requires WAL with at least one replica).
postgresql.wal.countNumber of WAL files.
postgresql.wal.lagTime 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.sizeTotal size of WAL files.

Live Row Estimates#

Metric NameDescription
postgresql.live_rowsThe approximate number of live rows, tagged with relation name.

Active Transaction Duration#

Metric NameDescription
postgresql.transactions.duration.maxMax duration of active transactions.
postgresql.transactions.duration.sumSum of duration of active transactions.

Troubleshooting#

"Integrations" menu not visible

If you do not see Integrations in Middleware, your account probably lacks Installation permissions. Ask an admin to add Installation to your role in Settings.

No metrics or connection failures

  • Confirm the Azure VM can reach the PostgreSQL server (check firewall rules, NSG rules, and VNet configuration).
  • Confirm the credentials use the Azure Database for PostgreSQL server name and port reachable from the VM.
  • Verify pg_stat_statements is enabled and the database user has the grants from Step 2.
  • Ensure SSL is configured correctly — Azure Database for PostgreSQL enforces SSL by default.

Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.