How nikolays/pg_ash works
Purpose and entry points
pg_ash is a pure SQL/PL/pgSQL Active Session History subsystem installed inside PostgreSQL. It samples live activity, retains compact history, and exposes SQL readers for incident analysis. Primary entry point: sql/ash-install.sql; current full implementation: sql/ash-1.5-to-2.0.sql and versioned install scripts such as sql/ash-1.5.sql.
Installation, schema, and lifecycle
Installation creates the ash schema, storage objects, functions, privileges, and catalog documentation. Administrative control is through ash.start(), ash.stop(), ash.status(), manual sampling, rotation, rollups, reader grants, and destructive rebuild/uninstall operations. Upgrade is explicit and ordered through sql/migrations/ash-1.0-to-1.1.sql through sql/migrations/ash-1.5-to-2.0.sql; root-level migration files remain compatibility wrappers.
Sampling and query attribution
ash.take_sample() reads PostgreSQL runtime statistics, principally pg_stat_activity, and stores active-session wait state rather than idle heartbeats. It records query IDs and can enrich reader output with text through optional pg_stat_statements; sampling remains functional without that extension, but attribution/text is degraded. The sampler requires appropriate statistics visibility, notably pg_read_all_stats, to observe other roles’ query IDs.
Raw retention boundary
Raw history uses a partitioned ring: partitions are rotated and old slots truncated, yielding bounded short-term evidence. Rotation also protects data by requiring raw samples to be rolled into minute aggregates before endangered partitions are removed. Partition geometry, retention safety checks, and query-map reconstruction are part of the install/runtime SQL in sql/ash-1.5-to-2.0.sql; the intended partition/rollup design is documented in blueprints/CONFIGURABLE_PARTITIONS_AND_ROLLUP.md.
Compaction pipeline
Two retention tiers preserve longer history: ash.rollup_minute() folds raw samples into rollup_1m, then ash.rollup_hour() compacts minute history into rollup_1h; ash.rollup_cleanup() expires rollups. This is a deliberate fidelity boundary: raw preserves exact query/wait links, while rollups retain aggregates and limited query attribution. Reader plans disclose source/grain and degrade honestly when only coarser history is available.
Reader and reporting API
The ash.* reader surface provides progressive investigation: periods() identifies affected windows; timeline() locates spikes; top() ranks waits, query IDs, and databases; samples() returns raw evidence. aas(), compare(), summary(), chart(), and JSONB report() serve scalar, before/after, terminal, and machine-consumer use cases. Query-specific and combined wait/query filters force raw reads, preventing rollup omissions from being misrepresented as zero.
Scheduling and runtime dependencies
PostgreSQL 14+ is the material runtime. pg_cron is optional: when available, ash.start() schedules sampling, rotation, rollups, and cleanup; otherwise the database stores intended cadence and operators run the same functions externally via psql/cron. pg_stat_statements and compute_query_id are optional but recommended dependencies for useful query attribution. The project targets managed PostgreSQL because it needs neither a C extension nor server restart.
Delivery validation and demonstrations
CI validates fresh installation and upgrade chains using repository-discovered SQL paths; discovery logic is in devel/scripts/ash_sql_chain.py and workflow orchestration in .github/workflows/test.yml. The terminal demonstration drives a real PostgreSQL workload, queries the public API, and renders reproducible artifacts through demos/bin/ash-demo, demos/lib/seed.sql, and demos/render/ansi2svg.py.
Main entry points: ash-1.5-to-2.0.sql Raw partition ring · test.yml Install & upgrade CI · ash-demo Terminal demo · ash-install.sql Install entry point
Components 21
Install & lifecycle
- Install entry point
sql/ash-install.sql - ASH 2.0 implementation · Creates schema, storage, functions, privileges, and documentation.
sql/ash-1.5-to-2.0.sql - Ordered migrations · Explicit upgrades span 1.0 through 2.0.
sql/migrations/ash-1.0-to-1.1.sql - Lifecycle controls · start, stop, status, manual sampling, rotation, and rebuild controls.
Capture & retention
- pg_stat_activity · Live session, wait-state, and query-ID source.
- take_sample() · Stores active-session evidence and skips idle heartbeats.
- Raw partition ring · Rotated partitions retain short-term exact query/wait links.
sql/ash-1.5-to-2.0.sql - Rotation safety · Rolls endangered raw data up before truncating old slots.
sql/ash-1.5-to-2.0.sql - rollup_1m
- rollup_1h
- Rollup & cleanup · Compacts minute history to hours and expires aggregate history.
Reader API
- Investigation readers · periods, timeline, top, samples, aas, compare, summary, chart, and report.
- Exact raw filters · Query-specific and wait/query filters force raw reads.
Validation & demo
- SQL chain discovery
devel/scripts/ash_sql_chain.py - Install & upgrade CI · Validates fresh installs and upgrade chains.
.github/workflows/test.yml - Terminal demo · Drives a live workload and queries the public API.
demos/bin/ash-demo - Demo workload
demos/lib/seed.sql - ANSI artifact renderer
demos/render/ansi2svg.py
Other components
- PostgreSQL 14+ · Hosts the pure SQL/PLpgSQL subsystem.
- pg_stat_statements · Enriches query IDs with query text when available.
- pg_cron or external cron · Runs sampling, rotation, rollups, and cleanup on the intended cadence.
Connections 26
- Install entry point → ASH 2.0 implementation: loads
- ASH 2.0 implementation → PostgreSQL 14+: installs into
- ASH 2.0 implementation → Lifecycle controls: defines
- ASH 2.0 implementation → Raw partition ring: defines
- Lifecycle controls → take_sample(): controls
- pg_stat_activity → take_sample(): sampled by
- take_sample() → Raw partition ring: writes active evidence
- pg_stat_statements → take_sample(): optional query-text enrichment
- pg_cron or external cron → Lifecycle controls: invokes scheduled work
- Rotation safety → Raw partition ring: rotates and truncates
- Raw partition ring → Rotation safety: must roll up before removal
- Raw partition ring → rollup_1m: folded by rollup_minute
- rollup_1m → rollup_1h: compacted by rollup_hour
- Rollup & cleanup → rollup_1m: maintains
- Rollup & cleanup → rollup_1h: maintains and expires
- Investigation readers → Raw partition ring: reads exact evidence
- Investigation readers → rollup_1m: reads minute grain
- Investigation readers → rollup_1h: falls back to hour grain
- Exact raw filters → Investigation readers: constrains plans
- Exact raw filters → Raw partition ring: requires
- SQL chain discovery → Install & upgrade CI: supplies SQL paths
- Install & upgrade CI → Install entry point: validates fresh install
- Install & upgrade CI → Ordered migrations: validates upgrades
- Demo workload → Terminal demo: generates workload
- Terminal demo → Investigation readers: exercises
- Terminal demo → ANSI artifact renderer: renders artifacts with