If you run npm update on a Mongoose 8 project without a pinned version, you might land on Mongoose 9 without meaning to. And depending on your codebase, that upgrade can go wrong in ways your test suite won't catch.
The headline change is that Mongoose 9 drops callback support from pre() hooks entirely. Any hook shaped like schema.pre('save', function(next) { ... next(); }) still runs, but next() is now a silent no-op. No thrown error, no console warning, just code after the hook that stops firing the way it used to.
That alone is grep-and-fix work. The riskier part is what it does to plugins you didn't write. Auth and validation packages like mongoose-unique-validator and passport-local-mongoose attach their own internal pre-save hooks. If a plugin's version predates confirmed Mongoose 9 support, its hook can silently stop doing its job, meaning duplicate key errors that used to get converted into clean ValidationErrors start reaching your API responses raw.
On top of that, ObjectId construction got stricter, and Mongoose's generated TypeScript types now check query filters more aggressively against your schema shape, so a clean tsc run before the upgrade won't necessarily stay clean after.
I break down all of this with a practical six-step upgrade order, how to write tests that actually catch a silently skipped hook, and a safe rollback plan here: https://devencyclopedia.com/blog/mongoose-9-migration-guide
Top comments (0)