Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Start with PostgreSQL’s server log, not the Spring exception message. A detected deadlock report identifies the participating database processes and SQL statements; use those details to trace the requests, transaction boundaries, and code paths that issued them. If the app is stuck but PostgreSQL has no deadlock evidence, investigate connection-pool exhaustion as a separate failure mode.

1. Capture the complete PostgreSQL deadlock report

Ask for the PostgreSQL server-log entry covering the incident—not just the exception text surfaced by the application. Preserve the full deadlock details, including process identifiers, timestamps, statements, and surrounding context. The server log is the durable record after PostgreSQL detects and resolves a deadlock; a live view may no longer show the cycle.

Include database-side identity in log lines where deployment policy allows. PostgreSQL’s logging configuration supports a log_line_prefix containing fields such as %m (timestamp), %p (process ID), %a (application name), %u (user), %d (database), and %e (SQLSTATE). These help align a database event with application logs. Check which settings and fields your PostgreSQL version and managed-service provider permit.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Enable evidence for lock waits that recur

For an issue you expect to reproduce, PostgreSQL can log lock waits that last longer than deadlock_timeout. The log_lock_waits setting is off by default. deadlock_timeout controls how long PostgreSQL waits before checking whether a lock wait is part of a deadlock, and also sets the threshold for those wait messages. PostgreSQL 18 documents a one-second default and notes that it is probably about the smallest practical value. See the logging settings and lock-management settings.

A shorter threshold can make lock-wait messages appear sooner during a targeted investigation, but consider permissions, server configuration, and the resulting log volume before changing it. This is a diagnostic threshold, not a remedy for conflicting lock order or underlying contention.

3. Inspect database sessions while the issue is active

When the incident is happening, inspect outstanding locks and connect them to session activity. PostgreSQL’s pg_locks view can be joined to pg_stat_activity using the backend process ID. Compare granted and ungranted lock rows, then inspect each session’s SQL and application identity.

SELECT a.pid, a.application_name, a.usename, a.datname, a.state,
       a.wait_event_type, a.wait_event, a.query,
       l.locktype, l.mode, l.granted,
       l.relation, l.transactionid
FROM pg_locks AS l
JOIN pg_stat_activity AS a ON a.pid = l.pid
ORDER BY a.pid, l.granted, l.locktype;

This query is a live snapshot, not a replacement for the server log’s record of a deadlock already detected. The PostgreSQL 16 pg_locks documentation also cautions that resolving relation OIDs through pg_class is meaningful only in the relevant database context. Verify view columns and permissions for the deployed PostgreSQL major version.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Trace the backend and SQL to Spring code

Use the database timestamp, process ID, application name, and statement to locate the corresponding request or job in application logs. Then inspect the method that issued each statement and the actual transaction boundary around it. Request or job IDs and transaction timing in application logs make this correlation more reliable.

Spring’s declarative transactions are implemented through AOP proxies. A call path that bypasses the expected proxy may therefore fail to establish the transaction boundary the code appears to imply. Imperative transactions are also thread-bound; they do not automatically flow into threads started inside a transactional method. Review asynchronous work and internal method calls against Spring’s explanation of the declarative transaction implementation.

5. Distinguish a database deadlock from pool exhaustion

A connection-pool stall can make requests appear stuck without proving that PostgreSQL detected a lock cycle. Use the evidence to separate the two hypotheses:

Evidence PostgreSQL lock deadlock Spring connection-pool exhaustion
Primary evidence PostgreSQL deadlock report with participating processes and lock details Pool acquisition delays or timeouts, plus connections retained by transactions
Database view Lock-wait or cycle evidence in server logs, or lock state observed while active Sessions may hold connections without a matching PostgreSQL deadlock report
Spring clue Transactions acquire conflicting resources in different sequences PROPAGATION_REQUIRES_NEW or another nested path needs a connection while an outer transaction retains one
First investigation Preserve the report, identify SQL and backend processes, then trace the call paths Inspect pool metrics, transaction duration, and each thread’s connection demand

Spring documents a specific pool-exhaustion risk with PROPAGATION_REQUIRES_NEW: an inner scope uses an independent physical transaction while the outer transaction’s resources remain bound. If multiple threads hold outer connections and wait for inner connections, an undersized pool can run out of connections. Check pool acquisition timing and active/idle counts alongside PostgreSQL sessions; treat this as a pool-resource issue unless database evidence establishes a lock cycle. See Spring’s transaction propagation documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

6. Verify exception translation and rollback behavior

Do not infer the underlying database event from the Java exception type alone. Spring’s JdbcTransactionManager translates database locking failures during commit or rollback into DataAccessException subclasses; DataSourceTransactionManager behaves differently. Check the transaction manager actually configured in the application and its JDBC/JPA stack. Spring documents connection handling and this distinction in Controlling Database Connections.

Also inspect the rollback rules on the relevant @Transactional boundary. By default, Spring rolls back for unchecked exceptions and Error, but not checked exceptions; explicit rollback rules can change that behavior. A rollback rule affects transaction outcome, but does not by itself establish whether PostgreSQL detected a deadlock. See Spring’s guide to rolling back a declarative transaction.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.