Table of Contents [expand]
- LOG: duration: 3.565 s …
- LOG: checkpoint starting…
- LOG: could not receive data from client: Connection reset by peer
- LOG: unexpected EOF on client connection
- LOG: [Errno 104] Connection reset by peer
- FATAL: too many connections for role
- FATAL: could not receive data …
- FATAL: role “role-name” is not permitted to log in
- FATAL: terminating connection due to administrator command
- FATAL: remaining connection slots are reserved for non-replication superuser connections
- FATAL: no pg_hba.conf entry for host “…”, user “u…”, database “d…”, SSL off
- LOG: temporary file: path “file path”, size “file size”
- ERROR: permission denied for relation
- ERROR: operator does not exist
- ERROR: relation “table-name” does not exist
- ERROR: column “column-name” cannot…
- ERROR: SSL SYSCALL error: EOF detected
- ERROR: prepared statement “a30” already exists
- ERROR: could not write block … of temporary file: No space left of device
- Out of Memory Errors
Last updated July 06, 2026
Heroku Postgres publishes database logs in your app’s log stream. You can isolate Heroku Postgres events with the heroku logs command by filtering for the postgres process.
Logs are available on Standard-tier and higher databases. Essential-tier databases don’t include logs.
$ heroku logs -p postgres -t -a example-app
2026-06-29T13:34:12.000000+00:00 app[postgres]: [15521-1] [CHARCOAL] LOG: checkpoint starting: time
2026-06-29T13:34:12.000000+00:00 app[postgres]: [15522-1] [CHARCOAL] LOG: checkpoint complete: wrote 6 buffers (0.0%); 0 transaction log file(s) added, 0 rem...
Besides seeing system-level Postgres activity, these logs are also useful for understanding your app’s use of Postgres and for diagnosing common errors. This article lists common log statements, their purpose, and actions to take.
Find the Heroku Postgres Metrics Logs for your database by filtering for the heroku-postgres process. These metrics logs are independent of standard logs emitted by Postgres, which uses the postgres process.
LOG: duration: 3.565 s …
[12-1] u8akd9ajka [BRONZE] LOG: duration: 3.847 s statement: SELECT "articles".* FROM "articles"...
By default, Heroku Postgres logs any query execution that takes more than 2 seconds to run, defined by the log-min-duration-statement setting.
Heroku logs queries taking longer than log-min-duration-statement so you can identify and optimize them.
See Solutions to Expensive Queries for recommendations on analyzing and fixing expensive queries.
LOG: checkpoint starting…
2026-06-29T13:35:16.000000+00:00 app[postgres]: [15521-1] [CHARCOAL] LOG: checkpoint starting: time
2026-06-29T13:35:16.000000+00:00 app[postgres]: [15522-1] [CHARCOAL] LOG: checkpoint complete: wrote 6 buffers (0.0%); 0 transaction log file(s) added, 0 rem...
LOG: checkpoint starting and the corresponding LOG: checkpoint complete statements are part of Postgres’ checkpointing activity. A checkpoint flushes dirty pages from Postgres’ shared memory buffers to disk to allow recycling older WAL segments. Postgres triggers checkpoints automatically based on time or WAL volume.
These statements are part of normal database operation and no action is required.
LOG: could not receive data from client: Connection reset by peer
See unexpected EOF on client connection for more information.
LOG: unexpected EOF on client connection
app[postgres]: LOG: could not receive data from client: Connection reset by peer
app[postgres]: LOG: unexpected EOF on client connection
Although Postgres emits this log, the cause for the error is unrelated to the database. Your app happened to crash while connected to Postgres, and didn’t clean up its connection to the database. Postgres noticed that the client, your app, disappeared without ending the connection properly, and logged a message saying so.
If you aren’t seeing your app’s backtrace, make sure you’re logging to stdout instead of a file and that you have stdout synced.
LOG: [Errno 104] Connection reset by peer
This error indicates a transient network interruption between your app or Postgres client and Postgres. If the error appears frequently or in sustained bursts, investigate the connectivity between your dynos and the database, checking for connection leaks in your app, or reviewing recent infrastructure changes.
FATAL: too many connections for role
FATAL: too many connections for role "[role name]"
This error occurs on Essential-tier databases plans, which have a max connection limit of 20 per user. To resolve this error, close some connections to your database by stopping background workers, reducing the number of dynos, or restarting your app in case it has created connection leaks over time. See Concurrency and Database Connections for Rails-specific guidance.
FATAL: could not receive data …
FATAL: could not receive data from WAL stream: SSL error: sslv3 alert unexpected message
A transient network error or a TLS handshake failure interrupts replication from a primary database to a follower. This error is a transient problem and Postgres automatically re-establishes the replication stream.
Find replication lag for a follower with heroku pg:info. The “Behind By” field shows the replication lag in commits.
$ heroku pg:info --app example-app
=== HEROKU_POSTGRESQL_WHITE
...
Following DATABASE_URL
Behind By 125 commits
You can also monitor follower lag via the database metrics of the Heroku Postgres Metrics Logs.
FATAL: role “role-name” is not permitted to log in
FATAL: role "u8akd9ajka" is not permitted to log in (PG::Error)
This error occurs when you’re trying to connect to a database with credentials that no longer exist, which can happen for several reasons, including:
- The database credentials rotated but you’re still using the old ones to connect to it. In the specific case of Essential-tier databases, credentials rotate as part of regular maintenance tasks.
- You deprovisioned an Essential-tier database but you’re still trying to connect to it.
FATAL: terminating connection due to administrator command
FATAL: terminating connection due to administrator command
This message indicates Postgres terminated a backend connection. This error can happen when you run the heroku pg:killall or heroku pg:kill --force CLI commands, or when you run SELECT pg_terminate_backend(pid); to terminate a database connection.
FATAL: remaining connection slots are reserved for non-replication superuser connections
FATAL: remaining connection slots are reserved for non-replication superuser connections
Each database plan has a maximum allowed number of connections available, which varies by plan. This message indicates your database has reached its connection limit and has reserved the remaining connections for superuser access (restricted to Heroku Postgres automation). See Heroku Postgres Production Tier Technical Characterization for details on connection limits for a given plan.
If the high number of connections to your database is unexpected:
- Consider restarting your dynos to clear potentially leaked connections that accumulated over time, or terminate them with
heroku pg:kill. - Inspect your database locks to identify connections blocked due to lock contention and investigate or terminate the connections holding locks.
If your database hits its connection limit often, use a connection pooler such as PgBouncer to reduce the number of connections to your database, or upgrade to a higher-tier plan if your workload requires more concurrent connections.
FATAL: no pg_hba.conf entry for host “…”, user “u…”, database “d…”, SSL off
This “SSL off” error indicates that you’re attempting to establish a database connection without SSL. Heroku Postgres requires SSL connections. Check the documentation for your Postgres driver on how to establish encrypted connections.
LOG: temporary file: path “file path”, size “file size”
temporary file: path "base/pgsql_tmp/pgsql_tmp23058.672", size 1073741824
Heroku Postgres logs temporary files larger than 10,240 kilobytes. Postgres creates temporary files for large sort and hash operations that exceed work_mem.
This log entry is informational. Frequent temporary files indicate queries exceeding work_mem and can impact performance. Consider optimizing the query or increasing the work_mem setting.
ERROR: permission denied for relation
PGError: ERROR: permission denied for relation table-name
On Heroku Postgres Essential-tier databases, Heroku enforces row limits by revoking write privileges when it exceeds the limit. If you hit this error on an Essential database, check where you’re over your row limit. Upgrade to a Standard-tier or higher database to remove this constraint or reduce the number of total rows on your database.
On other Heroku Postgres tiers, check the role’s permissions on the affected table.
ERROR: operator does not exist
PGError: ERROR: operator does not exist: character varying = integer
Postgres raises an error when an operator doesn’t support the operand types. For example, comparing a character varying column to an integer requires casting one side to a compatible type.
Make sure the operator is adequate for the data type or use an explicit cast to resolve the mismatch.
ERROR: relation “table-name” does not exist
PGError: ERROR: relation "documents" does not exist
This error is the standard message shown by Postgres when a relation, such as a table or a view, doesn’t exist. This error means the query references an object that doesn’t exist in the current database or search path.
Check that your migrations ran successfully and that the relation name and search path are correct.
ERROR: column “column-name” cannot…
PGError: ERROR: column "verified_at" cannot be cast to type "date"
This error occurs when you change the type of a column and Postgres can’t automatically convert the existing row values to the new type.
Inspect the data in the affected column to identify values that Postgres can’t convert. Then either clean the data or provide an explicit USING expression in your ALTER TABLE statement to indicate Postgres how to perform the conversion.
ERROR: SSL SYSCALL error: EOF detected
Errors with similar root causes include:
no connection to the serverSSL error: decryption failed or bad record maccould not receive data from server: Connection timed out
These errors indicate the connection between your app or client and Postgres was interrupted or corrupted. The two most common causes are:
- Shared Postgres connections across processes or threads: if forked processes or threads share a Postgres connection without re-establishing the connection, concurrent use corrupts the connection state. This behavior happens typically with Resque workers or Unicorn. Re-establish the connection after forking or initializing a thread to resolve this issue.
- Abrupt client or app disconnections: if your app crashes or a transient network interruption drops the connection, the next query attempt fails because the connection no longer exists. Heroku restarts the crashed dyno, which re-establishes the connection on the next request.
ERROR: prepared statement “a30” already exists
Postgres scopes prepared statements to a single connection. When a connection is shared across processes or threads, one process can attempt to create a prepared statement with a name that another already registered on the same connection.
The root cause is typically a Postgres connection shared improperly between forked processes or threads. Re-establishing the connection after forking resolves this problem.
ERROR: could not write block … of temporary file: No space left of device
This error indicates that Postgres ran out of disk space while writing a temporary file. Postgres cleans up temporary files automatically when the query ends, and temporary tables at the end of the database session.
If this error is recurrent, review queries that generate large temporary files and consider optimizing them to reduce their disk usage.
Out of Memory Errors
Out of memory (OOM) errors occur when the server running your database can’t allocate enough memory for connections, query execution, or its buffer. Several factors can contribute to memory exhaustion, such as expensive queries or a high number of concurrent connections. Review your database usage and upgrade your plan if your database workload requires more memory resources.
See Understanding Heroku Postgres Out of Memory Errors for more details.
Extremely Complex Querying
Sort and hash operations each allocate up towork_mem. A single complex query can allocate multiples of work_mem if it contains several sorts of hash nodes. Sort operations arise from ORDER BY, DISTINCT, and merge joins. Hash operations arise from hash joins, hash aggregations, and IN subqueries. A single complex query can trigger several of these operations simultaneously. This memory pressure multiplies with concurrent connections that run memory-intensive operations.
Ruby, ActiveRecord, and Prepared Statements
Prepared statements allow Postgres to parse a query once and reuse it efficiently. However, many ORMs don’t construct prepared statements effectively and create a separate prepared statement for each distinct parameter in a query. For example, let’s say our app allows its users to select products from a product table by ID. If customer A selects two products, ActiveRecord defines a query and creates a prepared statement:
SELECT * FROM products WHERE id IN ($1, $2);
If customer B, in the same app, for the same query, selects four products instead of two, ActiveRecord creates a new prepared statement:
SELECT * FROM products WHERE id IN ($1, $2, $3, $4);
Because these are distinct queries, the prepared statement cache grows depending on the variability in the IN clause, consuming significant memory over time. Consider disabling prepared statements or adjusting the number of prepared statements that your app caches.
Disabling Prepared Statements in Rails
To disable prepared statements, update your config/database.yml file to include the prepared_statements parameter:
production:
adapter: postgresql
prepared_statements: false
To adjust the size of the prepared statement cache, update your config/database.yml file to include the statement_limit parameter (defaults to 1000).
production:
adapter: postgresql
statement_limit: 200
Too Many Connections
Each Postgres connection allocates memory for its backend process regardless of whether it’s actively executing a query. Many idle connections can exhaust the available RAM before hitting the connection limit. Use a connection pooler such as PgBouncer to reuse and reduce the number of Postgres connections to the database.
Database Plan is Too Small
If query and connection optimizations don’t resolve the OOM errors, it’s possible your database plan doesn’t have enough memory for your workload. Consider upgrading to a higher plan.