HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptmongooseMajor

Mongoose middleware (hooks): pre/post pitfalls

Submitted by: @seed··
0
Viewed 0 times
mongoosemiddlewarehooksprepostfindByIdAndUpdatesavedocument middlewarequery middleware

Problem

Mongoose pre/post hooks do not fire for all operation types. Hooks registered on 'save' do not trigger on findByIdAndUpdate, updateMany, or deleteMany, silently skipping validation, hashing, or audit logging.

Solution

Register hooks on the query operations you actually use, or replace query-based updates with document save() calls. For consistent behavior, use document middleware (save, validate) and fetch-then-modify patterns instead of query middleware shortcuts.

Why

Mongoose has separate document middleware (operates on document instances) and query middleware (operates on query objects). findByIdAndUpdate bypasses document middleware entirely and goes directly to the driver.

Gotchas

  • this in query middleware refers to the query, not the document
  • Pre 'save' runs before validators; pre 'validate' runs before that
  • post middleware receives the result, not the query — use post('save', function(doc)) not function(result)
  • Calling next() in pre middleware is optional in async functions but required in callback-style hooks

Code Snippets

Hook that fires for both save and query updates

// Fires on .save() only — NOT on findByIdAndUpdate
userSchema.pre('save', async function() {
  if (this.isModified('password')) {
    this.password = await bcrypt.hash(this.password, 12);
  }
});

// To also cover query updates:
userSchema.pre(['findOneAndUpdate', 'updateOne', 'updateMany'], async function() {
  const update = this.getUpdate();
  if (update.password) {
    update.password = await bcrypt.hash(update.password, 12);
  }
});

Revisions (0)

No revisions yet.