Skip to main content

Agent monitoring and privacy

Data privacy and security

What DBtune collects

The agent collects only the metrics needed to optimize your database:

  • Performance metrics: query runtime, throughput, cache hit ratios.
  • System metrics: CPU utilization, memory usage, I/O statistics.
  • Database statistics: connection counts, wait events, vacuum activity.
  • Configuration parameters: current database configuration settings.
  • Hardware information: CPU count, memory size, disk type, instance type.
  • Schema metadata: catalogs describing your tables, columns, indexes, and constraints (no row data).

All transmitted data is either numeric, structural (catalog rows), or obfuscated query text used for query identification on the platform.

Query text

Query text collection is optional. Toggle it with the DBT_POSTGRESQL_INCLUDE_QUERIES environment variable, or with the per-collector include_queries knob on the pg_stat_statements collector.

If enabled, table and column names that appear in pg_stat_statements.query are transmitted along with the obfuscated parameters. See the PostgreSQL pg_stat_statements docs for what that field contains.

Query text is not used for optimization. Its only purpose is to let you identify queries in the platform, e.g. when picking queries for a Workload Fingerprint. DBtune still works without it; in that case we surface a query_id you can correlate manually with pg_stat_statements.

note

If you previously enabled query text and then disabled it, the obfuscated text already collected is retained. Email support@dbtune.com if you want it deleted.

What DBtune does NOT collect

The agent never reads or transmits:

  • Database contents: no row data, no stored values.
  • Query parameters: obfuscated by pg_stat_statements, or omitted entirely when query text is disabled.
  • Credentials: no passwords, API keys, or authentication tokens.
  • Personal data: no end-user information.

How collection works

Collection is per-collector, not a single global stream. Each collector has its own purpose, its own data source, and its own schedule, ranging from every 5 seconds for hot signals like wait events down to every 5 minutes for slow-moving catalog data.

Every collector ships with two universal knobs:

  • DBT_COLLECTOR_<NAME>_ENABLED. Set to false to turn the collector off.
  • DBT_COLLECTOR_<NAME>_INTERVAL_SECONDS. Overrides the default cadence (subject to a per-collector minimum).

Some collectors expose extra knobs, listed inline below where they apply. Defaults are sensible for most workloads; you should not need to touch these unless you are deliberately tuning the agent's footprint or privacy posture.

Collectors that target version-gated views (e.g. pg_stat_io on PG16+, pg_stat_checkpointer on PG17+) automatically skip themselves on older PostgreSQL releases.

Collector reference

The tables below list every collector the agent ships, grouped by what it watches. The "Source" column points at the underlying PostgreSQL view, system file, or cloud API.

Hot signals (every 5 seconds)

These are sampled aggressively because they drive real-time tuning decisions.

CollectorSourceWhat it captures
wait_eventspg_stat_activityCounts of backends waiting on each wait event type (Lock, IO, IPC, LWLock, etc.)
database_connectionspg_stat_activityActive / idle / idle-in-transaction / aborted / total connection counts
database_transactionspg_stat_databaseCumulative commit count, converted to TPS between samples
autovacuum_countpg_stat_activityNumber of currently running autovacuum workers
system_db_sizepg_database_size()Total bytes across all databases on the instance
server_uptimepg_postmaster_start_time()Server uptime in minutes

Database-wide statistics (every minute)

CollectorSourceWhat it captures
pg_stat_databasepg_stat_databasePer-database commits, rollbacks, block I/O, tuple I/O, deadlocks, session time, temp files
pg_stat_database_conflictspg_stat_database_conflictsReplication conflict counts by type (PG17+)
pg_stat_bgwriterpg_stat_bgwriterBackground-writer checkpoints, buffers written, fsync time
pg_stat_checkpointerpg_stat_checkpointerCheckpointer-process metrics (PG17+)
pg_stat_iopg_stat_ioFine-grained I/O by backend type, object, and context (PG16+)
pg_stat_walpg_stat_walWAL records, FPIs, bytes, buffer-full count, write/sync timing (PG14+)
pg_stat_archiverpg_stat_archiverWAL archive successes/failures and last archived file
pg_stat_slrupg_stat_slruSLRU buffer pool I/O (commit timestamps, multixact, etc.)
pg_databasepg_databasePer-database metadata, frozen XID age, multixact age

