In this lesson, you will learn how to maintain a persistent set of ready-to-use database connections to handle high-concurrency traffic efficiently.
The Problem with One-Connection-Per-Request
In a busy web server, creating a new database connection for every incoming request is incredibly expensive. Establishing a connection involves a "handshake" process—negotiating security, authentication, and network resources—which can take precious milliseconds. If 100 users hit your endpoint simultaneously, your server would struggle to spin up 100 separate connections, leading to latency spikes and potential database exhaustion.
The Solution: The Connection Pool
Instead of opening and closing connections, Connection Pooling keeps a "pool" of pre-established, idle connections ready in memory. When a request comes in:
- The application "borrows" an existing connection from the pool.
- The query is executed.
- The connection is "returned" to the pool, remaining open and ready for the next request.
This avoids the overhead of constant connection creation and ensures your application stays performant under load.
Concrete Implementation
Most modern database drivers for Node.js manage this logic internally. Here is how you would configure a pool for a typical PostgreSQL driver:
const { Pool } = require('pg');
// Create the pool once at the application level
const pool = new Pool({
max: 20, // Max number of concurrent connections
idleTimeoutMillis: 30000,
});
// Within your request lifecycle
async function getUser(req, res) {
// Borrow a connection from the pool
const client = await pool.connect();
try {
const result = await client.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
res.json(result.rows[0]);
} finally {
// Return the connection to the pool for reuse
client.release();
}
}
By using pool.connect() and client.release(), you ensure that connections are recycled rather than destroyed. If the pool is empty and the max limit hasn't been reached, the pool will create a new connection. If the pool is full, the request will simply wait for a connection to be returned, ensuring your database isn't overwhelmed by too many simultaneous tasks.
Key Takeaway: Connection pooling transforms database access from an expensive "connect-and-destroy" cycle into a high-performance "borrow-and-reuse" system, ensuring your application remains responsive under heavy traffic.