The Reason The Reason - 17 days ago 5
Node.js Question

Why mongoose opens two connections?

It's a simple file from mongoose quick guide

mongoose.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Chat');

var userSchema = mongoose.Schema({
name: String
});

var User = mongoose.model('User', userSchema);
var user = new User({name: 'Andy'});

user.save(); // if i comment it mongoose will keep one connection

User.find({}, function(err, data) { console.log(data); }); // the same if i comment it


I tried to use
db.once
method, but effect the same.

Why does mongoose open the second connection in this case?

mongodb

Answer

Mongoose uses native mongo driver underneath, and it in turn uses connection pooling - I believe the default is 5 connections (Check here).

So your mongoose connection will use up to 5 simultaneous connections when it has simultaneous requests.

And since both user.save and User.find are asynchronous, those will be done simultaneously. So what your "program" tells node:

1. Ok, you need to shoot a `save` request for this user.
2. Also, you need to fire this `find` request.

The node runtime then reads these, runs through the whole of your function (until a return). Then it looks at it's notes:

  • I was supposed to call this save
  • I also need to call this find
  • Hey, mongo native driver (which is written in C++) - here are two tasks for you!
  • and then the mongo driver fires the first request. And it sees it is allowed to open more connections then one, so it does, and fires the second request too, without waiting for the first to finish.

If you called the find within a callback to save, it would be sequential, and the driver would probably reuse the connection it already had.

Example:

// open the first connection
user.save(function(err) {

  if (err) {

    console.log('I always do this super boring error check:', err);
    return;
  }
  // Now that the first request is done, we fire the second one, and
  // we probably end up reusing the connection.
  User.find(/*...*/);
});

Or similar with promises:

user.save().exec().then(function(){
  return User.find(query);
})
.then(function(users) {
  console.log(users);
})
.catch(function(err) {
  // if either fails, the error ends up here.
  console.log(err);
});

By the way, you can tell mongoose to use only one connection if you need to, for some reason:

let connection = mongoose.createConnection(dbUrl, {server: {poolSize: 1}});

That would be the gist of it.

Read more on MongoLab blog and Mongoose website.

Comments