Skip to content

Fix MongoDB connection timeout on Vercel serverless#88

Merged
lnqminh3003 merged 2 commits intobackendfrom
fix/mongodb-stale-connection
Mar 23, 2026
Merged

Fix MongoDB connection timeout on Vercel serverless#88
lnqminh3003 merged 2 commits intobackendfrom
fix/mongodb-stale-connection

Conversation

@rxmox
Copy link
Copy Markdown
Collaborator

@rxmox rxmox commented Mar 19, 2026

Summary

  • Extracts shared DB connection logic into src/utils/db.ts with ping-based stale connection detection. When Vercel freezes/thaws a serverless function, the MongoDB connection can appear connected (readyState === 1) but have a dead TCP socket. The new connectDB() pings the DB to verify liveness and reconnects if stale.
  • Moves DB middleware before route handlers in app.ts. Previously, api/index.ts registered the connectDB middleware after importing app (which already had all routes mounted), so routes fired before the DB check ran. Now ensureConnection is registered on /api in app.ts before any route mounts.
  • Simplifies api/index.ts to just eagerly call connectDB() at module load (for Vercel cold starts) and export app. All connection logic and middleware now lives in utils/db.ts and app.ts.
  • Tunes connection options for serverless: bufferCommands: false (fail fast instead of buffering for 10s), maxPoolSize: 5, heartbeatFrequencyMS: 10000.

Problem

After ~3 days without redeployment, all DB operations fail with:

MongooseError: Operation users.findOne() buffering timed out after 10000ms

Redeploying temporarily fixes it. Root cause: Vercel freezes serverless functions between invocations, leaving stale MongoDB connections that pass the readyState check but can't actually send queries.

Files changed

File Change
src/utils/db.ts New: shared connectDB() with ping health check + ensureConnection middleware
src/app.ts Register ensureConnection middleware before route handlers
api/index.ts Simplified to eager connect + export (removed inline connection logic)
src/server.ts Use shared connectDB() instead of direct mongoose.connect()

Test plan

  • TypeScript compiles without errors
  • Dev server starts and connects to MongoDB
  • GET / returns Hello (no DB middleware on non-API routes)
  • POST /api/auth/login queries DB successfully (returns "Invalid credentials", not a timeout)
  • GET /api/users returns full user list from MongoDB
  • After deploying to Vercel, monitor logs for stale connection recovery and confirm login works after 3+ days without redeployment

rxmox added 2 commits March 19, 2026 16:39
Move DB connection middleware before route handlers in app.ts to ensure
the connection is verified before any route handler fires. Extract shared
connection logic into utils/db.ts with ping-based stale connection
detection to handle Vercel freeze/thaw cycles that leave dead TCP sockets
despite readyState showing connected. Tune connection options for
serverless (bufferCommands: false, smaller pool, heartbeat).
Cast req.params.eventId to string in event controller to fix
TS2345 where string | string[] was passed to functions expecting string.
@lnqminh3003 lnqminh3003 merged commit 4d6696f into backend Mar 23, 2026
1 check passed
@rxmox rxmox deleted the fix/mongodb-stale-connection branch March 26, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants