What the message means
HikariPool-1 is the default poolName. A thread called getConnection(), waited for connectionTimeout (30000 ms by default) and got no connection. HikariCP then throws java.sql.SQLTransientConnectionException.
From HikariCP 5.1.0 the message ends with the pool stats, and that is the first thing to read:
- active equals total, idle=0, waiting above 0: the pool is exhausted. Every connection is in use and requests are queued. This page is about this case.
- total=0 or active=0: the pool never got a connection, so the database is unreachable or refusing. Read the
Caused bybelow the message. A thread dump will not help here.
Common causes
The default maximumPoolSize is 10, but a pool this small is rarely the root cause. Look for who keeps connections too long:
- Slow query or a lock in the database. Each request holds its connection while it waits.
- External HTTP call inside
@Transactional. The connection stays borrowed while the thread waits for a partner API. - Open Session in View. On by default in Spring Boot, it keeps the persistence session open for the whole request, and in some setups the connection stays borrowed with it, including the time to render the response.
- Connection leak. A connection obtained and never closed.
- A second connection while holding the first. A
REQUIRES_NEWor a nested call that borrows another connection. All threads end up ingetConnectionand nobody is in the driver. - A pool that is really too small for the concurrency. Possible, but the last hypothesis, not the first.
Capture the evidence
One dump shows an instant. Take two or three, 10 seconds apart, so you can see which threads stay in the same place:
Three dumps, 10 seconds apart
for i in 1 2 3; do jcmd <pid> Thread.print -l > dump-$i.txt; sleep 10; done
jstack -l <pid> works the same way. For containers, Windows and kill -3, see how to take a thread dump.
Got the dump? Paste it and see which threads hold the connections.
Analyze my dump nowDump with sensitive data? Anonymize it first with tm-anon.
What it looks like in a dump
This is a real dump from our reproduction: JDK 25, HikariCP 6.3.3, a pool of 4 connections and 20 request threads. Sixteen threads wait for a connection, all with this stack:
Waiting for a connection
"http-nio-8080-exec-10" #39 [45876] prio=5 os_prio=0 cpu=0.00ms elapsed=5.30s tid=0x00000083ade64510 nid=45876 waiting on condition [0x00000083b00ce000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@25.0.2/Native Method) - parking to wait for <0x00000006219a0920> (a java.util.concurrent.SynchronousQueue$Transferer) at java.util.concurrent.locks.LockSupport.parkNanos(java.base@25.0.2/LockSupport.java:408) at java.util.concurrent.LinkedTransferQueue$DualNode.await(java.base@25.0.2/LinkedTransferQueue.java:452) at java.util.concurrent.LinkedTransferQueue.xfer(java.base@25.0.2/LinkedTransferQueue.java:613) at java.util.concurrent.SynchronousQueue.xfer(java.base@25.0.2/SynchronousQueue.java:235) at java.util.concurrent.SynchronousQueue.poll(java.base@25.0.2/SynchronousQueue.java:338) at com.zaxxer.hikari.util.ConcurrentBag.borrow(ConcurrentBag.java:162) at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:160) at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:142) at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:99) ...
Those threads are the victims. The culprits are the threads that are not in HikariPool.getConnection: three were running a query in the driver, and this one held a connection while it called an external service (simulated here with a sleep):
Holding a connection elsewhere
"http-nio-8080-exec-4" #33 [60220] prio=5 os_prio=0 cpu=0.00ms elapsed=5.58s tid=0x00000083ade5fec0 nid=60220 waiting on condition [0x00000083af9ce000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleepNanos0(java.base@25.0.2/Native Method) at java.lang.Thread.sleepNanos(java.base@25.0.2/Thread.java:509) at java.lang.Thread.sleep(java.base@25.0.2/Thread.java:540) at Repro$PartnerClient.chargeCard(Repro.java:9) ...
ThreadMine reads this pattern and reports it as a connection pool finding:
Connection pool exhausted: 16 threads waiting for a connection from HikariCP
16 threads
Every connection in the pool is in use. Look at the threads holding them, not at the ones waiting: running a query, or stuck somewhere else with the connection open.
To do it by hand, count the threads in getConnection, then read the stacks of everyone else.
How to fix it
Fix the cause the dump pointed to. Raising the pool size comes last.
A slow query or a lock
Fix the query or the lock. Add a statement timeout so one bad query cannot hold a connection forever: @Transactional(timeout = 5) in Spring, or statement_timeout in PostgreSQL.
An external call inside a transaction
Move the call out of the @Transactional method, so the connection is only borrowed for the database work.
Open Session in View
Set spring.jpa.open-in-view=false and load what the view needs inside the service.
A leak
Set spring.datasource.hikari.leak-detection-threshold (for example 20000, in ms). HikariCP logs the stack of the code that borrowed a connection and did not return it in time. Then close it with try-with-resources.
Slow failure
spring.datasource.hikari.connection-timeout decides how long a request waits. Shortening it makes the failure faster, and does not free anything.
Raise the pool size, last
spring.datasource.hikari.maximum-pool-size helps when the connections are held for a normal time and the concurrency really is higher. Check the database limit before raising it.
More about reading threads in a stuck application: Spring Boot stuck threads.
Frequently asked questions
What does "HikariPool-1 - Connection is not available" mean?
A thread called getConnection() and the pool had no free connection for the whole connectionTimeout, 30000 ms by default. HikariPool-1 is the pool name. The exception is java.sql.SQLTransientConnectionException. The numbers in parentheses (total, active, idle, waiting) tell you whether the pool is full or the database is unreachable.
Should I increase maximumPoolSize?
Not first. The default is 10. If the connections are held by a slow query, a leak or an external call inside a transaction, a bigger pool only moves the limit and puts more load on the database. Find who holds the connections with a thread dump, fix that, and raise the size last.
What is the default timeout?
connectionTimeout defaults to 30000 ms, which is why the message says "after 30000ms". In Spring Boot the property is spring.datasource.hikari.connection-timeout. A shorter value makes requests fail faster but does not free the connections.
How do I find who is holding the connections?
Take a thread dump and look at the threads that are not in HikariPool.getConnection. The ones in a JDBC driver call are running a query. The ones elsewhere, for example waiting on an HTTP call, may be holding a connection they already borrowed. To catch a leak, set leak-detection-threshold, and HikariCP logs the stack of the code that borrowed a connection and did not return it in time.
Is the problem the database?
Only sometimes. If the stats show total=0 or active=0, the pool cannot reach the database: read the Caused by of the exception, because a dump will not help. If active equals total, idle=0 and waiting is above zero, the pool is exhausted, and the cause is usually in the application or in a slow query.
Got the dump from the stuck pool?
Paste it and see which threads hold the connections. No signup for the first dump.