Observe, analyze, and optimize the usage, health, and performance of your PostgreSQL database.
The PostgreSQL monitoring solution is based on a remote monitoring approach implemented as a Dynatrace ActiveGate extension. The extension queries PostgreSQL databases for performance and health metrics. Dynatrace Intelligence analyzes these metrics for anomalies and problems.
Designate one or more ActiveGate groups to remotely connect to your PostgreSQL database server and pull data. All ActiveGates in each group must be able to reach the server.
For self-hosted Postgres:
For cloud-managed Postgres services:
Create a dedicated database user in your database instance. Dynatrace uses this user to run monitoring queries against your PostgreSQL database.
CREATE USER dynatrace WITH PASSWORD '<PASSWORD>' INHERIT;
.
Databases (recommended for first-time users) or create a monitoring configuration in
Extensions.Navigate to the PostgreSQL extension and select Add configuration.
Set up an endpoint pointing to your database instance. Each configuration can have up to 20000 endpoints.
postgres database).dynatrace monitoring user you created above:
Adjust the polling frequency and other variables for this monitoring configuration:
Endpoint metadata: Allows you to add a custom metadata field to all the entities created by this configuration.Query interval: Defaults to 1 minute and controls the polling frequency for the majority of the metrics collected by the extension.Long query interval: Controls the polling frequency of top query monitoring.Table query interval: Controls the polling frequency of table and index monitoring queries. Available from major version 3 onwards.Configuration query interval: Controls the polling frequency of database configuration parameters and schema.Select Next.
To monitor your database instance, specific settings must be configured on the PostgreSQL database. If you're onboarding through
Databases, scripts are provided that create the necessary database objects. Download the script to your host and run it as an admin user with sufficient permissions. Otherwise, run the following actions manually.
The script performs the following actions:
Grants the monitoring user membership in the pg_monitor role for read-only monitoring access.
GRANT pg_monitor TO dynatrace;
Create a helper function that generates execution plans from SQL commands for deeper query insights.
CREATE SCHEMA dynatrace;CREATE OR REPLACE FUNCTION dynatrace.dynatrace_execution_plan(query text,OUT explain JSON) RETURNS SETOF JSONLANGUAGE plpgsqlVOLATILERETURNS NULL ON NULL INPUTSECURITY DEFINERROWS 1SET plan_cache_mode = force_generic_planAS$$DECLAREarg_count integer;open_paren text;close_paren text;explain_cmd text;json_result json;BEGIN/* reject statements containing a semicolon in the middle */IF pg_catalog.strpos(pg_catalog.rtrim(dynatrace_execution_plan.query, ';'),';') OPERATOR(pg_catalog.>) 0 THENRAISE EXCEPTION 'query string must not contain a semicolon';END IF;/* get the parameter count */SELECT count(*) INTO arg_countFROM pg_catalog.regexp_matches( /* extract the "$n" */pg_catalog.regexp_replace( /* remove single quoted strings */dynatrace_execution_plan.query,'''[^'']*''','','g'),'\$\d{1,}','g');IF arg_count OPERATOR(pg_catalog.=) 0 THENopen_paren := '';close_paren := '';ELSEopen_paren := '(';close_paren := ')';END IF;/* construct a prepared statement */EXECUTEpg_catalog.concat('PREPARE _stmt_',open_paren,pg_catalog.rtrim(pg_catalog.repeat('unknown,', arg_count),','),close_paren,' AS ',dynatrace_execution_plan.query);/* construct an EXPLAIN statement */explain_cmd :=pg_catalog.concat('EXPLAIN (FORMAT JSON, ANALYZE FALSE) EXECUTE _stmt_',open_paren,pg_catalog.rtrim(pg_catalog.repeat('NULL,', arg_count),','),close_paren);/* get and return the plan */EXECUTE explain_cmd INTO json_result;RETURN QUERY SELECT json_result;/* delete the prepared statement */DEALLOCATE _stmt_;END;$$;
SECURITY DEFINER: Executes with the privileges of the user who defined the function, not the caller.EXPLAIN: Requires the same permissions needed to run the query. The user running this function needs sufficient privileges to run PREPARE and EXPLAIN on the queries it explains.USAGE grant on the dynatrace schema.GRANT USAGE ON SCHEMA dynatrace to <username>
search_path for the monitoring user:ALTER USER dynatrace SET search_path to dynatrace, public;
After running the creation script, run the validation script to confirm all required objects were created. This ensures the monitoring setup works as expected.
After these steps, metrics for the monitored PostgreSQL instance appear in the DB app within 2–3 minutes. Then, you can select any instance to explore detailed metrics and performance insights.
Dynatrace supports both self-hosted and cloud-managed monitoring for Postgres databases.
Choose self-hosted Postgres for complete observability, execution plan analysis, automated onboarding, and advanced diagnostics.
Choose cloud-managed Postgres for reduced operational overhead with some monitoring limitations and manual configuration.
With self-hosted Postgres, you manage the database instance and infrastructure. The extension collects data directly from the database using a read-only user. Complete the following setup to enable monitoring:
Configure database parameters.
Configure the following Postgres parameters in the postgresql.conf file and restart the server to apply the settings. For more details, see the Postgres documentation.
Grant the Dynatrace proxy access to the database.
Select and configure the ActiveGate group.
Cloud-managed PostgreSQL is provided as a service by cloud platforms. Services like AWS RDS, AWS Aurora, and Google Cloud SQL prevent direct database configuration. Enable the following features and settings to ensure full monitoring capability.
Add the pg_stat_statements extension.
This extension collects query-level statistics.
Configure the following settings:
track_activity_query_size = 4096 Required
Enables the collection of larger queries by increasing the size of SQL text in pg_stat_activity. If left at the default value (1024), queries longer than 1024 characters aren't collected.
pg_stat_statements.max = 10000 Optional
Increases the number of normalized queries tracked in pg_stat_statements.
pg_stat_statements.track_utility = off Optional
Disables tracking of utility commands like PREPARE and EXPLAIN.
track_io_timing = on Optional
Collects timing information for block read and write operations in queries.
Starting with version Dynatrace version 1.388 and extension major version 3, the following features require an individual connection to each database:
When creating an endpoint, configure database discovery to automatically monitor databases running on an instance without configuring a separate endpoint for each one.
The following discovery modes are available:
When database discovery is enabled, the following connection management settings control how connections to each discovered database are opened and maintained:
On-demand (default)
Connections open only when a query needs to run and close afterwards. A global limit caps the total number of concurrent open connections across all discovered databases.
| Parameter | Description | Default | Minimum | Maximum |
|---|---|---|---|---|
| Maximum number of concurrent connections across all discovered databases | 200 | 15 | 500 |
Pooled
Each discovered database has a dedicated connection pool. Connections are established eagerly and kept alive, which minimizes overhead during query execution. No additional configuration is required.
Use on-demand mode when the number of discovered databases is large and maintaining a permanent pool per database would exhaust available database connections. Use pooled mode when low query latency is a priority and the number of discovered databases is small.
The metrics collected through this extension are billed as Grail metrics.
Use the following formula to estimate the number of metric data points ingested:
( (68 * number of instances)+ (40 * number of databases)+ (1 * number of tablespaces))
For classic licensing, this extension consumes Dynatrace Davis Data Units (see DDUs for metrics).
For logs, Grail Log Analytics consumption applies. For classic licensing, refer either to DDU consumption for Log Management and Analytics or DDUs for Log Monitoring Classic.
If Dynatrace log monitoring is enabled and the pg_stat_statements view is available, Dynatrace ingests the top 100 queries (sorted by total execution time) every 5 minutes and stores them as logs. These logs are available either from the database instance screen or on
Databases, under Top queries by total execution time.
To filter for these queries on a dashboard or notebook, filter by dt.extension.name = com.dynatrace.extension.postgres and event.group = top_queries. Example DQL query:
fetch logs| filter dt.extension.name=="com.dynatrace.extension.postgres" and event.group=="top_queries"| sort total_exec_time desc
Whether or not pg_stat_statements is available, Dynatrace collects queries from pg_stat_activity as part of the Queries feature set. These are ingested as logs with event.group = longest_queries.
If you have configured top query monitoring (see previous section), you can fetch execution plans for these queries in
Databases by selecting Statement performance > Request on the execution plan for a specific query.
For that query, the extension attempts to execute the following:
SELECT * from dynatrace.dynatrace_execution_plan({query})
and then ingest into Dynatrace the first row of the column named explain. These execution plans are ingested as logs with event.group = execution_plans.
The ActiveGate must establish a direct connection to the host being monitored. It should avoid connecting through a load balancer, proxy, or connection pooler (such as pg-pool).
If the ActiveGate switches between different hosts while running (for example, during failover), it may compute differences in statistics across the DB instances. This can result in inaccurate metrics and misleading data.
When activating your extension using monitoring configuration, you can limit monitoring to one of the feature sets. To work properly, the extension has to collect at least one metric after the activation.
In highly segmented networks, feature sets can reflect the segments of your environment. Then, when you create a monitoring configuration, you can select a feature set and a corresponding ActiveGate group that can connect to this particular segment.
All metrics that aren't categorized into any feature set are considered to be the default and are always reported.
A metric inherits the feature set of a subgroup, which in turn inherits the feature set of a group. Also, the feature set defined on the metric level overrides the feature set defined on the subgroup level, which in turn overrides the feature set defined on the group level.
| Metric name | Metric key | Description |
|---|---|---|
| User function calls | postgres.user_functions.calls.count | Number of times this function has been called, as reported by pg_stat_user_functions. |
| User functions total time | postgres.user_functions.total_time.count | Total time spent in this function and all other functions called by it, as reported by pg_stat_user_functions. |
| User functions self time | postgres.user_functions.self_time.count | Total time spent in this function itself, not including other functions called by it, as reported by pg_stat_user_functions. |
| Metric name | Metric key | Description |
|---|---|---|
| Scheduled checkpoints performed | postgres.checkpoints_timed.count | Number of scheduled checkpoints that have been performed |
| Requested checkpoints performed | postgres.checkpoints_req.count | Number of requested checkpoints that have been performed |
| Checkpoints write time | postgres.checkpoint_write_time.count | Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk |
| Checkpoint sync time | postgres.checkpoint_sync_time.count | Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk |
| Buffers written during checkpoints | postgres.buffers_checkpoint.count | Number of buffers written during checkpoints |
| Buffers written by background writer | postgres.buffers_clean.count | Number of buffers written by the background writer |
| Cleaning scan stops | postgres.maxwritten_clean.count | Number of times the background writer stopped a cleaning scan because it had written too many buffers |
| Buffers written by backend | postgres.buffers_backend.count | Number of buffers written directly by a backend |
| Backend fsync executions | postgres.buffers_backend_fsync.count | Number of times a backend had to execute its own fsync call |
| Buffers allocated | postgres.buffers_alloc.count | Number of buffers allocated |
| Metric name | Metric key | Description |
|---|---|---|
| WAL files size | postgres.wal_files_size | Total size of all WAL files in the WAL directory |
| WAL files count | postgres.wal_files | Total number of WAL files in the WAL directory |
| WAL files age | postgres.wal_files_age | Time elapsed since the oldest WAL file was modified |
| WAL write | postgres.wal_write.count | Number of times WAL buffers were written out to disk via XLogWrite request |
| WAL sync | postgres.wal_sync.count | Number of times WAL files were synced to disk via issue_xlog_fsync request |
| WAL write time | postgres.wal_write_time.count | Total amount of time spent writing WAL buffers to disk via XLogWrite request, in milliseconds |
| WAL sync time | postgres.wal_sync_time.count | Total amount of time spent syncing WAL files to disk via issue_xlog_fsync request, in milliseconds |
| WAL diff size | postgres.wal_diff_size | Size of difference between current WAL and last WAL replay |
| WAL records per minute | postgres.wal_records.count | Number of WAL records generated per minute |
| WAL fpi per minute | postgres.wal_fpi.count | Number of WAL full page images generated per minute |
| WAL bytes | postgres.wal_bytes.count | Total amount of WAL generated in bytes |
| WAL buffers full | postgres.wal_buffers_full.count | Number of times WAL data was written to disk because WAL buffers became full |
| Metric name | Metric key | Description |
|---|---|---|
| Active backend processes | postgres.activity.active | Number of server processes executing a query |
| Active waiting backend processes | postgres.activity.active_waiting | Number of server processes actively waiting |
| Idle backend processes | postgres.activity.idle | Number of server processes waiting for a new client command |
| Idle in transaction backends processes | postgres.activity.idle_in_transaction | Number of server processes in transaction not currently executing a query |
| Idle in transaction aborted backends processes | postgres.activity.idle_in_transaction_aborted | Number of server processes in transaction not currently executing a query where one of the statements caused an error |
| Fast-path function backend processes | postgres.activity.fastpath_function_call | Number of server processes executing a fast-path function call |
| Metric name | Metric key | Description |
|---|---|---|
| Latest transaction XID age | postgres.xid_age | Difference between the current transaction's XID and datfrozenxid. If this value exceeds 2^31, this can cause a database crash due to transaction ID wraparound. |
| Number of backends | postgres.numbackends | Number of backends currently connected to this database |
| Committed transactions | postgres.xact_commit.count | Number of transactions in this database that have been committed |
| Rolled back transactions | postgres.xact_rollback.count | Number of transactions in this database that have been rolled back |
| Block read from disk | postgres.blks_read.count | Number of disk blocks read in this database |
| Blocks found in buffer cache | postgres.blks_hit.count | Number of times disk blocks were found already in the buffer cache, so that a read was not necessary |
| Live rows returned | postgres.tup_returned.count | Number of live rows fetched by sequential scans and index entries returned by index scans in this database |
| Live rows fetched by index scans | postgres.tup_fetched.count | Number of live rows fetched by index scans in this database |
| Rows inserted | postgres.tup_inserted.count | Number of rows inserted by queries in this database |
| Rows updated | postgres.tup_updated.count | Number of rows updated by queries in this database |
| Rows deleted | postgres.tup_deleted.count | Number of rows deleted by queries in this database |
| Queries canceled due to conflict | postgres.conflicts.count | Number of queries canceled due to conflicts with recovery in this database |
| Temporary files created | postgres.temp_files.count | Number of temporary files created by queries in this database |
| Data written to temporary files | postgres.temp_bytes.count | Total amount of data written to temporary files by queries in this database |
| Deadlocks | postgres.deadlocks.count | Number of deadlocks detected in this database |
| Data file blocks reading time | postgres.blk_read_time.count | Time spent reading data file blocks by backends in this database |
| Data file blocks writing time | postgres.blk_write_time.count | Time spent writing data file blocks by backends in this database |
| Database Size | postgres.db_size | Size of the database in bytes |
| Data page checksum failures | postgres.checksum_failures.count | Number of data page checksum failures detected in this database. Only available if data checksums are enabled. |
| Time spent by sessions | postgres.session_time.count | Time spent by database sessions in this database |
| Time spent executing SQL statements | postgres.active_time.count | Time spent executing SQL statements in this database |
| Time spent idling | postgres.idle_in_transaction_time.count | Time spent idling while in a transaction in this database |
| Established sessions | postgres.sessions.count | Total number of sessions established |
| Abandoned sessions | postgres.sessions_abandoned.count | Number of database sessions to this database that were terminated because connection to the client was lost |
| Fatal error terminated sessions | postgres.sessions_fatal.count | Number of database sessions to this database that were terminated by fatal errors |
| Killed sessions | postgres.sessions_killed.count | Number of database sessions to this database that were terminated by operator intervention |
| Metric name | Metric key | Description |
|---|---|---|
| Instance uptime | postgres.uptime | Time since the instance has been started |
| Metric name | Metric key | Description |
|---|---|---|
| SLRU blocks zeroed | postgres.slru.blks_zeroed.count | Number of blocks zeroed during initializations, as reported by pg_stat_slru. |
| SLRU blocks hit | postgres.slru.blks_hit.count | Number of times disk blocks were found already in the SLRU cache, so that a read was not necessary, as reported by pg_stat_slru. |
| SLRU blocks read | postgres.slru.blks_read.count | Number of disk blocks read, as reported by pg_stat_slru. |
| SLRU blocks written | postgres.slru.blks_written.count | Number of disk blocks written, as reported by pg_stat_slru. |
| SLRU blocks exists | postgres.slru.blks_exists.count | Number of blocks checked for existence, as reported by pg_stat_slru. |
| SLRU flushes | postgres.slru.flushes.count | Number of SLRU flushes of dirty data, as reported by pg_stat_slru. |
| SLRU truncates | postgres.slru.truncates.count | Number of SLRU truncates, as reported by pg_stat_slru. |
| Metric name | Metric key | Description |
|---|---|---|
| I/O reads | postgres.io.reads.count | Number of read operations as reported by pg_stat_io. |
| I/O read time | postgres.io.read_time.count | Time spent waiting for read operations as reported by pg_stat_io. |
| I/O writes | postgres.io.writes.count | Number of write operations as reported by pg_stat_io. |
| I/O write time | postgres.io.write_time.count | Time spent waiting for write operations as reported by pg_stat_io. |
| I/O writebacks | postgres.io.writebacks.count | Number of units of size BLCKSZ (typically 8kB) which the process requested the kernel write out to permanent storage as reported by pg_stat_io. |
| I/O writeback time | postgres.io.writeback_time.count | Time spent waiting for writeback operations as reported by pg_stat_io. |
| I/O extends | postgres.io.extends.count | Number of relation extend operations as reported by pg_stat_io. |
| I/O extend time | postgres.io.extend_time.count | Time spent waiting for extend operations as reported by pg_stat_io. |
| I/O hits | postgres.io.hits.count | The number of times a desired block was found in a shared buffer as reported by pg_stat_io. |
| I/O evictions | postgres.io.evictions.count | Number of times a block has been written out from a shared or local buffer in order to make it available for another use as reported by pg_stat_io. |
| I/O reuses | postgres.io.reuses.count | The number of times an existing buffer in a size-limited ring buffer outside of shared buffers was reused as part of an I/O operation as reported by pg_stat_io. |
| I/O fsyncs | postgres.io.fsyncs.count | Number of fsync calls as reported by pg_stat_io. |
| I/O fsync time | postgres.io.fsync_time.count | Time spent waiting for fsync operations as reported by pg_stat_io. |
| I/O read bytes | postgres.io.read_bytes.count | The total size of read operations as reported by pg_stat_io. |
| I/O write bytes | postgres.io.write_bytes.count | The total size of write operations as reported by pg_stat_io. |
| I/O extend bytes | postgres.io.extend_bytes.count | The total size of relation extend operations as reported by pg_stat_io. |
| Metric name | Metric key | Description |
|---|---|---|
| Number of locks | postgres.locks | Number of locks as reported by pg_locks |
| Metric name | Metric key | Description |
|---|---|---|
| Instance recovery mode | postgres.recovery.state | Indicate that the instance is in recovery mode. 1 if in recovery, 0 otherwise. |
| Metric name | Metric key | Description |
|---|---|---|
| Replication WAL restart delay | postgres.replication.restart_delay | Difference between current WAL LSN and the restart_lsn as reported by pg_replication_slots. |
| Replication WAL confirmed flush lag | postgres.replication.confirmed_flush_lag | Difference between current WAL LSN and the confirmed_flush_lsn as reported by pg_replication_slots. |
| Replication WAL confirmed flush lag | postgres.replication.slot_xmin_age | Age of the oldest transaction that this logical replication slot needs the database to retain, as reported by pg_replication_slots. |
| Database conflicts tablespace | postgres.database_conflicts.tablespace.count | Number of queries in this database that have been canceled due to dropped tablespaces, as reported by pg_stat_database_conflicts. Standby only. |
| Database conflicts lock | postgres.database_conflicts.lock.count | Number of queries in this database that have been canceled due to lock timeouts, as reported by pg_stat_database_conflicts. Standby only. |
| Database conflicts snapshot | postgres.database_conflicts.snapshot.count | Number of queries in this database that have been canceled due to old snapshots, as reported by pg_stat_database_conflicts. Standby only. |
| Database conflicts buffer pin | postgres.database_conflicts.bufferpin.count | Number of queries in this database that have been canceled due to pinned buffers, as reported by pg_stat_database_conflicts. Standby only. |
| Database conflicts deadlock | postgres.database_conflicts.deadlock.count | Number of queries in this database that have been canceled due to deadlocks, as reported by pg_stat_database_conflicts. Standby only. |
| Replication WAL write lag | postgres.replication.write_lag | Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written it, as reported by pg_stat_replication. |
| Replication WAL flush lag | postgres.replication.flush_lag | Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it, as reported by pg_stat_replication. |
| Replication WAL replay lag | postgres.replication.replay_lag | Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it, as reported by pg_stat_replication. |
| Replication backend transaction age | postgres.replication.backend_xmin_age | Age of the backend's xmin horizon, as reported by pg_stat_replication. |
| Replication replay delay | postgres.replication.replay_delay | Difference in bytes between the current WAL position and the last WAL position replayed on the standby server, as reported by pg_stat_replication. |
| WAL receiver received timeline ID | postgres.wal_receiver.received_tli | Timeline number of the last WAL received and flushed to disk, as reported by pg_stat_wal_receiver. Standby only. |
| WAL receiver last message send age | postgres.wal_receiver.last_msg_send_age | Time elapsed since last message sent to origin WAL sender, as reported by pg_stat_wal_receiver. Standby only. |
| WAL receiver last message receipt age | postgres.wal_receiver.last_msg_receipt_age | Time elapsed since last message received from origin WAL sender, as reported by pg_stat_wal_receiver. Standby only. |
| WAL receiver latest end age | postgres.wal_receiver.latest_end_age | Time elapsed since last write-ahead log location reported to origin WAL sender, as reported by pg_stat_wal_receiver. Standby only. |
| Metric name | Metric key | Description |
|---|---|---|
| Subscription stats - apply error | postgres.subscription_stats.apply_error.count | Number of times an error occurred while applying changes, as reported by pg_stat_subscription_stats. |
| Subscription stats - sync error | postgres.subscription_stats.sync_error.count | Number of times an error occurred during the initial table synchronization, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - insert exists | postgres.subscription_stats.confl_insert_exists.count | Number of times a row insertion violated a NOT DEFERRABLE unique constraint during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - update origin differs | postgres.subscription_stats.confl_update_origin_differs.count | Number of times an update operation was applied to a row that had been previously modified by another source during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - update exists | postgres.subscription_stats.confl_update_exists.count | Number of times that an updated row value violated a NOT DEFERRABLE unique constraint during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - update missing | postgres.subscription_stats.confl_update_missing.count | Number of times the tuple to be updated was not found during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - delete origin differs | postgres.subscription_stats.confl_delete_origin_differs.count | Number of times a delete operation was applied to row that had been previously modified by another source during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - missing delete | postgres.subscription_stats.confl_delete_missing.count | Number of times the tuple to be deleted was not found during the application of changes, as reported by pg_stat_subscription_stats. |
| Subscription stats conflict - multiple unique conflicts | postgres.subscription_stats.confl_multiple_unique_conflicts.count | Number of times a row insertion or an updated row values violated multiple NOT DEFERRABLE unique constraints during the application of changes, as reported by pg_stat_subscription_stats. |
| Metric name | Metric key | Description |
|---|
| Metric name | Metric key | Description |
|---|---|---|
| Tablespace size | postgres.tablespace.size | Tablespace size in bytes |
Top queries:
ALTER statements are excluded from top query collection.Execution plan details:
extensions:configuration.actions:write permission is required to trigger the execution plan fetching.dynatrace.dynatrace_execution_plan function has been created.This extension runs from your Dynatrace ActiveGates and connects to the configured databases. Once the connection is established, the extension regularly runs queries on the database to gather performance and health metrics, reporting the results back to Dynatrace.
Only SELECT queries are executed to collect data. To see exactly which queries run, download the extension yaml artifact: open the Release notes, select a release, and select Download version.
From version 2.3.0 onwards, query execution frequency is controlled by the configuration variables query-interval and heavy-query-interval. Most of the queries executed by the extension run every query-interval minutes (with a default of 1 minute), while the queries under the Queries feature set run every heavy-query-interval minutes (with a default of 5 minutes).
For older versions, most queries run every minute. The heavy queries mentioned above run every 5 minutes.
Supporting a wide range of Postgres versions requires running several versions of the same queries in parallel, since Postgres has changed column names for several tables over time. Some queries failing is expected. As long as no data is missing, there is no cause for concern.