Query and session activity (every minute, hot collectors faster)

CollectorSourceWhat it capturesNotes
pg_stat_statementspg_stat_statementsPer-statement execution time, call count, rows, buffer I/O, plan time, JIT, WAL statsEvery 5 s. Honors include_queries, max_query_text_length, diff_limit (see below)
pg_stat_activitypg_stat_activityBackend PID, user, app, wait event, transaction age, query ID (never query text)
pg_lockspg_locks + pg_blocking_pids()Only blocked-or-blocking locks, with wait time and lock modeEvery 30 s
pg_prepared_xactspg_prepared_xactsPrepared (two-phase commit) transactions and their age
pg_stat_user_functionspg_stat_user_functionsPer-function call count and execution time (top 500 by calls)

Configuration knobs for pg_stat_statements:

  • include_queries (default: true). If false, the query column is sent as NULL instead of obfuscated SQL. Same effect as DBT_POSTGRESQL_INCLUDE_QUERIES=false.
  • max_query_text_length (default and max: 8192). Truncates query text to this many characters.
  • diff_limit (default and max: 500). Caps the number of statement deltas reported per tick.

Tables and indexes (every minute)

CollectorSourceWhat it capturesNotes
pg_stat_user_tablespg_stat_user_tablesPer-table seq/index scans, row churn, vacuum/analyze counts and timing, dead tuplesSampled across three buckets (writes, reads, dead tuples), default 200 rows each
pg_stat_user_indexespg_stat_user_indexesPer-index scan count, last scan time, tuples read/fetchedSampled across three buckets (scans, rows returned, unused)
pg_statio_user_tablespg_statio_user_tablesPer-table heap, index, and toast block reads/hitsTop 500 active tables
pg_statio_user_indexespg_statio_user_indexesPer-index block reads vs cache hitsDelta-mode after backfill; backfill batch default 2 000

Configuration knobs:

  • category_limit on pg_stat_user_tables and pg_stat_user_indexes (default: 200). Caps rows per sampling bucket.
  • backfill_batch_size on pg_statio_user_indexes (default: 2 000). Sets the initial-load batch size before delta mode kicks in.

Replication (every minute)

CollectorSourceWhat it captures
pg_stat_replicationpg_stat_replicationPer-standby LSN positions, replication lag, sync state, Xmin age
pg_stat_wal_receiverpg_stat_wal_receiverStandby WAL receiver status and LSN positions
pg_replication_slotspg_replication_slotsReplication slot state, LSN positions, WAL retention, Xmin age, conflict status
pg_stat_replication_slotspg_stat_replication_slotsSlot streaming activity: spill / stream transactions and bytes (PG14+)
pg_stat_subscriptionpg_stat_subscriptionPer-subscription worker state and LSN
pg_stat_subscription_statspg_stat_subscription_statsLogical-replication apply / sync error counts (PG15+)
pg_stat_recovery_prefetchpg_stat_recovery_prefetchStandby recovery-prefetch metrics: cache hits, skips, I/O depth (PG15+)

Progress reporting (every 30 seconds)

CollectorSourceWhat it captures
pg_stat_progress_vacuumpg_stat_progress_vacuumIn-flight VACUUM / autovacuum phase, blocks scanned, dead tuples
pg_stat_progress_analyzepg_stat_progress_analyzeIn-flight ANALYZE phase, sample blocks scanned, extended-stats progress
pg_stat_progress_create_indexpg_stat_progress_create_indexIn-flight CREATE INDEX phase, block and tuple progress

Schema and catalog metadata (every 5 minutes)

These collectors describe what your schema looks like; they do not read row data.

