New to Kestra?
Use blueprints to kickstart your first workflows.
Audit Amazon Redshift database tables for unsorted rows and stale statistics with Kestra and SVV_TABLE_INFO. Send Slack alerts with VACUUM SORT and ANALYZE.
Amazon Redshift relies heavily on sorted data and accurate column statistics for high-throughput columnar analytics. In fast-moving data architectures, two common issues severely degrade cluster performance:
unsorted > 20%), Redshift zone maps (min/max block ranges) lose their effectiveness. Queries are forced to scan entire disk blocks rather than pruning skipped slices, dramatically inflating I/O and query duration. Note that heap tables without sort keys report 100% unsorted by design; this sentinel automatically filters those out of sort alerts.stats_off > 10), the cost-based query optimizer makes poor join order decisions, hash join memory misallocations, and unnecessary table broadcasts across compute slices.This sentinel flow focuses specifically on unsorted row bloat (for tables with defined sort keys) and optimizer statistics staleness across tables in the target database. It establishes automated weekly operational governance for target Redshift databases by inspecting the SVV_TABLE_INFO system view, flagging tables requiring maintenance, and providing exact VACUUM SORT ONLY "schema"."table" TO 100 PERCENT; and ANALYZE "schema"."table" THRESHOLD 0 PERCENT; commands in Slack incident cards.
weekly_redshift_maintenance_audit trigger (io.kestra.plugin.core.trigger.Schedule) executes every Sunday at 02:00 UTC (cron: "0 2 * * 0", timezone: "UTC"). It ships with disabled: true by default so manual verification can occur first.fetch_database_context (io.kestra.plugin.jdbc.redshift.Query) queries SELECT current_database() AS "database_name" to dynamically resolve the connected catalog name for incident tagging.audit_redshift_table_bloat_and_stats (io.kestra.plugin.jdbc.redshift.Query) queries the Amazon Redshift SVV_TABLE_INFO catalog view. It flags relations exceeding unsorted_pct_threshold (for tables with sortkey_num > 0) or stats_off_threshold while filtering out tables smaller than min_table_size_mb. It explicitly excludes temporary schemas (pg!_temp!_%) and system catalogs (pg_catalog, information_schema, pg_internal).emit_audit_manifest (io.kestra.plugin.core.debug.Return) returns a structured JSON manifest at {{ outputs.emit_audit_manifest.value }} containing audit evaluation timestamps, database metadata, anomaly totals, and table details before any external dispatch.evaluate_table_health (io.kestra.plugin.core.flow.If) branches execution based on whether anomalous tables were returned.notify_slack_incident (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) delivers an operational triage card with database context, affected tables, size (MB), unsorted %, stats_off score, and exact VACUUM and ANALYZE commands.log_clean_status (io.kestra.plugin.core.log.Log) logs confirmed cluster health in execution logs.errors block alerts Slack if the sentinel flow itself fails to connect to Amazon Redshift.flowchart TD
ScheduleTrigger["Weekly Maintenance Trigger (Cron: 0 2 * * 0 UTC)"] --> GetDB["Fetch Database Context via current_database()"]
ManualTrigger["Manual Execution / API"] --> GetDB
GetDB --> QuerySVV["Query SVV_TABLE_INFO for Connected Database"]
QuerySVV --> EmitManifest["Emit JSON Audit Manifest (Structured Telemetry)"]
EmitManifest --> EvalHealth{"Anomalous Tables Detected?\n(sortkey_num > 0 AND unsorted >= 20% OR stats_off >= 10)"}
EvalHealth -- "Yes (Anomalies Exist)" --> SlackAlert["Dispatch Operational Incident Card to Slack\n(Database, Table, Size, Unsorted %, Stats Off, Remediation)"]
EvalHealth -- "No (Database Clean)" --> LogClean["Log Confirmed Healthy Database Status"]
GetDB -. "Workflow Error" .-> ErrorSlack["Alert Slack: Sentinel Workflow Execution Failed"]
QuerySVV -. "Workflow Error" .-> ErrorSlack
VACUUM SORT ONLY "schema"."table" TO 100 PERCENT; and ANALYZE "schema"."table" THRESHOLD 0 PERCENT; syntax generated directly in Slack alerts, forcing statistics recalculation even when customized session analyze_threshold_percent cutoffs exceed default sensitivity.sortkey_num > 0 before recommending sort maintenance, preventing intentional heap tables without sort keys from raising false-positive VACUUM alerts.pg_temp_* session-scoped temporary tables and system catalog schemas (pg_catalog, information_schema, pg_internal) using escaped SQL patterns, ensuring short-lived ETL scratch tables do not generate false-positive operational incidents.plain_text, immunizing alerts from syntax breaking or accidental Slack token mentions (<!channel>).{{ outputs.emit_audit_manifest.value }} for automated compliance tracking and downstream pipelines.VACUUM and ANALYZE commands delivered directly to operational triage channels.Amazon Redshift provides internal auto-vacuum and auto-analyze routines, but in high-velocity workloads with continuous batch loads, automated background worker threads frequently defer maintenance during peak business hours. When statistics drift or bloat builds up between auto-vacuum windows, data platform teams have no native visibility into cluster-wide table degradation until end-user dashboards fail or queries spike in queue wait times.
Orchestrating this sentinel with Kestra delivers:
sys:operator role to query SVV_TABLE_INFO.Configure the following secrets in your Kestra namespace (Settings > Secrets):
| Secret Name | Description & Purpose | Example / Format |
|---|---|---|
REDSHIFT_JDBC_URL |
JDBC connection URL pointing to the Amazon Redshift cluster and target database. | jdbc:redshift://cluster-id.region.redshift.amazonaws.com:5439/analytics |
REDSHIFT_USER |
Dedicated Redshift user or service account with superuser or sys:operator privileges. |
kestra_sentinel_svc |
REDSHIFT_PASSWORD |
Password for the Redshift service account. | ******** |
SLACK_WEBHOOK_URL |
Incoming Webhook URL to deliver operational alert cards to Slack (e.g., #dataops-alerts). |
https://hooks.slack.com/services/T00/B00/XXXX |
REDSHIFT_JDBC_URL, REDSHIFT_USER, REDSHIFT_PASSWORD, and SLACK_WEBHOOK_URL.triggers and set disabled: false:triggers:
- id: weekly_redshift_maintenance_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "0 2 * * 0"
timezone: "UTC"
disabled: false
{{ outputs.emit_audit_manifest.value }}.outputs.audit_redshift_table_bloat_and_stats.rows to automatically run VACUUM SORT ONLY and ANALYZE during dedicated off-peak maintenance windows.pg_database and dynamically executes this sentinel across all databases in the Amazon Redshift cluster.