Databases for Developers

Lesson 9 of 10 · 20 min

x
90%

Cloud Databases & Connection Pooling

Managed cloud databases — AWS RDS/Aurora, Azure SQL Database, Google Cloud SQL — handle backups, failover, patching, and scaling. You pay more per GB than self-hosting, but you eliminate the operational work that consumes engineering time at every scale except very large. Connection pooling is the most overlooked production concern. Every database connection consumes memory on the server (PostgreSQL uses ~5MB per connection). Serverless and containerized apps can open thousands of connections under load, exhausting the database's limit. PgBouncer (for Postgres) or connection poolers built into cloud services (Aurora's RDS Proxy, Neon's built-in pooler) sit between your app and the database, multiplexing many application connections onto a small number of real database connections.

Before
Every function opens a new connection
// In a serverless function — a new connection per invocation
const db = new Client({ connectionString: process.env.DATABASE_URL });
await db.connect();
const result = await db.query('SELECT * FROM users WHERE id = $1', [id]);
await db.end();
After
Shared pool via connection pooler
// Use a pool at module level — reused across invocations
import { Pool } from 'pg';
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 10,
});

// No manual connect/disconnect
const { rows } = await pool.query(
  'SELECT * FROM users WHERE id = $1', [id]
);

Key Takeaway

Always use a connection pool in production — raw connections at scale will exhaust your database before your traffic does.

PreviousNext Lesson