CollectorSourceWhat it capturesNotes
pg_classpg_class + pg_namespace + pg_am + pg_stat_user_tablesTables, indexes, matviews: page count, tuple estimates, freezing age, access method, partitioning infoBackfill in 500-row batches; full rescan periodically
pg_indexpg_index + pg_classIndex keys, opclasses, predicates, expressions, validity, and full DDL via pg_get_indexdef()
pg_attributepg_attribute + pg_classColumn metadata: type, length, storage method, NOT NULL, statistics target
pg_constraintpg_constraintPrimary keys, unique, foreign-key, exclusion constraints
pg_typepg_type + pg_namespaceBuilt-in and user-defined data types and their propertiesSkipped if unchanged; heartbeat every 5 ticks
pg_statspg_statsColumn statistics: null fraction, distinct count, correlation, histograms, MCVsBackfill in 200-row batches. include_table_data=false strips MCV/histogram values for privacy
ddlpg_get_*def()Hash and full DDL of every user-schema object (tables, views, indexes, sequences, functions, types)Skipped if unchanged; heartbeat every 5 ticks

Configuration knob:

  • include_table_data on pg_stats (default: true). Set to false to omit the actual values inside MCV arrays and histogram bounds. Statistical shape is preserved either way.

System monitoring

PostgreSQL statistics tell us what the database is doing; system monitoring tells us what the host underneath can take. The agent pairs the two so DBtune can size memory-bound parameters (shared_buffers, work_mem, effective_cache_size), reason about I/O headroom (random_page_cost, effective_io_concurrency), and avoid recommending settings the machine cannot support.

Host metrics (every 5 seconds)

The agent samples the live state of the host alongside the database. These are the metrics that move minute-to-minute and feed directly into tuning decisions.

GroupMetrics
CPUutilization (overall and, where available, per-core)
Memorytotal, available, used, free, cached, buffers, shared, slab, active, inactive, percent used
Disk I/Oread and write counts, bytes, time, merged counts; busy time; queue depth where available
Network (containers only)bytes in/out

The exact source depends on where your database lives:

PlatformSourceNotes
Self-hosted, Patroni, on-premisegopsutil (host-local CPU, memory, disk I/O)Highest fidelity: full per-device breakdown
DockerDocker stats APILimited to container-visible CPU and memory
Kubernetes / CNPGKubernetes metrics API + cAdvisor + kubeletContainer CPU, memory, disk usage, IOPS, network I/O
AWS RDS / AuroraCloudWatch + Performance InsightsCPU utilization, memory used and freeable, IOPS read/write/total
Google Cloud SQLGoogle Cloud MonitoringCPU, memory, disk usage, IOPS, network bytes
AivenAiven metrics API1-hour resolution, cached. Tuning is therefore coarser than on self-hosted setups
Azure Database for PostgreSQL Flexible ServerAzure MonitorCPU, memory, IOPS

Cloud platforms only expose what their metrics APIs allow; on managed services you can expect CPU, memory, and IOPS, but not the per-device disk breakdown available on self-hosted hosts.

System information (every minute)

Slow-moving facts about the machine and the database server are refreshed once a minute. These define the envelope DBtune tunes inside, and rarely change between samples.

GroupWhat we collect
HardwareNumber of CPUs, total memory, available memory, disk type, cloud provider, instance type
SoftwarePostgreSQL version, operating system, maximum connections, total database size

Hardware shape is what lets DBtune translate a recommendation like "use ~25% of RAM for shared_buffers" into an actual byte value, and what flags an instance as too small for a target before any change is made.

What system monitoring is not

The agent does not run shell commands on the host, does not read arbitrary files, and does not collect process-level metrics for processes outside the database. On managed platforms it never bypasses the provider's metrics API.

Data transmission

All metrics travel over encrypted HTTPS to the DBtune server, authenticated with your API key. Keep that key secure and rotate it periodically.

Compliance and trust

  • Open source agent: the source lives at github.com/dbtuneai/dbtune-agent, so every collector and every query above is auditable.
  • Network isolation: the agent runs inside your network and only egresses to the DBtune API.
  • Production safety: built-in guardrails (e.g. memory thresholds) prevent unsafe configuration changes.
  • Per-collector control: anything you do not want collected can be turned off with a single environment variable.

For more on how individual tuning targets are computed from these metrics, see Tuning targets.