Table of Contents [expand]
Last updated May 12, 2026
Automated monitoring for your Heroku Postgres database can provide insight into the performance of your app and database. Use monitoring tools to spot problems in advance, respond to incidents quickly, and identify the root cause of issues. This article describes how to set up monitoring for your database, including which tools to use and what metrics to look for. The alerts and thresholds in this article are applicable to most apps, but aren’t universal.
Heroku Enterprise customers with Premier or Signature Success Plans can request in-depth guidance on this topic from the Customer Solutions Architecture (CSA) team. Learn more about Expert Coaching Sessions here or contact your Salesforce account executive.
Set Up Metrics Monitoring with a Platform Monitoring Tool
Heroku Postgres provides database and server metrics that give information on the status of your instance. Understanding and monitoring these metrics ensure the health of your database as your applications run and scale.
The most effective way to track database metrics is to install a platform monitoring add-on. Find a full list of monitoring add-ons on the Heroku Elements Marketplace.
Platform monitoring add-ons also provide insights on your apps and dynos. For details, see Monitoring Your App on Heroku.
For a full list of provided metrics, see Heroku Postgres Metrics Logs. Heroku recommends closely monitoring the metrics in this article, and using them to set up meaningful alerts on database health:
Database Size
The db_size metric is the size of the database, including all table and index data, and database bloat. The related db-max-size and db-size-percentage-used metrics provide more context on your database plan’s maximum data size allowed and your current usage.
If your Postgres database grows past the size allotted for your plan, you receive a warning email with directions on how to fix the issue. In some cases, we set an enforcement date when you’re allowed only a single database connection. We restrict access to READ, DELETE , and TRUNCATE privileges until the database is back under the plan limit.
Set alerts based on your plan’s storage limit to get advanced notice if you start approaching it. Set a warning alert when your database gets to 80% of the allotted size for your plan. Set a critical alert when it gets to 90% of the allotted size.
| Metric | Suggested Warning Alert Threshold | Suggested Critical Alert Threshold |
|---|---|---|
db-size-percentage-used |
0.80 | 0.90 |
If you get close to maximum size, either upgrade your plan or delete data to stay within plan limits. The Heroku pg-extras CLI plugin commands heroku pg:total-table-size, heroku pg:table-size and heroku pg:index-size help investigate database utilization.
Active Database Connections
The active-connections metric lists the number of established connections to your database. The related metrics max-connections and connections-percentage-used provide more context on your database’s connection limit and the current usage.
Heroku Postgres enforces a connection limit to optimize Postgres memory usage and scaling. This connection limit varies depending on the Heroku Postgres plan.
When your database connections reach the connection limit, you can’t create new connections to the database. In these situations, new connection attempts from your apps and clients fail with a “too many connections” PostgreSQL error.
There are two strategies for setting up alerts based on database connection counts:
- Set up an alert for sudden, large changes to the current connection count. Significant changes from baseline connection numbers can be a sign of increased query, transaction run times, or both. Alerting thresholds depend on your app’s connection count range, assessed under normal operating conditions. Consider +50/+100 over your normal daily maximum.
- Set up an alert for when the connection count approaches its limit, based on
connections-percentage-used.
Set a warning alert when your connection usage gets to 80% of the allowed connection limit. Set a critical alert when it gets to 90% of the allowed limit.
| Metric | Suggested Warning Alert Threshold | Suggested Critical Alert Threshold |
|---|---|---|
connections-percentage-used |
0.80 | 0.90 |
If you’re routinely approaching your connection limit, consider using connection pooling. See PgBouncer Configuration for best practices with connection pooling.
Waiting Connections
The waiting-connections metric shows how many connections are waiting on database locks.
You can expect occasional lock waits, but sustained lock waits can be a sign of mishandled database concurrency or a long-running database process conflicting with your normal database operations.
Set up an alert for when there are any connections waiting for five consecutive minutes.
The commands heroku pg:locks and heroku pg:blocking help identify queries that are preventing other operations from taking place.
You can terminate the blocking queries to resolve lock contention. Also, knowing what statements cause blocks can help to identify app code that can be optimized to reduce locks.
Database Load
The load-avg-* metrics shows average CPU load over the last 1 minute, 5 minute, and 15 minute periods. Heroku’s reported load metrics are normalized by dividing the system load by the number of CPUs of your database plan.
A load average over 1.0 indicates that processes waited for CPU or disk I/O resources during the given window. Higher values indicate more time spent by processes waiting and higher resource saturation. Values under 1.0 indicate that CPUs spent time idle during the given window. High load can result in inconsistent query execution times and longer wait times.
Set up alerts to identify resource saturation on your database server based on the different load average values.
| Metric | Suggested Warning Alert Threshold | Suggested Critical Alert Threshold |
|---|---|---|
load-avg-1m |
1.2 | 1.5 |
load-avg-5m |
0.9 | 1.0 |
load-avg-15m |
0.80 | 0.90 |
Adjust the suggested warning and critical alert threshold based on your database activity trends and performance expectations for your use case.
Observe your current database activity with the heroku pg:ps command for CPU-intensive queries. Also, monitor the IOPS metrics for your database. Reaching your database plan’s IOPS limits causes processes to wait on I/O, which increases system load. If you’re consistently seeing high values for load-avg-*, consider upgrading to a larger Heroku Postgres plan. Before upgrading or if you’re already on the largest plan, identify and optimize expensive queries to reduce the amount of processing work done on the database server. Also, monitor its read and write activity to identify I/O optimizations.
Read and Write IOPS
The read-iops and write-iops metrics track how many read and write I/O requests are made to the main database disk in values of IOPS (I/O operations per second). Each Heroku Postgres plan has a provided Provisioned IOPS (PIOPS) max, which is the maximum total reads and writes per second that the provisioned disk volume can sustain. The related metrics max-iops and iops-percentage-used provide more context on the database’s provisioned IOPS and its current usage.
Ideally, you want your database’s reads to come from memory (cache) rather than disk, as disk reads are slower than reading from memory. If the database exceeds the provisioned IOPS limit, processes must wait on I/O resources before they can progress, leading to degraded database performance. Database processes waiting for disk I/O contribute to higher load-avg values.
Set up an alert when iops-percentage-used reaches 90% of your Provisioned IOPS (PIOPS) to help identify activities or statements that require significant I/O so you can address them.
| Metric | Suggested Warning Alert Threshold | Suggested Critical Alert Threshold |
|---|---|---|
iops-percentage-used |
0.90 | 1.00 |
If your metrics consistently report high values for read-iops or write-iops, resulting in iops-percentage-used getting close or reaching 100% (1.00), consider upgrading to a larger Heroku Postgres plan. Before doing that, or if you’re already on the largest plan, identify and optimize expensive queries to reduce the amount of data being read directly from disk. A larger plan with higher RAM specs can help reduce disk reads in favor of a larger volume of cached data in Postgres’ Shared Buffers and the OS cache. If read activity causes the I/O workload pressure for your database, consider offloading some of the read throughput to a follower database.
WAL Disk Utilization
The wal-percentage-used metric tracks the percentage of disk space used to store Postgres write-ahead logs (WAL) temporarily. Heroku Postgres uses Postgres WAL as a part of Continuous Protection. Any database change is written to the write-ahead logs before it’s persisted in the database data files. Heroku Continuous Protection constantly archives the WAL segments that databases generate to an external storage. Postgres rotates archived WAL segments that are no longer required, deleting them from the database’s disk. WAL segments can accumulate on your database server if the database’s write activity increases faster than WAL archiving occurs, or if replication delays or pauses from Streaming Data Connectors force Postgres to hold WAL segments.
If the rate of WAL generation exceeds the rate of WAL archival, there’s a risk of completely filling up the WAL volume on your database server. This shuts down the database and can result in data loss or data corruption.
Heroku automatically begins throttling database connection limits when the WAL volume reaches 75% utilization, eventually terminating all connections when it reaches 95% utilization.
Set up an alert for when wal-percentage-used reaches 60% to notify before your database reaches the throttling threshold.
| Metric | Suggested Warning Alert Threshold | Suggested Critical Alert Threshold |
|---|---|---|
wal-percentage-used |
0.60 | 0.75 |
See Postgres Write-Ahead Log Usage for details and remediation strategies.
Install Logging Tool
To supplement the database system metrics, Heroku Postgres logs messages to your app’s log stream. Heroku doesn’t store logs for a long time, so you need an external tool to retain log history. Set up a logging tool by installing a logging add-on.
During an incident, logs can help investigate issues and identify long-running queries. After an incident, you can use logs for root cause analysis.
The Logging category includes several logging tools, with different features and retention periods.
To isolate events from Heroku Postgres logs, filter for the postgres process. For examples and more information, refer to the article Understanding Heroku Postgres Log Statements and Common Errors. It’s important to be familiar with Postgres logs to understand what errors or warnings are logged routinely and what messages are abnormal for your app. Logs are an invaluable tool for finding long running queries or locks.
If you use an external logging tool, you can set up a log drain to ingest your Heroku Postgres metrics data into that tool. If you use Heroku Shield, you can use Private Space Logging to drain all logs from a Space to an external tool.
For more logging use cases and setup tips, see Monitoring Your App on Heroku.
Install pg-extras
Postgres automatically collects statistical information on queries and tables that you can use to analyze performance issues. The Heroku pg-extras CLI plugin expands the commands available on the main Heroku CLI and provides shortcuts for interpreting those statistics.
Routinely reviewing database statistics helps identify potential issues before they become problems.
Find the pg-extras CLI plugin, setup instructions, and command reference on its GitHub repository.
Routinely review opportunities for improvement, such as unused indexes, large tables and indexes, vacuum statistics, bloat statistics, and outlier queries.
Also, the pg:diagnose command, included in the Heroku CLI, runs multiple checks and generates a report showing potential issues based on real-time activity and gathered statistics.
Application Monitoring
Database monitoring is just one part of overall app monitoring. See guidance for Monitoring Your App on Heroku.