Schedule icon
Query icon
Return icon
If icon
SlackIncomingWebhook icon
Log icon

Amazon Redshift Table Unsorted Bloat and Stale Statistics Sentinel

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.

Categories
CloudDataInfrastructure

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:

  1. Unsorted Row Bloat: As unsorted rows accumulate (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.
  2. Stale Optimizer Statistics: When table statistics age (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.

How it works

  1. Scheduled Maintenance Audit: The 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.
  2. Database Context Resolution: 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.
  3. System Catalog Inspection: 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).
  4. Audit Telemetry Manifest: 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.
  5. Health Evaluation Gate: evaluate_table_health (io.kestra.plugin.core.flow.If) branches execution based on whether anomalous tables were returned.
  6. Slack Incident Dispatch: When anomalies are detected, 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.
  7. Clean Cluster Confirmation: When all audited tables satisfy hygiene thresholds, log_clean_status (io.kestra.plugin.core.log.Log) logs confirmed cluster health in execution logs.
  8. Pipeline Error Handling: The 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

What you get

  • Automated Bloat & Staleness Governance: Proactive detection of unsorted row bloat and optimizer drift before mission-critical analytical queries or ETL jobs time out.
  • Exact SQL Remediation with Forced Thresholds: Targeted 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.
  • Sort Key Awareness: Evaluates sortkey_num > 0 before recommending sort maintenance, preventing intentional heap tables without sort keys from raising false-positive VACUUM alerts.
  • Session-Temporary & System Table Exclusion: Explicitly filters out 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.
  • Delimited-Safe Data Passing & Plain Text Labels: Passes database context and thresholds as structured data into JQ and renders attribution in plain_text, immunizing alerts from syntax breaking or accidental Slack token mentions (<!channel>).
  • Accessible Plain-Text Fallback Synthesis: Omits top-level mrkdwn fallback so Slack synthesizes notifications directly from typed plain-text header, section, and context blocks.
  • Bounded Slack Block Kit Layout: Formats each flagged relation as its own dedicated section block, preventing Slack's 3,000-character section limit while abiding by Slack's 50-block ceiling (capped at 47 relations).
  • Structured JSON Manifest: Emits telemetry at {{ outputs.emit_audit_manifest.value }} for automated compliance tracking and downstream pipelines.

Who it's for

  • Data Platform & DataOps Engineers: Maintaining Amazon Redshift clusters who need automated maintenance alerting without building complex Lambda monitors.
  • Analytics Engineers: Optimizing query performance, dbt build runtimes, and table health across large dimensional models and staging layers.
  • Database Administrators (DBAs): Seeking prioritized, copy-paste VACUUM and ANALYZE commands delivered directly to operational triage channels.

Why orchestrate this with Kestra

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:

  • Declarative Governance: A serverless, configuration-driven sentinel workflow that runs over standard JDBC without maintaining separate Python worker containers or AWS Lambda infrastructure.
  • Integrated Observability: Combines catalog metadata queries, conditional branching, Slack operational dispatch, and structured execution telemetry in a unified UI.
  • Audit Trail & History: Complete execution records and historical audit manifests stored directly in Kestra for Day 2 operations and compliance audits.

Prerequisites

  • An active Amazon Redshift cluster accessible via JDBC.
  • A dedicated Redshift service account with superuser privileges or granted sys:operator role to query SVV_TABLE_INFO.
  • An incoming Slack webhook configured for your DataOps or database administration channel.

Secrets

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

Quick start

  1. Configure Secrets: Navigate to Administration > Secrets in the Kestra UI (or configure namespace secrets via CI/CD) and add REDSHIFT_JDBC_URL, REDSHIFT_USER, REDSHIFT_PASSWORD, and SLACK_WEBHOOK_URL.
  2. Import Blueprint: Import this flow YAML into your Kestra instance.
  3. Execute Initial Audit: Click Execute in the UI to perform an immediate on-demand inspection of table hygiene in the connected database.
  4. Enable Weekly Schedule: Once verified, edit the flow under 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
    
  5. Consume Audit Output: Access structured JSON telemetry in downstream flows or dashboards via {{ outputs.emit_audit_manifest.value }}.

How to extend

  • Automated Remediation Loop: Add a downstream task iterating over outputs.audit_redshift_table_bloat_and_stats.rows to automatically run VACUUM SORT ONLY and ANALYZE during dedicated off-peak maintenance windows.
  • Multi-Database Fanout: Wrap this flow in a parent orchestration loop that queries pg_database and dynamically executes this sentinel across all databases in the Amazon Redshift cluster.
  • Multi-Channel Dispatch: Route incident cards to Microsoft Teams, PagerDuty, or Jira Service Management using Kestra's notification plugin ecosystem.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.