Connection Pool in Spring Boot Explained with a Real E-commerce Example (Thread Pool vs Connection Pool)
If you're preparing for Java Backend or Spring Boot interviews for companies like Oracle, Walmart, Microsoft, Amazon, or any product-based company, one question that frequently comes up is:ā¦
If you’re preparing for Java Backend or Spring Boot interviews for companies like Oracle, Walmart, Microsoft, Amazon, or any product-based company, one question that frequently comes up is:
“What is a Connection Pool, and how is it different from a Thread Pool?”
Many developers know that Spring Boot uses HikariCP by default, but they struggle to explain why a connection pool is needed, how it works internally, and how it interacts with Tomcat’s thread pool.
In this article, we’ll understand:
- What is a Connection Pool?
- Why do we need it?
- How does it work internally?
- Real-world e-commerce example
- Spring Boot implementation
- Thread Pool vs Connection Pool
- Common interview questions
Let’s begin.
What is a Connection Pool?
A Connection Pool is a cache of reusable database connections maintained by the application.
Instead of creating a new database connection for every request, the application reuses existing connections from the pool.
Think of it as a collection of pre-opened database connections that applications can borrow and return whenever required.
Why Do We Need a Connection Pool?
Creating a database connection is an expensive operation.
Every new connection requires:
- Network communication
- Authentication
- Resource allocation
- TCP handshake
- Database session creation
If every request created a new connection, the application would become slow and the database would quickly become overloaded.
Instead, we create a limited number of reusable connections.
Real-Life Analogy
Imagine a taxi stand.
Without a connection pool:
Every customer buys a brand-new taxi just to travel once.
After reaching the destination, the taxi is thrown away.
Obviously, this is extremely expensive.
With a connection pool:
A fixed number of taxis already exist.
Customers simply take an available taxi, complete the journey, and return it for the next customer.
Database connections work exactly the same way.
How Does a Connection Pool Work?
The process is simple.
- Spring Boot starts.
- HikariCP creates a pool of database connections.
- A request arrives.
- The application borrows one available connection.
- SQL queries are executed.
- After the transaction completes, the connection is returned to the pool instead of being closed.
The same connection can now be reused by another request.
Real-World Example: Amazon Flash Sale
Imagine you’re working on Amazon during a flash sale.
Suddenly,
- 1000 users click Place Order at the same time.
Your application is configured as follows:
- Tomcat Thread Pool = 200 Threads
- Hikari Connection Pool = 20 Database Connections
The architecture looks like this:
1000 Users
ā
ā¼
Load Balancer
ā
ā¼
Spring Boot Application
ā
ā¼
Tomcat Thread Pool
(200 Threads)
ā
ā¼
Order Service
ā
ā¼
Hikari Connection Pool
(20 Connections)
ā
ā¼
MySQL Database
Notice something important.
Although 200 requests are being processed simultaneously by Tomcat, only 20 requests can access the database at the same time.
The remaining requests simply wait until a connection becomes available.
Spring Boot Configuration
Spring Boot uses HikariCP as the default connection pool.
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
Let’s understand each property.
| Property | Description |
|---|---|
| maximum-pool-size | Maximum number of database connections allowed |
| minimum-idle | Minimum idle connections always kept ready |
| connection-timeout | Maximum time to wait for a free connection |
| idle-timeout | Close idle connections after this duration |
Order Entity
@Entity
public class Order {
@Id
@GeneratedValue
private Long id;
private String product;
private int quantity;
// getters and setters
}
Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
}
Service Layer
@Service
public class OrderService {
@Autowired
private OrderRepository repository;
@Transactional
public void placeOrder(Order order) {
repository.save(order);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
}
Why are we using Thread.sleep()?
Normally, a transaction completes quickly.
Here, we intentionally delay the transaction to simulate:
- Heavy database processing
- Long-running business logic
- Slow payment processing
Since the transaction is still active, the borrowed database connection cannot be returned to the pool.
This helps demonstrate how connection pools behave under heavy load.
Controller
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService service;
@PostMapping
public String placeOrder(@RequestBody Order order) {
service.placeOrder(order);
return "Order Placed Successfully";
}
}
What Happens When 25 Users Place Orders Simultaneously?
Suppose:
maximumPoolSize = 20
The first twenty users immediately receive database connections.
User 1 ā Connection 1
User 2 ā Connection 2
...
User 20 ā Connection 20
Now users 21 to 25 arrive.
User 21 ā Waiting
User 22 ā Waiting
User 23 ā Waiting
User 24 ā Waiting
User 25 ā Waiting
The pool is full.
These requests wait until another request finishes and returns its connection.
What If No Connection Becomes Available?
Suppose:
connectionTimeout = 30000
If a request waits for more than 30 seconds, HikariCP throws an exception.
SQLTransientConnectionException:
Connection is not available,
request timed out after 30000ms.
This prevents requests from waiting forever.
Understanding the Thread Pool
Many developers confuse Thread Pool and Connection Pool.
They are completely different concepts.
A Thread Pool contains worker threads responsible for processing HTTP requests.
For example,
Tomcat Thread Pool
Thread-1
Thread-2
Thread-3
...
Thread-200
Each request is assigned to one thread.
Example:
User Request
ā
Tomcat Thread
ā
OrderService
ā
Needs Database
ā
Borrow Connection from HikariCP
ā
Execute SQL
ā
Return Connection
ā
Return HTTP Response
Notice that the thread is not the database connection.
The thread simply borrows one whenever it needs to execute SQL.
What Happens If All Threads Need the Database?
Imagine:
- Tomcat Threads = 200
- Database Connections = 20
200 Threads
ā
20 Connections
ā
20 Threads Execute SQL
ā
180 Threads Wait
This is completely normal.
The application can continue handling HTTP requests while limiting expensive database resources.
Why Don’t We Create 200 Database Connections?
This is one of the most common interview questions.
A database connection is expensive because every connection consumes:
- Database memory
- CPU resources
- Network sockets
- Authentication information
- Transaction context
- Session information
If we open hundreds of connections unnecessarily, the database spends more time managing connections than executing queries.
Instead, applications maintain a relatively small connection pool and reuse those connections efficiently.
Connection Pool vs Thread Pool
| Feature | Thread Pool | Connection Pool |
|---|---|---|
| Purpose | Process incoming HTTP requests | Communicate with the database |
| Managed By | Tomcat / ExecutorService | HikariCP |
| Resource | Threads | Database Connections |
| Expensive? | Less expensive | Highly expensive |
| Reused? | Yes | Yes |
Internal Flow
User Request
ā
ā¼
Tomcat Thread Pool
ā
ā¼
Order Service
ā
ā¼
Need Database?
ā
ā¼
Borrow Connection
ā
ā¼
Execute SQL
ā
ā¼
Commit Transaction
ā
ā¼
Return Connection to Pool
ā
ā¼
Return Response
Common HikariCP Properties
| Property | Purpose |
|---|---|
| maximumPoolSize | Maximum database connections |
| minimumIdle | Minimum idle connections |
| connectionTimeout | Wait time for an available connection |
| idleTimeout | Close unused idle connections |
| maxLifetime | Maximum lifetime of a connection before it is replaced |
| leakDetectionThreshold | Detect connections that are held for too long (useful for debugging connection leaks) |
Common Interview Questions
Why is a Connection Pool required?
Creating database connections is expensive. A connection pool improves performance by reusing existing connections instead of creating a new one for every request.
What happens if all connections are busy?
Incoming requests wait until a connection becomes available.
If the waiting time exceeds connectionTimeout, HikariCP throws a timeout exception.
Does every thread have its own database connection?
No.
Threads borrow connections only when they need database access.
After the transaction completes, the connection is returned to the pool for reuse.
Can the Thread Pool size be larger than the Connection Pool size?
Yes.
This is the standard configuration in most production applications.
For example:
- 200 Tomcat threads
- 20 database connections
Many requests can be processed concurrently, while only a limited number access the database at the same time.
Key Takeaways
- A Connection Pool stores reusable database connections.
- Spring Boot uses HikariCP as the default connection pool.
- Database connections are expensive resources.
- Threads process requests, while connections execute SQL.
- Threads borrow connections only when required.
- Connections are returned to the pool after the transaction completes.
- Limiting database connections protects the database from overload and improves scalability.
- A Thread Pool and a Connection Pool solve different problems and work together in every Spring Boot application.
Conclusion
Understanding the difference between Thread Pool and Connection Pool is essential for any backend developer. In real-world applications, thousands of requests may arrive concurrently, but databases cannot efficiently handle thousands of simultaneous connections. By combining a thread pool to process requests and a connection pool to manage database access, Spring Boot applications achieve high performance, better scalability, and efficient resource utilization.
If you can confidently explain this architecture with the Amazon flash sale example, you’ll be well prepared for backend interviews at top product-based companies.