Mongoose: Slow initial DB query if connection string contains "localhost"

Created on 6 Mar 2018  路  13Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?
Report a bug

What is the current behavior?
If MongoDB query is executed as soon as app is started (and mongoose is initialized), the query is unusually slow if connection string contains localhost. If connection string contains IP address instead of localhost then the query executes quickly.

If app is started (and mongoose is initialized) and if I wait for few seconds before running MongoDB query then query executes quickly regardless whether using localhost or an IP address to reference MongoDB server.

If the current behavior is a bug, please provide the steps to reproduce.

  1. Connect to MongoDB with the connection string: mongodb://{username}:{password}@localhost/{db-name} and then execute the following code:
    console.time("findById");

    db.Users
        .findById("572a2912fd79bae00856d9da")
        .exec(function(err, user) {
            console.timeEnd("findById");
        })
    ;

The result is:

    findById: 5235.082ms
  1. Connect to MongoDB with the string: mongodb://{username}:{password}@127.0.0.1/{db-name} and then execute the following code:

    console.time("findById");
    
    db.Users
        .findById("572a2912fd79bae00856d9da")
        .exec(function(err, user) {
            console.timeEnd("findById");
        })
    ;
    

    The result is:

    findById: 272.564ms
    

What is the expected behavior?
No difference in initial connection speed whether we're referencing MongoDB server hostname via localhost or an IP address.

Please mention your node.js, mongoose and MongoDB version.
Node: v8.9.4
mongoose: v5.0.9
MongoDB: v3.4.9

needs clarification won't fix

Most helpful comment

Just wanted to add one more data point. Surprisingly, using 127.0.01 instead of localhost caused a significant improvement in startup time, roughly a full second faster. This only became relevant when I upgraded the driver from 2.X to 3.X (3.1.1 to be precise)

All 13 comments

@choxnox Can you try doing a dns lookup for localhost on your system and see if that takes longer than you expect? It sounds like you're experiencing an issue with name resolution ( at least for localhost ). If you're on mac or linux/unix check /etc/hosts for a localhost entry, if you're on windows, try C:WindowsSystem32Driversetchosts. make sure you have an entry for localhost:
127.0.0.1 localhost

I have the same issue, using localhost takes up to 10s to connect but using 127.0.0.1 takes about 10ms.
I have localhost in my /etc/hosts
The thing is, I'm not using mongoose, I'm using the node-mongodb native driver. So my guess is this has nothing to do with mongoose

Node: v8.10.0
mongodb: v3.0.4 (node driver)
MongoDB: v3.4.13 (server)

I checked the native driver bug queue on jira here and there aren't any existing reports about slowness resolving localhost.

@selimachour can you elaborate on your environment? what OS/version are you using? Can you post the results of ping localhost vs ping 127.0.0.1 here?

@lineus I'll elaborate ...
I've been having some issues with internet lately, very slow sometimes and I noticed that my express server at http://localhost:4000 which usually replies within 30ms (multiple F5 in chrome while watching the network tab) would once every about 10 refreshes, take up to 10s ! to reply.
When I disable the wifi, the problem goes away but no internet :(

Yesterday, I stumbled accross your thread and tried the 127.0.0.1 thing which also fixed my problem. Since I'm not using mongoose but the plain node-mongodb module, I thought I'd let you know that it might not be a mongoose thing.

Today, I tried again at my place and at the office and can confirm I only have the problem with bad internet when I use "localhost".

My config:
LinuxMint 18.1 (4.10.0-38-generic)
localhost is defined in /etc/hosts

I'm not at home right now so the ping localhost and 127.0.0.1 show the same results.

Hope this helps

This is most certainly an issue on your end then and how your local setup resolves localhost. I'll keep this open for now but for the moment I'm going to mark this as won't fix because I am pretty confident this is not a mongoose issue.

I can't reproduce your issue locally either so I'm not sure what more we can do here.

Random bit of information which might or might not be related to this issue.

I work from several places, but at one particular house it takes _one minute_ to connect to Mongo using localhost, which made me stop programming whenever I was at that place. Thanks to this issue, I resolved the slow connection by connecting to 127.0.0.1 instead. :smile:

However, using the same laptop at other places, I have never had this issue. Also, ping localhost or using localhost anywhere else, I never had any slowness problems ever. So it looks like the particular combination of Mongoose + localhost + the specific network router at this place is causing issues. :thinking: I understand if you won't be able to fix this. :joy:

TBH I've had similar issues where mongoose tests fail 100% of the time when I'm connected to the WiFi at this WeWork, no idea why. The instant I disconnect from their WiFi or connect to my hotspot the tests pass again. :confused:

FYI I was having a very hard time debugging some slow tests that use node-mongodb-native. Found this thread. Changed the mongodb connection string to use ip instead of hostname and it sped right up. Except in my case I'm running them in a docker-compose environment and had to change it to use the container ip.

Just wanted to add one more data point. Surprisingly, using 127.0.01 instead of localhost caused a significant improvement in startup time, roughly a full second faster. This only became relevant when I upgraded the driver from 2.X to 3.X (3.1.1 to be precise)

It is because the default connection tcp family is 6 (mongoose/node_modules/mongodb-core/lib/connection/connection.js Connection.prototype.connect)
This will cause cause system do dns lookup first if host is 'localhost'.
if ::1 localhost is not defined in /etc/hosts then the system will try to query the external dns server.
it responds slow because the dns server fails to respond until timeout.

BTW, 127.0.0.1 is ok although the mongodb driver will still try to make connection with tcp family 6. However, net.createConnection will detect the host ip string type and make ipv4 connection (this is adjusted by nodejs dns.lookup)

@hshixun That is _exactly_ the problem! Nice detective work. I was getting really slow connections to my replica set. I add &family=4 to the end of the connection string and problem solved. @varunjayaraman Why is IPv6 the default for connections?

@hshixun - amazing work, thank you so much for looking into that.

So ... now that we know the problem, does someone who's smart on TCP and similar know if there's a solution to this?

Was this page helpful?
0 / 5 - 0 ratings