Snowflake Postgres Insights¶
Insights is a Postgres extension that continuously collects performance and health metrics
from your Snowflake Postgres instance and stores them inside the database. It samples standard
Postgres statistics views, such as pg_stat_activity, pg_stat_database, and
pg_stat_statements, on a schedule. It then keeps a rolling history and automatically rolls
that history up into hourly and daily summaries, expected-range baselines, and capacity forecasts.
Because the data lives in ordinary tables in the insights schema, you can query it with plain
SQL. No external agent, collector, or time-series database is required. This makes pgInsights a
convenient backend for dashboards (for example Grafana), ad-hoc troubleshooting, and capacity
planning.
Note
This page documents the pgInsights extension that you install and query inside your database. It is different from the Database Insights panel on the instance details page in Snowsight. The two are complementary: the Snowsight panel gives you point-in-time recommendations, while pgInsights gives you queryable history and trends.
What pgInsights collects¶
| Category | Examples |
|---|---|
| Cluster-wide activity | background writer, checkpointer, WAL, archiver |
| Database activity | commits, rollbacks, blocks read/hit, tuples, temp files, deadlocks |
| Connections and sessions | active/idle counts, longest query, longest transaction, lock waits |
| Relations | table and index size, scans, I/O, dead tuples, vacuum activity |
| Replication | sender/receiver state, replication slots, subscriptions |
| SQL statement statistics | per-query calls, timing, rows, buffers (via pg_stat_statements) |
| Configuration | non-default server settings and version information |
| Operating system | CPU, memory, load average, disk, network (Linux only) |
Enabling Insights¶
Create the extension¶
Connect to the database you want to monitor, then create the extension. Creating insights
also creates pg_stat_statements automatically through the CASCADE option:
All objects are created in the insights schema. The background workers begin collecting on
their schedule immediately; no further action is required.
Verify the installation¶
You can also confirm that data is landing:
How it works¶
pgInsights runs a simple, automatic pipeline. You normally don’t call these steps by hand; the background workers do that for you. Understanding the flow makes the tables easier to interpret.
- Collections are the named units of work (for example
pg_session). Each one is due on its own interval. - Metrics are the individual values a collection emits (for example
active,idle). Multi-valued metrics carry a JSON key (for example{"datname": "mydb"}). - Properties are slowly-changing settings (for example server configuration) tracked separately, with a history of changes.
Reference: database tables¶
All pgInsights objects are in the insights schema. The tables you’ll query most often are
listed first.
| Table | What it holds |
|---|---|
pgi_metric | Current (latest) value of every metric: one row per metric |
pgi_metric_history | Raw metric snapshots at ~30-second granularity (30-day retention) |
pgi_metric_summary_hour | Hourly rollups: min/avg/max/stddev/total plus topband/bottomband (180-day retention) |
pgi_metric_summary_day | Daily rollups, same statistics (360-day retention) |
pgi_metric_trend | Expected value range (floor_val, avg_val, ceiling_val) for each day-of-week × hour-of-day |
pgi_metric_forecast | Linear-regression projections, up to 180 days out |
pgi_property | Current value of tracked properties (server settings, version) |
pgi_property_history | History of property changes (60-day retention) |
pgi_sql | Query text, keyed by queryid |
pgi_sql_metric_history | Per-statement execution statistics per snapshot |
pgi_sql_summary | Per-role, per-database SQL statistics roll-up |
pgi_wait_event | Per-session wait-event samples (1-day retention) |
pgi_collection | Collection configuration: what to collect, how often, enabled/disabled |
pgi_jobs / pgi_runs | Background worker job definitions and run history |
Common columns in the metric tables:
| Column | Meaning |
|---|---|
col_name | Collection the row came from (for example pg_session) |
metric_name | Individual metric (for example active) |
metric_key | JSON dimension key for multi-valued metrics, or NULL |
metric_value | Value, stored as text: cast with ::numeric when charting |
snapshot_dt / rollup_dt | Timestamp of the sample or rollup bucket |
Reference: collections and metrics¶
pgInsights ships with about 34 collections. Most run every 30 seconds; larger or more expensive collections run less often. Two collections are disabled by default.
Metrics: every 30 seconds¶
| Collection | Source |
|---|---|
pg_archiver | pg_stat_archiver |
pg_bgwriter | pg_stat_bgwriter |
pg_checkpointer | pg_stat_checkpointer (PG17+); derived on PG16 |
pg_db_stats | pg_stat_database |
pg_function | pg_stat_user_functions |
pg_replication | pg_stat_replication |
pg_replication_slots | pg_replication_slots |
pg_session | pg_stat_activity (derived, per database) |
pg_subscription | pg_stat_subscription |
pg_transaction | pg_database (transaction-ID age) |
pg_wait_event | pg_stat_activity (writes to pgi_wait_event) |
pg_wal | pg_stat_wal (derived from pg_stat_io on PG18+) |
pg_wal_receiver | pg_stat_wal_receiver |
os_cputime, os_disk, os_loadavg, os_memory, os_network, os_process | Linux /proc |
Note
The os_* collections read Linux /proc. On platforms where /proc is unavailable, they
return no rows. They are harmless everywhere and don’t require opt-in.
Metrics: other intervals¶
| Collection | Interval | Source |
|---|---|---|
pg_stat_statements | 1 minute | pg_stat_statements |
pg_db_size_est | 1 hour | pg_class.relpages: estimated database size |
pg_index_io | 1 day | pg_statio_user_indexes |
pg_index_stats | 1 day | pg_stat_user_indexes |
pg_table_io | 1 day | pg_statio_user_tables |
pg_table_stats | 1 day | pg_stat_user_tables |
Metrics: disabled by default¶
| Collection | Interval | Why off |
|---|---|---|
pg_db_size | 1 day | pg_database_size() walks the filesystem; expensive on large clusters. The hourly pg_db_size_est covers most needs. |
pg_stat_io | 5 minutes | The source view is rarely enabled and the collection adds many rows per cycle. |
Properties: every day¶
| Collection | Source |
|---|---|
pg_info | version() |
pg_settings | pg_settings (non-default values only) |
Example: pg_session metrics¶
Each collection emits a defined set of metrics. For example, pg_session is keyed by
{"datname": …} and emits these gauges:
| Metric | Meaning |
|---|---|
total | Backends attached to the database |
active | Backends running a query |
idle | Idle backends |
idle_in_txn | Backends idle inside a transaction |
max_query_time | Longest currently-running client query (seconds) |
max_txn_time | Longest currently-open client transaction (seconds) |
max_idle_in_txn_time | Longest idle-in-transaction time (seconds) |
max_blocked_query_time | Longest time a query has waited on a lock (seconds) |
pct_connections | Backends as a percentage of max_connections |
pct_active | Non-idle backends as a percentage of total |
Tip
For the full list of metrics emitted by every collection, including units and version differences, query the collection directly to see its live output:
Setting server parameters¶
A few pgInsights settings, such as insights.enabled and the insights.retention_* windows,
are PostgreSQL server parameters. On Snowflake Postgres, you can’t change server
parameters with ALTER SYSTEM, by editing postgresql.conf, or by calling pg_reload_conf().
Instead, set them on the instance through Snowsight. You can use either the instance settings UI
or the ALTER POSTGRES INSTANCE SQL command with the POSTGRES_SETTINGS clause, keyed as
component:parameter_name:
None of the parameters below require an instance restart, so you don’t need to wait for a
maintenance window. APPLY IMMEDIATELY applies the change as soon as it’s ready. For the full
server-settings mechanism and the Snowsight UI steps, see
Snowflake Postgres server settings,
ALTER POSTGRES INSTANCE, and
Managing instances.
Note
Many day-to-day adjustments don’t require a server-parameter change. You can enable or disable
individual collections, change their intervals, and apply a one-off retention purge with
ordinary SQL against the insights schema, as described below.
GUC parameter reference¶
Every parameter pgInsights registers is prefixed with insights.. Time-based values are stored
in seconds. When setting one, use a plain number of seconds or a Postgres duration abbreviation
(s, min, h, or d; for example 14d, not 14 days).
| Parameter | Type | Default | Minimum | What it controls |
|---|---|---|---|---|
insights.enabled | boolean | on | — | Enables the background worker orchestrator that drives all automatic collection. Setting this to off stops every scheduled collection and maintenance task without dropping the extension. |
insights.job_timeout | integer (seconds) | 0 (no limit) | 0 | Maximum execution time for a single scheduled job. A job still running past this limit is cancelled. 0 disables the limit. |
insights.retention_raw | integer (seconds) | 30d | 3d | How long rows are kept in pgi_metric_history before the purge task deletes them. |
insights.retention_hour | integer (seconds) | 180d | 1d | How long rows are kept in pgi_metric_summary_hour. |
insights.retention_day | integer (seconds) | 360d | 1d | How long rows are kept in pgi_metric_summary_day. |
insights.retention_property | integer (seconds) | 60d | 1d | How long rows are kept in pgi_property_history. |
insights.retention_runs | integer (seconds) | 1d | 1h | How long successful job run records are kept in pgi_runs. Failed runs are retained regardless, for troubleshooting. |
Tip
pgi_wait_event has a fixed 1-day retention that isn’t configurable through a parameter.
Managing collections¶
Collection behavior is controlled by the pgi_collection table. Changes take effect on the
background worker’s next scheduling cycle; no restart is needed.
Enable or disable a collection¶
Change how often a collection runs¶
Force a collection to run now¶
pgi_snapshot() runs only the collections whose next_collect time has passed. Reset the
watermark to collect on the next cycle:
Pause all background collection¶
To stop the background workers without removing the extension, set the insights.enabled
server parameter to off. On Snowflake Postgres, server parameters are changed through
Snowsight, either with SQL or the UI, not with ALTER SYSTEM, postgresql.conf, or
pg_reload_conf(). Using ALTER POSTGRES INSTANCE:
Set it back to "on" the same way to resume. See
Setting server parameters below for details.
Tip
You don’t need a server-parameter change to pause an individual collection. Update its row in
pgi_collection instead (see Managing collections). That takes effect
on the next scheduling cycle and requires only a table UPDATE.
Note
Modifying pgi_collection requires ownership of the table or an explicit UPDATE grant.
Objects are owned by the snowflake_insights role. A privileged user can delegate control:
Data retention¶
Old rows are removed automatically by a scheduled purge task. Retention windows are server parameters, so you can change the defaults without touching the schema.
| Table | Default | Server parameter |
|---|---|---|
pgi_metric_history | 30 days | insights.retention_raw |
pgi_metric_summary_hour | 180 days | insights.retention_hour |
pgi_metric_summary_day | 360 days | insights.retention_day |
pgi_property_history | 60 days | insights.retention_property |
pgi_wait_event | 1 day | fixed: not configurable |
To change a default, set the corresponding server parameter through Snowsight (see Setting server parameters). For example, to keep raw history for two weeks:
To apply a retention window immediately without changing a server parameter, call the purge procedure directly with explicit intervals. This is a plain SQL call that any user with access to the schema can run:
Sample queries¶
Current connection state¶
Connection count over the last hour¶
Peak and average connections by hour (last 7 days)¶
Active session wait events (last 5 minutes)¶
Top 10 queries by total execution time¶
PostgreSQL configuration changes over time¶
Metrics currently outside their expected range (anomalies)¶
pgi_metric_trend records the normal range for each metric at each hour of the week. Join
current values against it to surface anything unusual for the current day-of-week and hour:
Capacity forecast¶
Query privacy¶
pg_stat_statements normalizes literal values out of most queries, so parameter values don’t
appear in pgi_sql. In addition, pgInsights deliberately doesn’t store administrative and
session-management statements that carry no performance value and could contain secrets,
including CREATE/ALTER/DROP USER/ROLE/GROUP, CREATE SUBSCRIPTION, CREATE SERVER,
CREATE USER MAPPING, SET, RESET, SHOW, DISCARD, DEALLOCATE, and COMMENT.
Caution
The pgi_wait_event samples capture pg_stat_activity.query, which is not normalized.
Literal parameter values can appear there. This data is retained for one day and is readable by
pg_monitor. Consider this before relying on wait-event sampling in regulated environments.
Granting read access¶
Objects are owned by the snowflake_insights role. To let another user read pgInsights data:
Uninstalling¶
To also stop the background workers, set the insights.enabled server parameter to off
through Snowsight (see Setting server parameters). Removing
insights from the instance’s preloaded libraries requires a restart and is also a
server-parameter change made through Snowsight.
Troubleshooting¶
No data is being collected¶
Confirm collections are enabled and due:
Confirm the background workers are running:
If no insights% workers appear, confirm that insights is preloaded and enabled. These are
instance server parameters, changed through Snowsight (see
Setting server parameters). You can read their current values
with:
SQL statistics are empty¶
Verify pg_stat_statements is installed, preloaded, and tracking:
Permission denied reading insights tables¶
Grant read access as shown in Granting read access.