When To .lean() On Mongoose?

Dmitry Sychev
3 min readJan 10, 2021

TL;DR: Almost always if you’re performing a GET request and almost never if you’re performing a POST/PUT request.

Thanks for reading and don’t forget to like and subscribe!

Oh, you’re still here? I wasn’t ready for this. Well, all right then. I’ve found myself doing a fetch request from my front end and noticed that it was taking an absurdly long time, even timing out some of the time. Upon inspecting the network stats for the fetch, I saw that the response was a whopping 64mb! That means someone trying to use my app on a 56k connection from AOL will probably use up all of their free hours to load the page. Still, that’s terrible design on my part, but I got very curious about whether there’s an efficient way to overcome that blunder.

As this is first time I’m dipping my toes into MongoDB, I of course spent countless hours pouring over the docs on mongodb.com and mongoosejs.com before I even wrote a single line of code… You did too right?

Anyway, since we’re both here. What’s .lean() anyway? Well, to put it as simply as I understand it, when you’re using a Mongoose Schema, the fetch request is, as they put it ‘hydrated’. What that means is that our response object is converted from a plain old JS object into a Mongoose object. So what? That means that you’re able to use all of the functionality that comes included with Mongoose to operate on data. Custom setters and getters, .save(), as well as some others.

Ok, get to .lean() already. Fine, here’s the main course. Getting our fetch as plain old JS means that our optimized by a bootcamp grad backend can actually perform like a it was written by a superstar and everyone will be none the wiser. All jokes aside, it really did seem like magic. Skipping the processing done by Mongoose for a simple get request cut my fetch response time by 10x.

Here’s the Express GET function code in detail:

getDonuts = async (req, res,) => {
await Donut.find({}, (err, donuts) => {
if (err) {
return res.status(400).json({ success: false, error: err })
}
if (!donuts.length) {
return res
.status(404)
.json({ success: false, error: "We're all out of donuts!" }) }
return res.status(200).json({ success: true, data: donuts }) }).lean().catch(err => console.log(err))}

If you’re still with me, lets wrap this up. Use .lean() for pretty much any GET request, unless you’d like a custom getter. Don’t use .lean() for POST/PUT requests, because you won’t be able to use .save() on your data.

--

--