Skip to content

Feature Proposal: Schema-level Auto-lean option #15894

@aclarembeau

Description

@aclarembeau

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

Hello, I'd like to suggest a new feature: "Add a schema-level lean option that automatically applies .lean() to all query operations for that schema".

When set to true, all queries would return plain JavaScript objects by default instead of Mongoose documents, eliminating the need to manually call .lean() on every query.

Motivation

Performance Benefits

Many applications have schemas that represent read-heavy data where Mongoose's document hydration overhead is unnecessary.
Currently, developers must remember to append .lean() to every query:

await User.findById(id).lean();
await User.find({ active: true }).lean();
await User.findOne({ email }).lean();

This becomes particularly burdensome in codebases with hundreds of queries, leading to:

  • Inconsistent performance: Forgetting .lean() on a single query causes unexpected overhead
  • Code verbosity: Every query requires an extra method call
  • Maintenance burden: Refactoring requires updating each query individually

Use Cases

  • Read-only data models: Logs, analytics, historical records
  • API responses: Data that's immediately serialized to JSON
  • High-throughput services: Microservices where every millisecond counts
  • Aggregation pipelines: Data that goes through significant transformation
  • Cache layers: Objects stored in Redis or similar

Example

Proposed API


const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  role: String,
  createdAt: Date
}, {
  lean: true  // Enable auto-lean for all queries
});

const User = mongoose.model('User', userSchema);

Behavior

// All queries automatically return plain objects
const user = await User.findById(id);
// user is a plain object, not a Mongoose document

const users = await User.find({ role: 'admin' });
// users is an array of plain objects

// Override when needed - explicit opt-out
const fullDoc = await User.findById(id).lean(false);
// fullDoc is a Mongoose document with all methods

Query Types Affected

  • find(), findOne(), findById()
  • findOneAndUpdate(), findOneAndDelete(), etc. (when returning documents)
  • count(), estimatedDocumentCount() (no-op, already return primitives)

Backwards Compatibility

  • Default remains false to maintain current behavior
  • Explicit .lean(false) overrides schema setting
  • Chaining .lean() without arguments remains equivalent to .lean(true)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementThis issue is a user-facing general improvement that doesn't fix a bug or add a new featurenew featureThis change adds new functionality, like a new method or class

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions