Solving MongoDB timeout

Sometimes you may encounter an error like this

While it’s easy to blame it on an overloaded server, there may be other reasons like

  • You changed something in your database access code
  • You are using a specific version of Mongoose (4.7.1 is known to have problems)
  • Your network condition isn’t good

You can try to set connectionTimeoutMS and socketTimeoutMS to ‘0’, hoping it to never time out, but ‘0’ doesn’t mean never with Mongo (from the FAQ)

The special meaning of 0

Setting connectTimeoutMS and socketTimeoutMS to the value 0 has a special meaning. On the face of it, it means never timeout. However this is a truth with some modifications. Setting it to 0 actually means apply the operating system default socket timeout value.

maxTimeMS is the option you are looking for

Most people try to set a low socketTimeoutMS value to abort server operations. As we have proved above this does not work. To work correctly you want to use the maxTimeMS setting on server operations. This will make MongoDB itself abort the operation if it runs for more than maxTimeMS milliseconds. A simple example is below performing a find operation.

// Execute a find command
col.find({“$where”: “sleep(100) || true”})
 .maxTimeMS(50)
 .count(function(err, count) {
});

So what you can do is:

Increase the timeout value (connectTimeoutMS, socketTimeoutMS)

[cc]
server: {
socketOptions: {
connectTimeoutMS: 60000,
socketTimeoutMS: 60000,
keepAlive: 1
},
[/cc]

Note that those two values’ meaning are

  • 0: default socket timeout (20 secs for Linux)
  • 30s: default for Mongo DB
  • 60s: longer timeout for our case

Add keep alive to the connection

It’s a safeguard against timeout. From Mongoose docs

A note about keepAlive

For long running applications, it is often prudent to enable keepAlive with a number of milliseconds. Without it, after some period of time you may start to see “connection closed” errors for what seems like no reason. If so, after reading this, you may decide to enable keepAlive:

options.server.socketOptions = options.replset.socketOptions = { keepAlive: 120 };
mongoose.connect(uri, options);

Hope this can help someone with the same question 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.