Understanding Redshift Monitoring
Amazon Redshift is a fully managed petabyte-scale data warehouse service that runs complex analytical queries against large datasets. Monitoring Redshift involves tracking performance metrics, query execution patterns, resource utilization, and system health indicators to ensure your data warehouse operates efficiently and cost-effectively. Unlike transactional databases, Redshift's columnar storage and massively parallel processing (MPP) architecture requires a distinct monitoring approach focused on query throughput, disk utilization, and cluster coordination.
Effective monitoring provides visibility into three critical layers: the cluster layer (hardware resources like CPU, memory, disk I/O), the query layer (execution plans, queue times, concurrency), and the data layer (storage distribution, vacuum operations, table statistics). Each layer generates distinct metrics that collectively paint a complete picture of warehouse health.
Why Redshift Monitoring Matters
Without proper monitoring, Redshift clusters can silently degrade in performance, leading to slow queries, failed ETL jobs, and ballooning costs. Here are the key reasons monitoring is essential:
- Cost optimization — Redshift charges by the hour per node. Over-provisioned clusters waste money; under-provisioned clusters cause query failures. Monitoring helps right-size your cluster based on actual usage patterns.
- Query performance troubleshooting — Long-running queries, unusual queue wait times, or sudden spikes in execution time often indicate stale statistics, skewed table distribution, or resource contention that must be addressed.
- Proactive disk management — Redshift nodes have finite storage. Running out of disk space can bring the cluster to a halt. Monitoring disk usage trends lets you take action before critical thresholds are breached.
- Concurrency and workload management (WLM) — When query slots fill up, subsequent queries queue up, causing user-facing delays. Monitoring WLM queue depths reveals whether your slot configuration matches workload demands.
- Compliance and auditing — Tracking connection attempts, schema changes, and access patterns supports security audits and helps detect anomalous activity.
Key Redshift Metrics to Monitor
Redshift exposes metrics through several channels: AWS CloudWatch (host-level and cluster-level metrics), system tables (query-level and internal diagnostics), and the AWS Management Console. Below are the most important metrics organized by category.
1. Cluster Resource Metrics (CloudWatch)
These metrics are automatically collected and published to CloudWatch for every Redshift cluster. They reflect the physical resource consumption of your compute nodes.
CPUUtilization— Percentage of CPU capacity consumed across all nodes. Sustained high CPU (>80%) indicates overwork; investigate expensive queries or consider scaling up.PercentageDiskSpaceUsed— Percentage of total disk space consumed. This is critical: Redshift becomes read-only at 100%. Set alarms at 80-85%.ReadIOPS/WriteIOPS— Disk I/O operations per second. High read IOPS with low query throughput may indicate poor compression or missing sort keys.ReadThroughput/WriteThroughput— Bytes read/written per second. Useful for understanding data scan volumes.NetworkThroughput— Network traffic in bytes. Spikes can indicate large data loads or unloads.HealthStatus— 1 for healthy, 0 for impaired. A sudden drop signals node failure or cluster degradation.MaintenanceMode— 1 when the cluster is in maintenance. Queries may be paused; alerts help correlate unexpected downtime.
2. Query Performance Metrics (System Tables)
Redshift's internal STL and STV system tables provide granular query-level data. These are not pushed to CloudWatch automatically — you must query them directly or via scheduled scripts.
- Query Duration and Throughput:
STL_QUERYcaptures every query's start time, end time, and elapsed duration. Use it to track slow queries and throughput trends over time. - Queue Wait Times:
STL_WLM_QUERYshows how long each query spent waiting in a WLM queue versus executing. High queue times indicate concurrency bottlenecks. - Disk Space by Table:
STV_TBL_PERMreveals table sizes, including raw and compressed bytes. Useful for identifying storage-heavy tables and verifying compression efficiency. - Table Skew and Distribution:
SVV_TABLE_INFOexposes distribution skew (how unevenly rows are spread across slices). Skew above 4x typically requires redistribution. - Transaction Logs and Locking:
STL_TR_CONFLICTandSVV_TRANSACTION_STATEhelp diagnose lock contention and open transactions. - Vacuum and Analyze Status:
SVV_VACUUM_PROGRESSandSTL_VACUUMtrack the progress of vacuum operations, which reclaim deleted row space and re-sort tables.
Querying System Tables for Monitoring Data
The following practical queries extract actionable monitoring data directly from Redshift's system tables. Run these periodically (via cron jobs, Lambda functions, or scheduled queries) to build a comprehensive monitoring pipeline.
Top 10 Longest Recent Queries
SELECT
query,
TRIM(REGEXP_SUBSTR(query_text, '\\n.*', 1, 1, 'e')) AS query_snippet,
DATEDIFF(seconds, starttime, endtime) AS duration_seconds,
aborted,
elapsed_time / 1000000.0 AS elapsed_seconds
FROM STL_QUERY
WHERE starttime >= GETDATE() - INTERVAL '24 hours'
AND query_text NOT LIKE '%STL_%'
AND query_text NOT LIKE '%SVL_%'
AND query_text NOT LIKE '%pg_%'
ORDER BY duration_seconds DESC
LIMIT 10;
This query filters out internal system queries to surface only user-generated work. The REGEXP_SUBSTR extracts the first meaningful line of the SQL for quick identification.
WLM Queue Wait Time Analysis
SELECT
service_class,
query,
DATEDIFF(milliseconds, queue_starttime, queue_endtime) AS queue_wait_ms,
DATEDIFF(milliseconds, queue_endtime, endtime) AS exec_time_ms,
CASE
WHEN DATEDIFF(milliseconds, queue_starttime, queue_endtime) > 60000
THEN 'HIGH_WAIT'
ELSE 'NORMAL'
END AS wait_flag
FROM STL_WLM_QUERY
WHERE queue_starttime >= GETDATE() - INTERVAL '6 hours'
ORDER BY queue_wait_ms DESC
LIMIT 20;
This reveals whether queries are spending excessive time waiting for execution slots. Consistent HIGH_WAIT flags indicate that your WLM concurrency settings need adjustment.
Disk Usage by Table (Top Consumers)
SELECT
database,
schema,
table_id,
"table" AS table_name,
size AS bytes,
size / 1024 / 1024 AS mb,
size / 1024 / 1024 / 1024 AS gb,
tbl_rows
FROM SVV_TABLE_INFO
WHERE "table" NOT LIKE '%_pqt_%' -- exclude internal tables
ORDER BY size DESC
LIMIT 20;
Identifying the largest tables helps prioritize compression optimization (using ANALYZE COMPRESSION) and evaluate distribution key choices.
Table Distribution Skew Detection
SELECT
"schema",
"table",
diststyle,
skew_rows,
sliced_rows,
CASE
WHEN skew_rows > 4.0 THEN 'CRITICAL_SKEW'
WHEN skew_rows > 2.0 THEN 'MODERATE_SKEW'
ELSE 'HEALTHY'
END AS skew_status
FROM SVV_TABLE_INFO
WHERE diststyle NOT IN ('AUTO(ALL)', 'AUTO(EVEN)')
AND skew_rows IS NOT NULL
ORDER BY skew_rows DESC;
Skew ratios above 4 indicate that some slices hold significantly more data than others, causing uneven query workload distribution and slower overall performance.
Active Connections and Session Load
SELECT
COUNT(*) AS total_connections,
COUNT(CASE WHEN current_query <> '' THEN 1 END) AS active_queries,
MAX(DATEDIFF(minutes, query_start, GETDATE())) AS longest_running_minutes
FROM STV_SESSIONS
WHERE user_name NOT IN ('rdsdb', 'rdsadmin');
This quick health check reveals current concurrency pressure and helps identify runaway sessions that may need termination.
Setting Up CloudWatch Alarms
CloudWatch Alarms are the primary mechanism for automated alerting on Redshift metrics. They trigger when a metric crosses a threshold and can send notifications via Amazon SNS (email, SMS, Lambda invocation, or third-party integrations like PagerDuty or Slack).
Creating Alarms via AWS CLI
The following command creates a disk space alarm that triggers when PercentageDiskSpaceUsed exceeds 85% for a sustained 15-minute period (3 consecutive 5-minute evaluation periods):
aws cloudwatch put-metric-alarm \
--alarm-name "Redshift-DiskSpace-Critical" \
--alarm-description "Alert when Redshift disk usage exceeds 85%" \
--namespace "AWS/Redshift" \
--metric-name "PercentageDiskSpaceUsed" \
--statistic "Average" \
--period 300 \
--evaluation-periods 3 \
--threshold 85 \
--comparison-operator "GreaterThanThreshold" \
--dimensions "Name=ClusterIdentifier,Value=my-redshift-cluster" \
--alarm-actions "arn:aws:sns:us-east-1:123456789012:RedshiftAlerts" \
--treat-missing-data "breaching"
Key parameters explained:
--period 300— Evaluates the metric every 5 minutes (300 seconds).--evaluation-periods 3— Requires 3 consecutive breaching periods before triggering, preventing false alarms from transient spikes.--treat-missing-data "breaching"— If data stops arriving (possible cluster failure), the alarm triggers rather than staying green silently.
CPU Utilization Alarm (High Severity)
aws cloudwatch put-metric-alarm \
--alarm-name "Redshift-HighCPU" \
--alarm-description "CPU utilization sustained above 90% for 20 minutes" \
--namespace "AWS/Redshift" \
--metric-name "CPUUtilization" \
--statistic "Average" \
--period 300 \
--evaluation-periods 4 \
--threshold 90 \
--comparison-operator "GreaterThanThreshold" \
--dimensions "Name=ClusterIdentifier,Value=my-redshift-cluster" \
--alarm-actions "arn:aws:sns:us-east-1:123456789012:RedshiftAlerts" \
--treat-missing-data "breaching"
Health Status Alarm (Critical)
aws cloudwatch put-metric-alarm \
--alarm-name "Redshift-HealthCheck-Failed" \
--alarm-description "Cluster health status indicates impairment" \
--namespace "AWS/Redshift" \
--metric-name "HealthStatus" \
--statistic "Minimum" \
--period 60 \
--evaluation-periods 1 \
--threshold 1 \
--comparison-operator "LessThanThreshold" \
--dimensions "Name=ClusterIdentifier,Value=my-redshift-cluster" \
--alarm-actions "arn:aws:sns:us-east-1:123456789012:RedshiftAlerts" \
--treat-missing-data "breaching"
Since HealthStatus is 1 for healthy and 0 for impaired, we use LessThanThreshold with threshold 1 to catch any degradation immediately (60-second period, single evaluation).
Provisioning an SNS Topic for Alarm Notifications
# Create the SNS topic
aws sns create-topic --name "RedshiftAlerts"
# Subscribe an email endpoint
aws sns subscribe \
--topic-arn "arn:aws:sns:us-east-1:123456789012:RedshiftAlerts" \
--protocol "email" \
--notification-endpoint "dba-team@example.com"
# Subscribe a Lambda function for automated remediation
aws sns subscribe \
--topic-arn "arn:aws:sns:us-east-1:123456789012:RedshiftAlerts" \
--protocol "lambda" \
--notification-endpoint "arn:aws:lambda:us-east-1:123456789012:function:RedshiftAutoRemediator"
Building CloudWatch Dashboards
CloudWatch Dashboards provide a unified visual interface for monitoring Redshift metrics alongside related infrastructure. Dashboards are defined as JSON structures containing widgets (graphs, text, metric queries) arranged in a grid layout. You can create them via the AWS Console, CLI, or SDK.
Complete Dashboard JSON Definition
Below is a production-ready dashboard definition that covers the most critical Redshift monitoring dimensions. Save this as redshift-dashboard.json and deploy via CLI:
{
"widgets": [
{
"type": "metric",
"x": 0,
"y": 0,
"width": 8,
"height": 6,
"properties": {
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "CPU Utilization",
"metrics": [
[ "AWS/Redshift", "CPUUtilization", { "stat": "Average" } ],
[ ".", "CPUUtilization", { "stat": "p95" } ],
[ ".", "CPUUtilization", { "stat": "Maximum" } ]
],
"period": 300,
"yAxis": { "left": { "min": 0, "max": 100 } },
"annotations": {
"horizontal": [
{ "value": 80, "label": "Warning 80%", "color": "#ff9900" },
{ "value": 95, "label": "Critical 95%", "color": "#d13212" }
]
}
}
},
{
"type": "metric",
"x": 8,
"y": 0,
"width": 8,
"height": 6,
"properties": {
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Disk Space Used (%)",
"metrics": [
[ "AWS/Redshift", "PercentageDiskSpaceUsed", { "stat": "Average" } ]
],
"period": 300,
"yAxis": { "left": { "min": 0, "max": 100 } },
"annotations": {
"horizontal": [
{ "value": 70, "label": "Warning 70%", "color": "#ff9900" },
{ "value": 85, "label": "Critical 85%", "color": "#d13212" }
]
}
}
},
{
"type": "metric",
"x": 0,
"y": 6,
"width": 8,
"height": 6,
"properties": {
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Read/Write IOPS",
"metrics": [
[ "AWS/Redshift", "ReadIOPS", { "stat": "Sum", "color": "#1f77b4" } ],
[ ".", "WriteIOPS", { "stat": "Sum", "color": "#ff7f0e" } ]
],
"period": 300
}
},
{
"type": "metric",
"x": 8,
"y": 6,
"width": 8,
"height": 6,
"properties": {
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Network Throughput (Bytes/s)",
"metrics": [
[ "AWS/Redshift", "NetworkThroughput", { "stat": "Average" } ]
],
"period": 300
}
},
{
"type": "metric",
"x": 0,
"y": 12,
"width": 16,
"height": 6,
"properties": {
"view": "timeSeries",
"stacked": false,
"region": "us-east-1",
"title": "Health Status & Maintenance Mode",
"metrics": [
[ "AWS/Redshift", "HealthStatus", { "stat": "Minimum", "color": "#2ca02c" } ],
[ ".", "MaintenanceMode", { "stat": "Maximum", "color": "#d62728" } ]
],
"period": 60,
"yAxis": { "left": { "min": 0, "max": 1.5 } }
}
},
{
"type": "text",
"x": 0,
"y": 18,
"width": 16,
"height": 3,
"properties": {
"markdown": "## Redshift Cluster Monitoring Dashboard\n\n**Cluster:** my-redshift-cluster | **Region:** us-east-1 | **Last Updated:** Auto-refresh every 5 min\n\nUse this dashboard to monitor cluster health, resource utilization, and query performance trends. Cross-reference with STL table queries for granular diagnostics."
}
}
]
}
Deploying the Dashboard via CLI
aws cloudwatch put-dashboard \
--dashboard-name "Redshift-Monitoring" \
--dashboard-body file://redshift-dashboard.json
After deployment, the dashboard appears in the CloudWatch console under "Dashboards." You can also embed these dashboards in operational portals using the CloudWatch Dashboard API or share read-only access via IAM policies.
Adding Custom Metrics to the Dashboard
To surface query-level metrics (queue wait times, long-running queries) on the dashboard, publish custom metrics from a scheduled Lambda function that queries Redshift system tables:
import boto3
import psycopg2
from datetime import datetime
def publish_custom_metrics(event, context):
# Connect to Redshift
conn = psycopg2.connect(
host='my-redshift-cluster.abc123.us-east-1.redshift.amazonaws.com',
port=5439,
database='dev',
user='monitoring_user',
password='secure_password'
)
cursor = conn.cursor()
# Query for active queue wait times
cursor.execute("""
SELECT
COALESCE(MAX(DATEDIFF(seconds, queue_starttime, queue_endtime)), 0)
FROM STL_WLM_QUERY
WHERE queue_endtime >= GETDATE() - INTERVAL '5 minutes'
AND queue_starttime IS NOT NULL
""")
max_queue_wait = cursor.fetchone()[0]
# Query for long-running queries (> 300 seconds)
cursor.execute("""
SELECT COUNT(*)
FROM STV_RECRLY
WHERE DATEDIFF(seconds, query_start, GETDATE()) > 300
""")
long_running_count = cursor.fetchone()[0]
cursor.close()
conn.close()
# Publish to CloudWatch
cw = boto3.client('cloudwatch')
cw.put_metric_data(
Namespace='Redshift/Custom',
MetricData=[
{
'MetricName': 'MaxQueueWaitSeconds',
'Value': max_queue_wait,
'Unit': 'Seconds',
'Timestamp': datetime.utcnow()
},
{
'MetricName': 'LongRunningQueries',
'Value': long_running_count,
'Unit': 'Count',
'Timestamp': datetime.utcnow()
}
]
)
return {
'statusCode': 200,
'body': f'Published metrics: queue_wait={max_queue_wait}s, long_running={long_running_count}'
}
After publishing custom metrics, add them to the dashboard with metric queries targeting Redshift/Custom namespace:
# Example widget snippet for custom metrics dashboard JSON
{
"type": "metric",
"x": 0, "y": 24, "width": 8, "height": 6,
"properties": {
"view": "timeSeries",
"region": "us-east-1",
"title": "Max WLM Queue Wait (seconds)",
"metrics": [
[ "Redshift/Custom", "MaxQueueWaitSeconds", { "stat": "Maximum" } ]
],
"period": 300
}
}
Automating Monitoring with Scheduled Queries
Redshift now supports scheduled queries natively via the Redshift Data API or the console. This lets you run monitoring queries on a cron-like schedule and optionally export results to S3 or trigger notifications.
Creating a Scheduled Monitoring Query via CLI
aws redshift-data create-schedule \
--schedule-expression "cron(0/5 * * * ? *)" \
--schedule-description "Every 5 minutes: check for long-running queries" \
--database "dev" \
--sql "INSERT INTO monitoring.long_query_log
SELECT query, DATEDIFF(minutes, starttime, GETDATE())
FROM STV_RECRLY
WHERE DATEDIFF(minutes, starttime, GETDATE()) > 10;" \
--role-arn "arn:aws:iam::123456789012:role/RedshiftScheduledQueryRole" \
--schedule-name "monitor-long-queries" \
--cluster-identifier "my-redshift-cluster" \
--enabled
This schedules a query that logs any query running longer than 10 minutes into a monitoring table every 5 minutes. You can then build alarms around the row count in that table.
Integrating with Third-Party Monitoring Tools
While CloudWatch provides the native monitoring foundation, many teams augment it with specialized observability platforms. The integration pattern typically involves:
- CloudWatch Metric Streams — Stream Redshift metrics to Datadog, New Relic, or Grafana via CloudWatch Metric Streams (Kinesis Data Firehose destination).
- Lambda-based collectors — As shown above, Lambda functions query STL tables and push metrics to external services via API.
- Redshift query logging to S3 — Enable audit logging in Redshift to capture all queries to S3, then use Athena or ElasticSearch to analyze patterns.
Enabling Audit Logging for Query-Level Visibility
# Enable audit logging on the cluster
aws redshift enable-logging \
--cluster-identifier "my-redshift-cluster" \
--bucket-name "my-redshift-logs-bucket" \
--s3-key-prefix "audit-logs/" \
--log-destination-type "s3" \
--log-exports "connectionlog" "userlog" "useractivitylog"
Once enabled, all queries (including user, connection, and activity logs) are delivered to S3. You can build Athena tables over these logs for historical analysis and join them with CloudWatch metric data for complete observability.
Best Practices for Redshift Monitoring
- Layer your monitoring — Combine CloudWatch (infrastructure health), system table queries (query performance), and S3 audit logs (user activity) for full coverage. No single source tells the whole story.
- Set disk space alarms at multiple thresholds — Use 70% for warning (time to plan scaling or cleanup), 85% for critical (immediate action required). Include a 95% emergency alarm with a different notification channel.
- Monitor WLM queue depth proactively — Don't wait for user complaints. Track queue wait times as a custom metric and alert when the 90th percentile exceeds your SLA (commonly 30-60 seconds).
- Schedule vacuum and analyze operations — Monitor
SVV_TABLE_INFOfor tables with highunsortedpercentages or stale statistics. AutomateVACUUM DELETE ONLYandANALYZEduring maintenance windows. - Use
treat-missing-data: breachingon all alarms. If a cluster fails entirely, metric data stops. Without this setting, alarms stay green while your warehouse is down. - Separate alarms by severity and channel — Use SNS topics to route critical alarms (health status, disk > 85%) to PagerDuty/on-call rotations, while warning-level alerts (CPU > 70%, queue wait > 30s) go to Slack or email for daytime investigation.
- Tag all alarms with environment and owner — CloudWatch supports tags on alarms. Use them to track ownership and filter dashboards by environment (production vs. staging).
- Test alarm configurations regularly — Simulate threshold breaches (e.g., by running a heavy load) to verify that notifications arrive and the correct people are alerted.
- Document your monitoring architecture — Maintain a runbook that maps each alarm to diagnostic queries and remediation steps. When an alarm fires at 3 AM, the responder should know exactly what to query and how to mitigate.
Conclusion
Monitoring Redshift is a multi-layered discipline that spans infrastructure metrics via CloudWatch, query-level diagnostics through system tables, and user activity tracking through audit logs. By instrumenting all three layers with well-configured alarms and dashboards, you gain the visibility needed to maintain performance, control costs, and respond rapidly to issues. Start with the essential CloudWatch alarms — disk space, CPU, and health status — then progressively layer in custom metrics from system table queries as your operational maturity grows. The combination of automated alerting, rich dashboards, and scheduled diagnostic queries transforms Redshift monitoring from a reactive chore into a proactive engineering practice that keeps your data warehouse fast, reliable, and cost-efficient.