New to Kestra?
Use blueprints to kickstart your first workflows.
Audit PostgreSQL with Kestra - slow queries from pg_stat_statements, seq-scan index candidates, one Slack advisory, weekly or on demand.
PostgreSQL records every statement in pg_stat_statements, but the view only answers questions someone remembers to ask. Nobody spot-checks it weekly, the report never reaches the team channel, and the table that has been doing sequential scans for months keeps doing them. This blueprint turns that view into a standing advisory: the queries that deserve attention, the tables that probably deserve an index, delivered where the team already reads.
fetch_slow_queries (io.kestra.plugin.jdbc.postgresql.Query, fetchType: FETCH) reads pg_stat_statements for statements whose mean time is at least min_mean_ms and that ran at least min_calls times, ordered by cumulative time, with newlines flattened out of the SQL text and capped at top_n rows.fetch_totals (same plugin, FETCH_ONE) aggregates the same filters into a count and a cumulative-time figure so the Slack message can state totals without parsing rows in Pebble.fetch_index_candidates reads pg_stat_user_tables for tables with at least min_table_rows estimated rows where sequential scans outnumber index scans - the classic shape of a query that should have been an index scan.audit_gate (io.kestra.plugin.core.flow.If) posts the advisory to Slack when either list is non-empty, and logs a quiet all-clear otherwise. The alert lists each slow query with its call count, mean and total time, and each candidate table with its scan counts.errors handler posts a distinct Slack message when the audit itself fails, so a broken connection or a missing extension is loud instead of silently missing a week.The thresholds are deliberately inputs: a 20 ms floor suits an OLTP fleet, a 500 ms floor suits an analytics warehouse, and min_calls keeps a single exploratory statement from dominating the report.
A pg_stat_statements query in a cron job is a script: no retries when the connection blips, no execution history when someone asks what the report said three weeks ago, no built-in alert when the query itself breaks. Kestra gives the audit scheduled and event triggers, retries, execution lineage, inputs you can tune without editing SQL, and a failure path that pages instead of vanishing into a cron log.
mean_exec_time / total_exec_time columns).pg_stat_statements extension installed and loaded via shared_preload_libraries (managed services usually expose it as a parameter).POSTGRES_JDBC_URL: JDBC URL for the database (for example jdbc:postgresql://host:5432/postgres).POSTGRES_USERNAME: database username.POSTGRES_PASSWORD: database password.SLACK_WEBHOOK_URL: Slack incoming webhook URL for the advisory and failure alerts.SELECT count(*) FROM pg_stat_statements;.fetch_slow_queries output rows.on_demand webhook with your own key, then enable the weekly schedule.min_mean_ms and min_calls to keep the channel quiet, or lower them after a migration to catch small regressions.audit_gate that opens a GitHub issue from the same rows, so the advisory leaves a permanent backlog item.Flow trigger and compare the outputs between releases.slowest_query into an EXPLAIN automation that plans the statement against production statistics.