diff --git a/binding.gyp b/binding.gyp
index e3b2a925a30f83a042471c207e0a5191f45f8280..a449730d213ce048b093faf035e879928786a23c 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -39,9 +39,6 @@
 {
   'variables': {
     'runtime%': 'node',
-    # UV integration in C core is enabled by default. It can be disabled
-    # by setting this argument to anything else.
-    'grpc_uv%': 'true',
     # Some Node installations use the system installation of OpenSSL, and on
     # some systems, the system OpenSSL still does not have ALPN support. This
     # will let users recompile gRPC to work without ALPN.
@@ -90,17 +87,11 @@
       'include'
     ],
     'defines': [
-      'GPR_BACKWARDS_COMPATIBILITY_MODE'
+      'GPR_BACKWARDS_COMPATIBILITY_MODE',
+      'GRPC_ARES=0',
+      'GRPC_UV'
     ],
     'conditions': [
-      ['grpc_uv=="true"', {
-        'defines': [
-          'GRPC_ARES=0',
-          # Disabling this while bugs are ironed out. Uncomment this to
-          # re-enable libuv integration in C core.
-          'GRPC_UV'
-        ]
-      }],
       ['grpc_gcov=="true"', {
         'cflags': [
             '-O0',
@@ -949,13 +940,10 @@
         "src/node/ext/call_credentials.cc",
         "src/node/ext/channel.cc",
         "src/node/ext/channel_credentials.cc",
-        "src/node/ext/completion_queue_threadpool.cc",
-        "src/node/ext/completion_queue_uv.cc",
+        "src/node/ext/completion_queue.cc",
         "src/node/ext/node_grpc.cc",
         "src/node/ext/server.cc",
         "src/node/ext/server_credentials.cc",
-        "src/node/ext/server_generic.cc",
-        "src/node/ext/server_uv.cc",
         "src/node/ext/slice.cc",
         "src/node/ext/timeval.cc",
       ],
diff --git a/build.yaml b/build.yaml
index fbef42502d0d29cf2df22c3c975162298d69f25d..5f23562022a6d21ed6ec1562ec86cfecad776967 100644
--- a/build.yaml
+++ b/build.yaml
@@ -4457,13 +4457,10 @@ node_modules:
   - src/node/ext/call_credentials.cc
   - src/node/ext/channel.cc
   - src/node/ext/channel_credentials.cc
-  - src/node/ext/completion_queue_threadpool.cc
-  - src/node/ext/completion_queue_uv.cc
+  - src/node/ext/completion_queue.cc
   - src/node/ext/node_grpc.cc
   - src/node/ext/server.cc
   - src/node/ext/server_credentials.cc
-  - src/node/ext/server_generic.cc
-  - src/node/ext/server_uv.cc
   - src/node/ext/slice.cc
   - src/node/ext/timeval.cc
 openssl_fallback:
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index bd60775aad9f84d4ccf1dec910a1247b094a7c4f..8877995f8f258929b54739e5d04d1839b6aba0f2 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -46,7 +46,6 @@
 #include "call.h"
 #include "channel.h"
 #include "completion_queue.h"
-#include "completion_queue_async_worker.h"
 #include "call_credentials.h"
 #include "slice.h"
 #include "timeval.h"
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index 1263cc0d286c465f14b9041088c8e7b25f0717dd..2c533f056a0dc8639fc747ec9d4410d58c390c41 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -42,7 +42,6 @@
 #include "call.h"
 #include "channel.h"
 #include "completion_queue.h"
-#include "completion_queue_async_worker.h"
 #include "channel_credentials.h"
 #include "timeval.h"
 
diff --git a/src/node/ext/completion_queue_uv.cc b/src/node/ext/completion_queue.cc
similarity index 98%
rename from src/node/ext/completion_queue_uv.cc
rename to src/node/ext/completion_queue.cc
index 0f6f7da46077a6129a1981f454f47122aa425e0b..a743784c37472719e5dd74e7db582257f69e1a6f 100644
--- a/src/node/ext/completion_queue_uv.cc
+++ b/src/node/ext/completion_queue.cc
@@ -31,8 +31,6 @@
  *
  */
 
-#ifdef GRPC_UV
-
 #include <uv.h>
 #include <node.h>
 #include <v8.h>
@@ -97,5 +95,3 @@ void CompletionQueueInit(Local<Object> exports) {
 
 }  // namespace node
 }  // namespace grpc
-
-#endif /* GRPC_UV */
diff --git a/src/node/ext/completion_queue_async_worker.h b/src/node/ext/completion_queue_async_worker.h
deleted file mode 100644
index 6e541167658aefd4c88c92394c0bafe83a2dfb14..0000000000000000000000000000000000000000
--- a/src/node/ext/completion_queue_async_worker.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_
-#define NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_
-#include <nan.h>
-
-#include "grpc/grpc.h"
-
-namespace grpc {
-namespace node {
-
-/* A worker that asynchronously calls completion_queue_next, and queues onto the
-   node event loop a call to the function stored in the event's tag. */
-class CompletionQueueAsyncWorker : public Nan::AsyncWorker {
- public:
-  CompletionQueueAsyncWorker();
-
-  ~CompletionQueueAsyncWorker();
-  /* Calls completion_queue_next with the provided deadline, and stores the
-     event if there was one or sets an error message if there was not */
-  void Execute();
-
-  /* Returns the completion queue attached to this class */
-  static grpc_completion_queue *GetQueue();
-
-  /* Convenience function to create a worker with the given arguments and queue
-     it to run asynchronously */
-  static void Next();
-
-  /* Initialize the CompletionQueueAsyncWorker class */
-  static void Init(v8::Local<v8::Object> exports);
-
- protected:
-  /* Called when Execute has succeeded (completed without setting an error
-     message). Calls the saved callback with the event that came from
-     completion_queue_next */
-  void HandleOKCallback();
-
-  void HandleErrorCallback();
-
- private:
-  grpc_event result;
-
-  static grpc_completion_queue *queue;
-
-  // Number of grpc_completion_queue_next calls in the thread pool
-  static int current_threads;
-  // Number of grpc_completion_queue_next calls waiting to enter the thread pool
-  static int waiting_next_calls;
-};
-
-}  // namespace node
-}  // namespace grpc
-
-#endif  // NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_
diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc
deleted file mode 100644
index 7b1bdda03341e14afbe70a03c6a684659b6a2ee3..0000000000000000000000000000000000000000
--- a/src/node/ext/completion_queue_threadpool.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* I don't like using #ifndef, but I don't see a better way to do this */
-#ifndef GRPC_UV
-
-#include <node.h>
-#include <nan.h>
-
-#include "grpc/grpc.h"
-#include "grpc/support/log.h"
-#include "grpc/support/time.h"
-#include "completion_queue.h"
-#include "call.h"
-
-namespace grpc {
-namespace node {
-
-namespace {
-
-/* A worker that asynchronously calls completion_queue_next, and queues onto the
-   node event loop a call to the function stored in the event's tag. */
-class CompletionQueueAsyncWorker : public Nan::AsyncWorker {
- public:
-  CompletionQueueAsyncWorker();
-
-  ~CompletionQueueAsyncWorker();
-  /* Calls completion_queue_next with the provided deadline, and stores the
-     event if there was one or sets an error message if there was not */
-  void Execute();
-
-  /* Returns the completion queue attached to this class */
-  static grpc_completion_queue *GetQueue();
-
-  /* Convenience function to create a worker with the given arguments and queue
-     it to run asynchronously */
-  static void Next();
-
-  /* Initialize the CompletionQueueAsyncWorker class */
-  static void Init(v8::Local<v8::Object> exports);
-
- protected:
-  /* Called when Execute has succeeded (completed without setting an error
-     message). Calls the saved callback with the event that came from
-     completion_queue_next */
-  void HandleOKCallback();
-
-  void HandleErrorCallback();
-
- private:
-  static void TryAddWorker();
-
-  grpc_event result;
-
-  static grpc_completion_queue *queue;
-
-  // Number of grpc_completion_queue_next calls in the thread pool
-  static int current_threads;
-  // Number of grpc_completion_queue_next calls waiting to enter the thread pool
-  static int waiting_next_calls;
-};
-
-const int max_queue_threads = 2;
-
-using v8::Function;
-using v8::Local;
-using v8::Object;
-using v8::Value;
-
-grpc_completion_queue *CompletionQueueAsyncWorker::queue;
-
-// Invariants: current_threads <= max_queue_threads
-// (current_threads == max_queue_threads) || (waiting_next_calls == 0)
-
-int CompletionQueueAsyncWorker::current_threads;
-int CompletionQueueAsyncWorker::waiting_next_calls;
-
-CompletionQueueAsyncWorker::CompletionQueueAsyncWorker()
-    : Nan::AsyncWorker(NULL) {}
-
-CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {}
-
-void CompletionQueueAsyncWorker::Execute() {
-  result =
-      grpc_completion_queue_next(queue, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
-  if (!result.success) {
-    SetErrorMessage("The async function encountered an error");
-  }
-}
-
-grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; }
-
-void CompletionQueueAsyncWorker::TryAddWorker() {
-  if (current_threads < max_queue_threads && waiting_next_calls > 0) {
-    current_threads += 1;
-    waiting_next_calls -= 1;
-    CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
-    Nan::AsyncQueueWorker(worker);
-  }
-  GPR_ASSERT(current_threads <= max_queue_threads);
-  GPR_ASSERT((current_threads == max_queue_threads) ||
-             (waiting_next_calls == 0));
-}
-
-void CompletionQueueAsyncWorker::Next() {
-  waiting_next_calls += 1;
-  TryAddWorker();
-}
-
-void CompletionQueueAsyncWorker::Init(Local<Object> exports) {
-  Nan::HandleScope scope;
-  current_threads = 0;
-  waiting_next_calls = 0;
-  queue = grpc_completion_queue_create(NULL);
-}
-
-void CompletionQueueAsyncWorker::HandleOKCallback() {
-  Nan::HandleScope scope;
-  current_threads -= 1;
-  TryAddWorker();
-  CompleteTag(result.tag, NULL);
-
-  DestroyTag(result.tag);
-}
-
-void CompletionQueueAsyncWorker::HandleErrorCallback() {
-  Nan::HandleScope scope;
-  current_threads -= 1;
-  TryAddWorker();
-  CompleteTag(result.tag, ErrorMessage());
-
-  DestroyTag(result.tag);
-}
-
-}  // namespace
-
-grpc_completion_queue *GetCompletionQueue() {
-  return CompletionQueueAsyncWorker::GetQueue();
-}
-
-void CompletionQueueNext() {
-  CompletionQueueAsyncWorker::Next();
-}
-
-void CompletionQueueInit(Local<Object> exports) {
-  CompletionQueueAsyncWorker::Init(exports);
-}
-
-}  // namespace node
-}  // namespace grpc
-
-#endif  /* GRPC_UV */
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index 122e5e63ee9d16c0eb9f0418e57761fdd29e5586..f600cb9def609d4a968078903ab48f1f1362d0d3 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -43,18 +43,15 @@
 #include "grpc/support/time.h"
 
 // TODO(murgatroid99): Remove this when the endpoint API becomes public
-#ifdef GRPC_UV
 extern "C" {
 #include "src/core/lib/iomgr/pollset_uv.h"
 }
-#endif
 
 #include "call.h"
 #include "call_credentials.h"
 #include "channel.h"
 #include "channel_credentials.h"
 #include "server.h"
-#include "completion_queue_async_worker.h"
 #include "server_credentials.h"
 #include "slice.h"
 #include "timeval.h"
@@ -438,9 +435,7 @@ void init(Local<Object> exports) {
   InitWriteFlags(exports);
   InitLogConstants(exports);
 
-#ifdef GRPC_UV
   grpc_pollset_work_run_loop = 0;
-#endif
 
   grpc::node::Call::Init(exports);
   grpc::node::CallCredentials::Init(exports);
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index 5384305631db0e0009c0e7c177a765682ba794fd..f7c62a311d3d31502f57c5bd71fd6f023112e0d1 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -41,7 +41,6 @@
 #include <vector>
 #include "call.h"
 #include "completion_queue.h"
-#include "completion_queue_async_worker.h"
 #include "grpc/grpc.h"
 #include "grpc/grpc_security.h"
 #include "grpc/support/log.h"
@@ -78,6 +77,30 @@ using v8::Value;
 Nan::Callback *Server::constructor;
 Persistent<FunctionTemplate> Server::fun_tpl;
 
+static Callback *shutdown_callback = NULL;
+
+class ServerShutdownOp : public Op {
+ public:
+  ServerShutdownOp(grpc_server *server) : server(server) {}
+
+  ~ServerShutdownOp() {}
+
+  Local<Value> GetNodeValue() const { return Nan::Null(); }
+
+  bool ParseOp(Local<Value> value, grpc_op *out) { return true; }
+  bool IsFinalOp() { return false; }
+  void OnComplete(bool success) {
+    /* Because cancel_all_calls was called, we assume that shutdown_and_notify
+       completes successfully */
+    grpc_server_destroy(server);
+  }
+
+  grpc_server *server;
+
+ protected:
+  std::string GetTypeString() const { return "shutdown"; }
+};
+
 class NewCallOp : public Op {
  public:
   NewCallOp() {
@@ -156,6 +179,10 @@ class TryShutdownOp: public Op {
       server_persist;
 };
 
+Server::Server(grpc_server *server) : wrapped_server(server) {}
+
+Server::~Server() { this->ShutdownServer(); }
+
 void Server::Init(Local<Object> exports) {
   HandleScope scope;
   Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
@@ -184,6 +211,36 @@ void Server::DestroyWrappedServer() {
   }
 }
 
+NAN_METHOD(ServerShutdownCallback) {
+  if (!info[0]->IsNull()) {
+    return Nan::ThrowError("forceShutdown failed somehow");
+  }
+}
+
+void Server::ShutdownServer() {
+  Nan::HandleScope scope;
+  if (this->wrapped_server != NULL) {
+    if (shutdown_callback == NULL) {
+      Local<FunctionTemplate> callback_tpl =
+          Nan::New<FunctionTemplate>(ServerShutdownCallback);
+      shutdown_callback =
+          new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked());
+    }
+
+    ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
+    unique_ptr<OpVec> ops(new OpVec());
+    ops->push_back(unique_ptr<Op>(op));
+
+    grpc_server_shutdown_and_notify(
+        this->wrapped_server, GetCompletionQueue(),
+        new struct tag(new Callback(**shutdown_callback), ops.release(), NULL,
+                       Nan::Null()));
+    grpc_server_cancel_all_calls(this->wrapped_server);
+    CompletionQueueNext();
+    this->wrapped_server = NULL;
+  }
+}
+
 NAN_METHOD(Server::New) {
   /* If this is not a constructor call, make a constructor call and return
      the result */
diff --git a/src/node/ext/server_generic.cc b/src/node/ext/server_generic.cc
deleted file mode 100644
index 0cf20f754a817693ae888bc2f99363bec04653a7..0000000000000000000000000000000000000000
--- a/src/node/ext/server_generic.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *
- * Copyright 2017, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPC_UV
-
-#include "server.h"
-
-#include <node.h>
-#include <nan.h>
-#include "grpc/grpc.h"
-#include "grpc/support/time.h"
-
-namespace grpc {
-namespace node {
-
-Server::Server(grpc_server *server) : wrapped_server(server) {
-  shutdown_queue = grpc_completion_queue_create(NULL);
-  grpc_server_register_non_listening_completion_queue(server, shutdown_queue,
-                                                      NULL);
-}
-
-Server::~Server() {
-  this->ShutdownServer();
-  grpc_completion_queue_shutdown(this->shutdown_queue);
-  grpc_completion_queue_destroy(this->shutdown_queue);
-}
-
-void Server::ShutdownServer() {
-  if (this->wrapped_server != NULL) {
-    grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue,
-                                    NULL);
-    grpc_server_cancel_all_calls(this->wrapped_server);
-    grpc_completion_queue_pluck(this->shutdown_queue, NULL,
-                                gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
-    grpc_server_destroy(this->wrapped_server);
-    this->wrapped_server = NULL;
-  }
-}
-
-}  // namespace grpc
-}  // namespace node
-
-#endif /* GRPC_UV */
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
deleted file mode 100644
index 789938318ebfd99bb8864b8b407fab2167335981..0000000000000000000000000000000000000000
--- a/src/node/ext/server_uv.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *
- * Copyright 2017, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifdef GRPC_UV
-
-#include "server.h"
-
-#include <node.h>
-#include <nan.h>
-#include "grpc/grpc.h"
-#include "grpc/support/time.h"
-
-#include "call.h"
-#include "completion_queue.h"
-
-namespace grpc {
-namespace node {
-
-using Nan::Callback;
-using Nan::MaybeLocal;
-
-using v8::External;
-using v8::Function;
-using v8::FunctionTemplate;
-using v8::Local;
-using v8::Object;
-using v8::Value;
-
-static Callback *shutdown_callback = NULL;
-
-class ServerShutdownOp : public Op {
- public:
-  ServerShutdownOp(grpc_server *server): server(server) {
-  }
-
-  ~ServerShutdownOp() {
-  }
-
-  Local<Value> GetNodeValue() const {
-    return Nan::Null();
-  }
-
-  bool ParseOp(Local<Value> value, grpc_op *out) {
-    return true;
-  }
-  bool IsFinalOp() {
-    return false;
-  }
-  void OnComplete(bool success) {
-    /* Because cancel_all_calls was called, we assume that shutdown_and_notify
-       completes successfully */
-    grpc_server_destroy(server);
-  }
-
-  grpc_server *server;
-
- protected:
-  std::string GetTypeString() const { return "shutdown"; }
-};
-
-Server::Server(grpc_server *server) : wrapped_server(server) {
-}
-
-Server::~Server() {
-  this->ShutdownServer();
-}
-
-NAN_METHOD(ServerShutdownCallback) {
-  if (!info[0]->IsNull()) {
-    return Nan::ThrowError("forceShutdown failed somehow");
-  }
-}
-
-void Server::ShutdownServer() {
-  Nan::HandleScope scope;
-  if (this->wrapped_server != NULL) {
-    if (shutdown_callback == NULL) {
-      Local<FunctionTemplate>callback_tpl =
-          Nan::New<FunctionTemplate>(ServerShutdownCallback);
-      shutdown_callback = new Callback(
-          Nan::GetFunction(callback_tpl).ToLocalChecked());
-    }
-
-    ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
-    unique_ptr<OpVec> ops(new OpVec());
-    ops->push_back(unique_ptr<Op>(op));
-
-    grpc_server_shutdown_and_notify(
-        this->wrapped_server, GetCompletionQueue(),
-        new struct tag(new Callback(**shutdown_callback), ops.release(), NULL,
-                       Nan::Null()));
-    grpc_server_cancel_all_calls(this->wrapped_server);
-    CompletionQueueNext();
-    this->wrapped_server = NULL;
-  }
-}
-
-}  // namespace grpc
-}  // namespace node
-
-#endif /* GRPC_UV */
diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template
index bbd62c5512a755165bf61e6afbdd032e46a2fb2c..933174ab6edb6b12565ad3bd7ec6e7a02177e682 100644
--- a/templates/binding.gyp.template
+++ b/templates/binding.gyp.template
@@ -41,9 +41,6 @@
   {
     'variables': {
       'runtime%': 'node',
-      # UV integration in C core is enabled by default. It can be disabled
-      # by setting this argument to anything else.
-      'grpc_uv%': 'true',
       # Some Node installations use the system installation of OpenSSL, and on
       # some systems, the system OpenSSL still does not have ALPN support. This
       # will let users recompile gRPC to work without ALPN.
@@ -87,17 +84,11 @@
         'include'
       ],
       'defines': [
-        'GPR_BACKWARDS_COMPATIBILITY_MODE'
+        'GPR_BACKWARDS_COMPATIBILITY_MODE',
+        'GRPC_ARES=0',
+        'GRPC_UV'
       ],
       'conditions': [
-        ['grpc_uv=="true"', {
-          'defines': [
-            'GRPC_ARES=0',
-            # Disabling this while bugs are ironed out. Uncomment this to
-            # re-enable libuv integration in C core.
-            'GRPC_UV'
-          ]
-        }],
         ['grpc_gcov=="true"', {
           % for arg, prop in [('CPPFLAGS', 'cflags'), ('DEFINES', 'defines'), ('LDFLAGS', 'ldflags')]:
           %  if configs['gcov'].get(arg, None) is not None:
diff --git a/tools/run_tests/helper_scripts/build_node.sh b/tools/run_tests/helper_scripts/build_node.sh
index 2c4cf02d8fe7d2398b5e2508abb0be67d0ea1a82..07ecf98396aa725b2bb886026e1e1933e7bbfbb1 100755
--- a/tools/run_tests/helper_scripts/build_node.sh
+++ b/tools/run_tests/helper_scripts/build_node.sh
@@ -46,6 +46,4 @@ case "$CONFIG" in
   *) config_flag='--release' ;;
 esac
 
-uv_flag=$2
-
-npm install --unsafe-perm --build-from-source $uv_flag $config_flag
+npm install --unsafe-perm --build-from-source $config_flag
diff --git a/tools/run_tests/performance/build_performance.sh b/tools/run_tests/performance/build_performance.sh
index 3f7c9fed961d966395d0027729d21867667d724a..5f8749dda2725f9a30b9ced02ef0387d568e5e36 100755
--- a/tools/run_tests/performance/build_performance.sh
+++ b/tools/run_tests/performance/build_performance.sh
@@ -61,9 +61,6 @@ do
   "csharp")
     python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --compiler coreclr
     ;;
-  "node")
-    python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --iomgr_platform=uv
-    ;;
   *)
     python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8
     ;;
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index a1ec1b2f4570d9ab9424f2b28c739c81758d2505..b55632815f063c526c62de24aa7bb7692deb08de 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -430,10 +430,6 @@ class NodeLanguage(object):
     _check_compiler(self.args.compiler, ['default', 'node0.12',
                                          'node4', 'node5', 'node6',
                                          'node7', 'electron1.3', 'electron1.6'])
-    if args.iomgr_platform == "uv":
-      self.use_uv = True
-    else:
-      self.use_uv = False
     if self.args.compiler == 'default':
       self.runtime = 'node'
       self.node_version = '7'
@@ -481,7 +477,6 @@ class NodeLanguage(object):
       else:
         config_flag = '--release'
       return [['tools\\run_tests\\helper_scripts\\build_node.bat',
-               '--grpc_uv={}'.format('true' if self.use_uv else 'false'),
                config_flag]]
     else:
       build_script = 'build_node'
@@ -490,8 +485,7 @@ class NodeLanguage(object):
         # building for electron requires a patch version
         self.node_version += '.0'
       return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script),
-               self.node_version,
-               '--grpc_uv={}'.format('true' if self.use_uv else 'false')]]
+               self.node_version]]
 
   def post_tests_steps(self):
     return []
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 1da754d9f8c873fe611ce6b148ee99203d124091..c3c785936aafed340e9a6c2757f3801457a3fa13 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -279,15 +279,6 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS)
                               platforms=['linux'],
                               arch='default',
                               compiler='electron1.6',
-                              iomgr_platform='uv',
-                              labels=['portability'],
-                              extra_args=extra_args,
-                              inner_jobs=inner_jobs)
-
-  test_jobs += _generate_jobs(languages=['node'],
-                              configs=['dbg'],
-                              platforms=['linux'],
-                              iomgr_platform='uv',
                               labels=['portability'],
                               extra_args=extra_args,
                               inner_jobs=inner_jobs)