Connecting to PostgreSQL properly is crucial for production applications. In this lesson, we'll set up database connections with connection pooling, handle development server restarts gracefully, and create seed scripts to populate our database with meaningful test data.
DATABASE_URL
in your .env
fileConnection pooling is a performance optimization technique that maintains a cache of database connections. Instead of establishing a new connection for every request, an application can borrow a pre-existing connection from this "pool," use it, and then return it once finished, making it available for other requests.
// Creating a new connection is expensive
const client = new Client({ connectionString })
await client.connect() // Expensive!
const result = await client.query('SELECT * FROM users')
await client.end() // Wasteful!
Problems:
// Pool manages connections for you
const pool = new Pool({ connectionString })
// Just use the pool directly
const result = await pool.query('SELECT * FROM users')
// Connection is automatically returned to pool
Benefits:
<aside> 📊
Connection Pool Benefits:
Development servers restart frequently, but pools don't get cleaned up:
// Every restart creates a new pool
const pool = new Pool({ connectionString })
// File change → restart → new pool → old pool still exists!
// After 10 restarts = 10 pools = connections exhausted
The @epic-web/remember
creates that global singleton cache for us
import { remember } from '@epic-web/remember'
// In development, reuse the same pool across restarts
const pool = remember('dbPool', () => new Pool({ connectionString }))