Skip to main content

Command Palette

Search for a command to run...

You do NOT need to do anything special in your Panache code.

Published
3 min read

No. You do NOT need to do anything special in your Panache code.

Once you:

  • configure the reactive datasource + pool in application.properties

  • use 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:

  1. Borrow a connection from the pool (non-blocking)

  2. Execute the SQL asynchronously

  3. Return the connection to the pool

  4. Resume your Uni when 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:

ThingLifetimeCost
Hibernate Reactive SessionPer operationLightweight
DB ConnectionPooledExpensive

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 / Multi

  • No 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.