Skip to content

Conversation

@AlessioGr
Copy link
Member

@AlessioGr AlessioGr commented Nov 18, 2025

Description

Moves getSession (MongoDB) and getTransaction (Drizzle) calls to immediately before database operations.

Why

When sessions are retrieved early in a function but used much later, there's a race condition window: if a parallel operation commits/ends that session before we use it, we get MongoExpiredSessionError. By retrieving the session right before use, we minimize this window.

This alone significantly reduced transaction errors in #14651. By retrieving sessions closer to use, if a parallel operation commits the transaction before we retrieve it, we get undefined instead of an expired session. Operations then run without a session (which succeeds) rather than attempting to use an expired session (which errors).

Example:

// Before - 50+ line window where session could be ended by parallel operation
const session = await getSession(this, req)
const query = await buildQuery(...)     // Line 1
transform(data)                         // Line 2
// ... 48 more lines
await Model.find(query, { session })    // Line 50 - session might be expired!
// After - retrieve right before use
const query = await buildQuery(...)
transform(data)
const session = await getSession(this, req)  // Get it now
await Model.find(query, { session })         // Use immediately

@AlessioGr AlessioGr changed the title refactor(db-mongodb,drizzle): retrieve sessions immediately before database operations refactor(db-mongodb,drizzle): reduce race condition window between retrieving and using a session Nov 18, 2025
@github-actions
Copy link
Contributor

📦 esbuild Bundle Analysis for payload

This analysis was generated by esbuild-bundle-analyzer. 🤖
This PR introduced no changes to the esbuild bundle! 🙌

@AlessioGr AlessioGr enabled auto-merge (squash) November 18, 2025 05:48
Copy link
Contributor

@DanRibbens DanRibbens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is right to do.

Looking at your simplified explanation:

// After - retrieve right before use
const query = await buildQuery(...)
transform(data)
const session = await getSession(this, req)  // Get it now
await Model.find(query, { session })         // Use immediately

We're saying that we can ignore changes that may have occurred on this transaction when querying related docs, then use the transaction for the find.

Happy to talk more about this and I think I could even make a test that will fail with this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants