Add vacuum activity information to database diagnostics

What & why

Adds an Vacuum information section to the admin Database Diagnostics page (/admin/database_diagnostics) showing in-progress (auto)vacuum operations per database from pg_stat_progress_vacuum — phase, heap-scan progress, index progress, dead-tuple usage, and index passes. delay_time is shown on PostgreSQL 18+. Reads run on the primary, scoped to the current database.

Screenshot

Screenshot_2026-06-18_at_11.05.10_AM

How to verify

Apply patch with sample dataset:

diff --git a/lib/gitlab/database/database_information.rb b/lib/gitlab/database/database_information.rb
--- a/lib/gitlab/database/database_information.rb	(revision 0ae0c4d5a54fd3e023ea1aee284878a9f6975c83)
+++ b/lib/gitlab/database/database_information.rb	(date 1781737345474)
@@ -106,6 +106,8 @@
       # would report an empty progress view. Byte/count columns are returned as
       # integers and delay_time (PostgreSQL 18+) as a float or nil.
       def collect_vacuums(connection)
+        return sample_vacuums # TODO: REMOVE — temporary UI verification stub
+
         sql = format(VACUUM_PROGRESS_SQL, delay_time_column: delay_time_column(connection))
 
         rows = Gitlab::Database::LoadBalancing::SessionMap
@@ -134,6 +136,36 @@
         end
       end
 
+      # TODO: REMOVE — temporary sample data for UI verification only.
+      def sample_vacuums
+        [
+          # Everything lit up: autovacuum + anti-wraparound + long-running + memory pressure
+          { pid: 4242, schema_name: 'public', table_name: 'ci_builds', phase: 'vacuuming indexes',
+            heap_blks_total: 1_000_000, heap_blks_scanned: 640_000, heap_blks_vacuumed: 600_000,
+            index_vacuum_count: 3, max_dead_tuple_bytes: 268_435_456, dead_tuple_bytes: 268_400_000,
+            indexes_total: 8, indexes_processed: 5, vacuum_type: 'autovacuum', anti_wraparound: true,
+            running_time_seconds: 32_400, delay_time: 12.5 },
+          # Autovacuum, long-running but otherwise healthy
+          { pid: 4243, schema_name: 'public', table_name: 'merge_request_diffs', phase: 'scanning heap',
+            heap_blks_total: 500_000, heap_blks_scanned: 120_000, heap_blks_vacuumed: 90_000,
+            index_vacuum_count: 1, max_dead_tuple_bytes: 67_108_864, dead_tuple_bytes: 12_000_000,
+            indexes_total: 4, indexes_processed: 0, vacuum_type: 'autovacuum', anti_wraparound: false,
+            running_time_seconds: 25_200, delay_time: 0.0 },
+          # Manual VACUUM, short-running
+          { pid: 4244, schema_name: 'public', table_name: 'notes', phase: 'cleaning up indexes',
+            heap_blks_total: 80_000, heap_blks_scanned: 80_000, heap_blks_vacuumed: 80_000,
+            index_vacuum_count: 1, max_dead_tuple_bytes: 16_777_216, dead_tuple_bytes: 2_000_000,
+            indexes_total: 3, indexes_processed: 3, vacuum_type: 'manual', anti_wraparound: false,
+            running_time_seconds: 420, delay_time: nil },
+          # Autovacuum, just started, nothing flagged
+          { pid: 4245, schema_name: 'public', table_name: 'users', phase: 'initializing',
+            heap_blks_total: 12_000, heap_blks_scanned: 0, heap_blks_vacuumed: 0,
+            index_vacuum_count: 0, max_dead_tuple_bytes: 4_194_304, dead_tuple_bytes: 50_000,
+            indexes_total: 2, indexes_processed: 0, vacuum_type: 'autovacuum', anti_wraparound: false,
+            running_time_seconds: 45, delay_time: 0.0 }
+        ]
+      end
+
       # 'autovacuum worker' is the backend_type PostgreSQL reports for vacuums
       # launched by the autovacuum daemon; anything else (a client backend) is
       # a manually issued VACUUM.

Visit https://gdk.test:3000/admin/database_diagnostics page

References

Edited by Niko Belokolodov

Merge request reports

Loading
Loading