GitHub
10/09/2026, 5:53 PMshared_preload_libraries, restarts the server, and installs the extension's SQL objects in the relevant databases. Monitoring then queries the extension's views and compares observations over time, accounting for resets. In Cloudberry, the extension also defines how local observations are exposed and aggregated across the coordinator and segments.
This gives each consumer control over its metrics and SQL interface while keeping storage and lifecycle operations in the common cumulative-statistics system. The VACUUM example below follows this path from measurement to SQL.
What Cloudberry has today and why it is insufficient
Before the proposed port, Cloudberry already has a cumulative-statistics infrastructure for built-in kinds, including Cloudberry-specific resource-queue statistics. What is missing is the supported registration API that lets extensions define their own kinds and participate in that infrastructure.
There are two existing approaches to adding statistics, each with a limitation:
| Approach | Limitation |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| Add a built-in statistics kind or extend existing core statistics and SQL interfaces | Metric-specific changes become core changes; adding catalog functions or system-view columns also requires catalog maintenance |
| Keep statistics in an extension-owned store | The extension must maintain its own storage, synchronization, reset, and persistence behavior |
For example, pg_stat_statements maintains its own shared hash table with a limit set by pg_stat_statements.max and removes entries when it fills up. This illustrates the separate storage machinery an extension maintains today. pg_stat_statements implementation
The common cumulative-statistics system also uses a hash table, backed by dynamic shared memory. It allocates memory as entries are added, without a configured entry-count limit like pg_stat_statements.max. Making this store available to custom kinds would let extensions reuse it. Statistics memory allocation
Proposed implementation and how it works
This mechanism has already been added to PostgreSQL and is documented in PostgreSQL 19. PR #2102 proposes bringing it to Cloudberry by cherry-picking the upstream commits and adapting them, including preservation of Cloudberry-specific resource-queue statistics.
The implementation extends the existing cumulative-statistics infrastructure with registration and access APIs. Its operation and division of responsibilities are described first, followed by the commits that introduce them.
Registration and storage
An extension describes a statistics kind with PgStat_KindInfo and registers it through pgstat_register_kind() while loading through shared_preload_libraries.
Two object models are supported:
| Model | Example use |
| ---------------------------- | -------------------------------------------------- |
| Fixed-numbered statistics | A fixed set of counters for a subsystem |
| Variable-numbered statistics | Separate entries for tables, indexes, or databases |
The kind descriptor defines the data layout, storage properties, and applicable callbacks. Extensions can use pending local updates with callbacks to flush them into shared memory. The write_to_file property controls whether statistics participate in persistence.
The PR also adds an optional reset_data_cb for variable-numbered kinds. It lets a reset clear counters while preserving identifying metadata in the entry payload. Without the callback, the existing zero-fill behavior remains. PR #2102
Limitations
Dynamic allocation does not guarantee that a statistics update will succeed when memory is exhausted. Variable-numbered kinds share the cumulative-statistics memory infrastructure. Their memory use grows with the number of tracked objects and the size of each entry, with additional overhead for the shared hash table, backend-local references, pending updates, and snapshots. There is no per-kind entry-count limit or automatic eviction policy comparable to pg_stat_statements.max.
When a new entry is needed, the current implementation inserts it into the shared hash table and allocates its payload with dsa_allocate0(). This allocation does not use `DSA_ALLOC_NO_OOM`: if memory cannot be allocated, the allocator raises ERROR. The infrastructure therefore does not guarantee that it will simply skip a statistics sample under memory pressure. The error can propagate to the operation collecting the statistics, including a VACUUM reporting through an extension hook. See the local implementation in <../src/backend/utils/activity/pgstat_shmem.c|pgstat_shmem.c>, <../src/include/utils/dsa.h|dsa.h>, and <../src/backend/utils/mmgr/dsa.c|dsa.c>.
This makes memory budgeting and cleanup part of extension design. Extensions should keep payloads compact, avoid unnecessarily high-cardinality keys, and connect object deletion to entry cleanup. A per-kind quota, eviction policy, or a safe way to drop a sample on allocation failure would require additional design; the proposed API does not provide these guarantees. Memory-pressure tests should establish both the error seen by the caller and whether subsequent collection remains usable.
Other limitations also affect consumers:
• Custom kind IDs are limited to 24–32 and must be unique across loaded extensions. Registration happens during preload, so enabling a new module requires a restart.
• Shared-entry locking, pending-update flushing, and snapshot creation have a cost. The API does not guarantee negligible overhead under frequent updates or concurrent access.
• Re…
apache/cloudberry