Handbooks / Node.js / Chapter 7
Databases from Node
7 pages · ~5 min✓ Reviewed
Builds on Error Handling and Async Patterns. Next up: Authentication and Security Basics.
Connection Pools: The Mental Model
1. What a Pool Is
- A pool keeps a fixed set of open DB connections and lends them out
- New TCP + auth connection per query is slow
- The server caps connections, so unbounded opens fail
2. Lifecycle and Options
- Acquireclient from pool
- Queryrun statements
- Releaseback to pool
- All clients busy: requests queue until one frees
- Or the acquire timeout fires and the request errors
Parameterised Queries with pg
1. Placeholders
pool.query(text, values)with $1, $2 placeholders- Values travel separately from the SQL text
- Input is never parsed as SQL: no injection
- Rows in
result.rows, count inresult.rowCount
const result = await pool.query( 'SELECT * FROM users WHERE email = $1 AND active = $2', [email, true] ); console.log(result.rows, result.rowCount);
Transactions
1. What a transaction is
- A transaction groups statements: all commit or all roll back (ACID)
- Every statement must run on the same connection
pool.querymay pick a different connection each call, so it cannot hold a transaction
2. pg pattern
const client = await pool.connect(); try { await client.query('BEGIN'); // all statements use client await client.query('COMMIT'); } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); }
release() in finally, even after ROLLBACK
ORMs vs Query Builders: Prisma and Drizzle
1. Builder vs ORM
- Query builder (Knex, Kysely): chained methods build SQL, stays close to SQL
- ORM: maps tables to models, with relations and a schema layer
2. Prisma vs Drizzle
| Prisma |
|---|
MongoDB Driver Basics and Clean Shutdown
1. Client and Collection
- One
MongoClientper process; the pool is built in (maxPoolSize100) await client.connect()once, then reuse; never one per request- No schema; BSON docs get an auto
_id(ObjectId)
const col = client.db('app').collection('users'); await col.insertOne({ name: 'Ann', active: true });
2. CRUD Calls
Database Access Cheat Sheet
1. Pool and pg
- One Pool per process, created at startup
- max × instances < server max_connections
- Options:
max,idleTimeoutMillis,connectionTimeoutMillis pool.query(sql, [vals])with$1,$2- Never interpolate values into the SQL string
2. Transactions
Check yourself
You run pool.query('BEGIN'), then two pool.query updates, then pool.query('COMMIT'). The second update fails. What gets rolled back?
- Possibly nothing: each
pool.querycan use a different connection. BEGINmay sit on one connection and the updates on others, so there is no real transaction.- Fix:
pool.connect(), run every statement on thatclient,client.release()infinally.