You do NOT need to do anything special in your Panache code.
No. You do NOT need to do anything special in your Panache code.
Once you:
configure the reactive datasource + pool in
application.propertiesuse Hibernate Reactive Panache (
Uni,Multi)avoid blocking calls
👉 Panache automatically reuses connections from the pool for every DB operation.
You do NOT open a connection per REST request.
You do NOT manage sessions manually.
You do NOT need any extra code.
🔍 Now the Important Part: Why This Is True
Let’s walk this slowly and mechanically, so there’s zero doubt.
1️⃣ What Actually Happens on Every REST Request
When a REST request comes in:
HTTP Request
↓
Quarkus REST layer
↓
Your resource method
↓
Panache repository method
↓
Hibernate Reactive
↓
Reactive PG client pool
↓
CockroachDB
🔴 What does NOT happen
❌ A new DB connection is not created
❌ A TCP connection is not opened
❌ You do not block a thread
2️⃣ Where the Pool Actually Lives
The pool is created once at application startup.
From your config:
quarkus.datasource.ns1.reactive.max-size=5
This creates:
A Vert.x reactive connection pool
Managed by Quarkus
Owned by the named datasource
Shared safely across all requests for that nanoservice
The pool lives longer than any request.
3️⃣ What Panache Does Internally (Critical Insight)
When you call:
Product.findAll().list();
or
repository.findById(id);
Panache does this internally:
Borrow a connection from the pool (non-blocking)
Execute the SQL asynchronously
Return the connection to the pool
Resume your
Uniwhen the result arrives
💡 If all connections are busy:
The query waits asynchronously
No threads are blocked
No connection storm happens
4️⃣ Is a Session Created Per Request?
Yes — but this is not a DB connection.
Important distinction:
| Thing | Lifetime | Cost |
| Hibernate Reactive Session | Per operation | Lightweight |
| DB Connection | Pooled | Expensive |
A session is:
Just a logical context
Bound to the reactive chain
Automatically closed
So this is safe and expected.
5️⃣ What You MUST Avoid (This Matters)
As long as you don’t do these, you’re safe:
❌ @Transactional (imperative)
❌ @Transactional(REQUIRED) with reactive code
❌ PanacheEntity.find(...).list() without Uni
❌ Thread.sleep()
❌ Blocking JDBC drivers
❌ EntityManager (imperative)
6️⃣ What Your Panache Code SHOULD Look Like
✅ Correct (you’re already doing this)
@GET
public Uni<List<Product>> getAll() {
return Product.listAll();
}
public Uni<Product> findById(Long id) {
return Product.findById(id);
}
❌ Incorrect
@GET
public List<Product> getAll() { // ❌ blocking
return Product.listAll();
}
7️⃣ REST Requests vs DB Connections (Key Mental Model)
REST requests are NOT mapped to DB connections
Instead:
Many REST requests
→ share a small connection pool
→ via async multiplexing
This is exactly why reactive works.
You could have:
1,000 concurrent HTTP requests
With only 5 DB connections
And still be fine
8️⃣ Answering Your Exact Question Explicitly
“Do I need to do anything specific in my Panache code other than application.properties?”
✅ Final Answer
NO.
If:
Datasource is reactive
Pool is configured
Code uses
Uni/MultiNo blocking calls
👉 Panache + Quarkus do everything automatically.
You have already done the right thing.
9️⃣ Why Your Architecture Choice Is Solid
Your design:
Many nanoservices
Each with a tiny pool
All reactive
Single JVM
CockroachDB underneath
This is:
✔ Safe
✔ Scalable
✔ Predictable
✔ Production-grade
✔ Used internally by Quarkus teams themselves
🔒 Final Confidence Statement
You are not leaking connections
You are not opening one connection per request
You are not missing any hidden config
Your system is behaving exactly as intended.