diff --git a/lib/dns.js b/lib/dns.js
index 4572d253f1bf96..5c175de67452fc 100644
--- a/lib/dns.js
+++ b/lib/dns.js
@@ -2,6 +2,7 @@
 
 const net = require('net');
 const util = require('util');
+const EventEmitter = require('events').EventEmitter;
 
 const cares = process.binding('cares_wrap');
 const uv = process.binding('uv');
@@ -11,6 +12,12 @@ const GetNameInfoReqWrap = cares.GetNameInfoReqWrap;
 
 const isIp = net.isIP;
 
+// `resolving` serves as a gate to `setServers()` which is not async
+// friendly, we have to wait for resolutions to finish before changing
+// the servers in c-ares
+const resolving = new EventEmitter();
+resolving.count = 0;
+resolving.paused = false;
 
 function errnoException(err, syscall, hostname) {
   // FIXME(bnoordhuis) Remove this backwards compatibility shite and pass
@@ -56,7 +63,10 @@ function makeAsync(callback) {
   if (typeof callback !== 'function') {
     return callback;
   }
+  resolving.count++;
   return function asyncCallback() {
+    if (--resolving.count === 0)
+      resolving.emit('empty');
     if (asyncCallback.immediately) {
       // The API already returned, we can invoke the callback immediately.
       callback.apply(null, arguments);
@@ -164,13 +174,20 @@ exports.lookup = function lookup(hostname, options, callback) {
   req.hostname = hostname;
   req.oncomplete = all ? onlookupall : onlookup;
 
-  var err = cares.getaddrinfo(req, hostname, family, hints);
-  if (err) {
-    callback(errnoException(err, 'getaddrinfo', hostname));
-    return {};
+  function enqueue() {
+    var err = cares.getaddrinfo(req, hostname, family, hints);
+    if (err) {
+      callback(errnoException(err, 'getaddrinfo', hostname));
+      return {};
+    }
+    callback.immediately = true;
+    return req;
   }
 
-  callback.immediately = true;
+  if (!resolving.paused)
+    return enqueue();
+
+  resolving.once('ready', enqueue);
   return req;
 };
 
@@ -199,10 +216,18 @@ exports.lookupService = function(host, port, callback) {
   req.port = port;
   req.oncomplete = onlookupservice;
 
-  var err = cares.getnameinfo(req, host, port);
-  if (err) throw errnoException(err, 'getnameinfo', host);
+  function enqueue() {
+    var err = cares.getnameinfo(req, host, port);
+    if (err) throw errnoException(err, 'getnameinfo', host);
+  }
 
   callback.immediately = true;
+
+  if (resolving.paused)
+    resolving.once('ready', enqueue);
+  else
+    return enqueue();
+
   return req;
 };
 
@@ -232,9 +257,19 @@ function resolver(bindingName) {
       hostname: name,
       oncomplete: onresolve
     };
-    var err = binding(req, name);
-    if (err) throw errnoException(err, bindingName);
+
+    function enqueue() {
+      var err = binding(req, name);
+      if (err) throw errnoException(err, bindingName);
+    }
+
     callback.immediately = true;
+
+    if (resolving.paused)
+      resolving.once('ready', enqueue);
+    else
+      return enqueue();
+
     return req;
   }
 }
@@ -278,7 +313,31 @@ exports.getServers = function() {
 };
 
 
-exports.setServers = function(servers) {
+exports.setServers = function setServers(servers) {
+  if (resolving.paused) {
+    return resolving.once('ready', function() {
+      setServers(servers);
+    });
+  }
+
+  if (resolving.count === 0) {
+    return _setServers(servers);
+  }
+
+  resolving.paused = true
+  resolving.once('empty', function() {
+    setImmediate(function() {
+      try {
+        _setServers(servers);
+      } finally {
+        resolving.paused = false;
+        resolving.emit('ready');
+      }
+    });
+  });
+}
+
+function _setServers(servers) {
   // cache the original servers because in the event of an error setting the
   // servers cares won't have any servers available for resolution
   var orig = cares.getServers();
@@ -319,7 +378,7 @@ exports.setServers = function(servers) {
     throw new Error('c-ares failed to set servers: "' + err +
                     '" [' + servers + ']');
   }
-};
+}
 
 // uv_getaddrinfo flags
 exports.ADDRCONFIG = cares.AI_ADDRCONFIG;
diff --git a/test/parallel/test-dns-setserver-async.js b/test/parallel/test-dns-setserver-async.js
new file mode 100644
index 00000000000000..e87a30762253e6
--- /dev/null
+++ b/test/parallel/test-dns-setserver-async.js
@@ -0,0 +1,13 @@
+// should not crash
+// see https://github.com/iojs/io.js/issues/894 for what this is trying
+// to test
+
+var common = require('../common');
+var assert = require('assert');
+var dns = require('dns');
+
+dns.resolve4('www.microsoft.com', function (err, result) {
+  dns.setServers([ '8.8.8.9' ]);
+  dns.resolve4('test.com', function (err, result) {});
+});
+dns.setServers([ '8.8.8.8' ]);