Skip to content
Databases for Developers

Lesson 9 of 10 · 20 min

x
9/10

Lesson position in the course — not completion. Use Mark Complete to track finished lessons (saved in this browser).

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
1// In a serverless function — a new connection per invocation2const db = new Client({ connectionString: process.env.DATABASE_URL });3await db.connect();4const result = await db.query('SELECT * FROM users WHERE id = $1', [id]);5await db.end();
After
Shared pool via connection pooler
1// Use a pool at module level — reused across invocations2import { Pool } from 'pg';3const pool = new Pool({4  connectionString: process.env.DATABASE_URL,5  max: 10,6});7 8// No manual connect/disconnect9const { rows } = await pool.query(10  'SELECT * FROM users WHERE id = $1', [id]11);

Exercise

Compare opening a new Client per serverless invocation vs a module-level Pool (or a managed pooler URL). Document max connections on your DB tier and what fails when you exceed them.

Previous

Progress is saved in this browser.

Next Lesson