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

PostgreSQL Connection Pool Saturation and Deadlock Sentinel

Automated database reliability workflow to monitor PostgreSQL connection pool limits, idle transactions, deadlocks, and alert Slack.

Categories
BusinessData

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

In PostgreSQL production environments, connection pool exhaustion and lingering idle-in-transaction states represent catastrophic failure vectors. When application workloads leak connections or experience sudden traffic spikes, active sessions quickly consume the server's max_connections allocation. Once saturated, PostgreSQL rejects incoming requests with FATAL: remaining connection slots are reserved for non-replication superuser connections, abruptly taking dependent services offline.

Furthermore, connections left in idle in transaction state prevent the autovacuum daemon from cleaning dead row versions (tuples). This results in severe table bloat, disk exhaustion, and degraded query cache hit ratios.

This blueprint establishes a continuous reliability watchdog for PostgreSQL. Executing on a 5-minute schedule or on-demand, it inspects pg_stat_activity and pg_stat_database to evaluate pool utilization percentages, flags aged idle transactions, records cumulative deadlocks, and delivers actionable Slack alerts before connection starvation causes production outages.

How it works

  1. Scheduled Health Check: The scheduled_health_check trigger (io.kestra.plugin.core.trigger.Schedule) executes every 5 minutes or on-demand via the Kestra UI.
  2. Activity & Pool Audit: The audit_postgres_health task (io.kestra.plugin.jdbc.postgres.Query) queries pg_stat_activity and pg_settings using Common Table Expressions (CTEs) to calculate connection utilization percentage against max_connections and identify transactions left idle for longer than max_idle_transaction_age_seconds.
  3. Threshold Gate: The evaluate_health_thresholds flowable task (io.kestra.plugin.core.flow.If) evaluates whether the computed health_status is non-healthy (CONNECTION_POOL_SATURATION or IDLE_IN_TRANSACTION_STARVATION).
  4. Slack Alert Notification: If thresholds are breached, notify_dba_slack (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) dispatches a diagnostic card detailing connection counts, aged idle transaction duration, and remediation commands.
  5. Nominal Logging: If all metrics remain healthy, log_healthy_status records current pool capacity in execution logs.
  6. Audit Manifest: The export_audit_manifest task records telemetry metrics for reliability reporting and observability platforms.

What you get

  • Early warning before PostgreSQL reaches max_connections and rejects application queries.
  • Detection of aged idle in transaction sessions that cause table bloat and block autovacuum.
  • Visibility into cumulative database deadlock counts.
  • Zero human overhead for continuous PostgreSQL connection health surveillance.

Who it is for

  • Site Reliability Engineers (SREs) and Database Administrators managing production PostgreSQL clusters.
  • Backend engineers diagnosing connection leaks, pool starvation, or transaction timeout spikes.
  • Platform teams managing connection poolers such as PgBouncer or Pgpool-II.

Why orchestrate this with Kestra

Monitoring PostgreSQL connection pool health usually requires complex external metric agents or custom cron daemons. Kestra provides declarative, serverless orchestration: it handles secure JDBC connectivity, schedules regular health checks, branches conditionally based on utilization thresholds, and alerts the engineering team directly in Slack.

Inputs

Name Type Default Description
postgres_url STRING jdbc:postgresql://localhost:5432/postgres JDBC connection string targeting the target PostgreSQL database.
max_connection_utilization_percent FLOAT 80.0 Threshold percentage of max_connections beyond which an alert is triggered.
max_idle_transaction_age_seconds INT 120 Duration in seconds an idle transaction can remain open before triggering an alert.
slack_channel STRING #dba-alerts Slack channel destination for database performance alerts.

Expected outputs

  • {{ outputs.audit_postgres_health.rows[0].connection_utilization_percent }}: Current percentage of allowed connections in use.
  • {{ outputs.audit_postgres_health.rows[0].idle_in_transaction_connections }}: Count of active sessions currently holding an uncommitted transaction in idle state.
  • {{ outputs.audit_postgres_health.rows[0].aged_idle_in_transaction_connections }}: Count of idle transactions older than the configured threshold.
  • {{ outputs.audit_postgres_health.rows[0].health_status }}: Computed operational status (HEALTHY, CONNECTION_POOL_SATURATION, or IDLE_IN_TRANSACTION_STARVATION).
  • {{ outputs.export_audit_manifest.value }}: Structured JSON telemetry manifest recording execution timestamp and pool metrics.

Prerequisites

  • A PostgreSQL database instance (version 12, 13, 14, 15, or 16).
  • A database user with pg_read_all_stats role or superuser privileges to inspect all client connections in pg_stat_activity.
  • A Slack Incoming Webhook URL targeting your database alert channel.

Secrets

  • POSTGRES_USERNAME: Database username authorized to inspect server activity views.
  • POSTGRES_PASSWORD: Password for the PostgreSQL monitoring user.
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint URL used for sending alert notifications.

Quick start

  1. Configure POSTGRES_USERNAME, POSTGRES_PASSWORD, and SLACK_WEBHOOK_URL in your Kestra namespace secrets.
  2. Import this flow YAML into your Kestra instance.
  3. Click Execute in the UI to run an initial connection audit.
  4. Review execution outputs to check connection pool utilization and active transaction states.

Common pitfalls and troubleshooting

  • Permissions on pg_stat_activity: In PostgreSQL 10+, non-superuser accounts can only view queries executed by their own role unless granted the pg_read_all_stats predefined role. Grant GRANT pg_read_all_stats TO <monitoring_user>; for full visibility.
  • Pooled Connection Behavior: If utilizing an external transaction pooler like PgBouncer in transaction pooling mode, server connections may rapidly fluctuate. Adjust max_idle_transaction_age_seconds to reflect your workload characteristics.
  • Deadlock Metric Reset: The deadlocks column in pg_stat_database is cumulative since the last stats reset. Track the change over time rather than absolute historical counts.

How to extend

  • Add io.kestra.plugin.notifications.pagerduty.PagerDutyAlert inside the then: block for critical saturation escalations.
  • Automate termination of idle sessions older than 600 seconds by adding an auxiliary task executing SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE ....
  • Monitor replication slot lag by joining pg_replication_slots into the diagnostic query.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.