Before you go, check out these stories!

Hackernoon logoEnabling Virtuals In Mongoose Lean Mode (in a FeathersJs service) by@melvinkcx2

Enabling Virtuals In Mongoose Lean Mode (in a FeathersJs service)

Author profile picture

@melvinkcx2Melvin Koh

Software Engineer. Pythonista, JavaScripter. Find me on Twitter @melvinkcx2 ๐Ÿ˜

Originally published at

Iโ€™ve had some hard time when

wasnโ€™t showing up. Without digging deep into Mongoose, I quickly turned
mode off, crafting a new technical debt. After a while, I decided to spend some to look into this particular issue.

(optional) A Quickย Primer

This section is also available in my another article.

What is Lean mode in Mongoose?

When lean mode is enabled, all queries return plain JavaScript objects instead of Mongoose Document. In this case, Mongoose will never have to instantiate Mongoose Document from plain JS object, apply magic methods, etc. Neglecting all these overhead in Lean mode, it makes perfect sense to have lean enabled by default.

What isย Virtual?

Virtuals are attributes derived during query, which the values are not actually persisted in MongoDB. Since virtual is one of Mongoose magic attributes, it is disabled by default.

Using The Mongoose Pluginโ€” mongoose-lean-virtual

Thanks to the community, I discovered the official pluginโ€Šโ€”โ€Š

ย , which supports virtuals which preserving the behavior of lean mode.

In this article, I will be focusing on how to apply

in a typical Feathers.js Mongoose service (generated with feathers-cli).

Install mongoose-lean-virtual

First of all, install it:

npm install --save mongoose-lean-virtuals

Defining Model

Suppose we are creating a

service, we define our model as:

import mongooseLeanVirtuals from 'mongoose-lean-virtuals';

export default (app) => {
  const mongooseClient = app.get('mongooseClient');
  const {Schema} = mongooseClient;
  const {ObjectId} = Schema.Types;

  const user = new Schema({
    // ...

  // Define a virtual attribute `UID`
  user.virtual('uid').get(function () {
    return this._id;

  user.set('toObject', { virtuals: true });    // add this
  user.set('toJSON', { virtuals: true });      // add this

  user.plugin(mongooseLeanVirtuals);           // add this

  return mongooseClient.model('user', user);

In our model, we defined a virtual

to return the Object ID of our user document. Then, we set the properties
to show virtuals. To apply
, we also add in line 20.

Defining Service


, we add
{virtuals: true}
as the value of lean in our service options (line 11).

// user.service.js
import createService from 'feathers-mongoose';
// other imports...

export default (app) => {
  const Model = createModel(app);
  // ...

  const options = {
    lean: {virtuals: true},     // add this line

  const service = createService(options);

  // ...


Try to consume your service, you should be able to see the virtuals now.

> Virtual is now available.

Performance Concern

According to Mongoose documentation, lean mode is enabled to enhance query performance. However, would applying

affect the performance of our app?

I have done a simple profiling and have the results posted here. Feel free to check it out to understand the performance impact of


If you find this article helpful, feel free to share it on Twitter!

Author profile picture

@melvinkcx2Melvin Koh

Read my stories

Software Engineer. Pythonista, JavaScripter. Find me on Twitter @melvinkcx2 ๐Ÿ˜


Join Hacker Noon

Create your free account to unlock your custom reading experience.