Merge branch 'cq_create_api_changes' into cq_create_api_changes_with_factory
diff --git a/BUILD b/BUILD
index 053f581..b3364c5 100644
--- a/BUILD
+++ b/BUILD
@@ -308,8 +308,8 @@
     srcs = [
         "src/core/lib/profiling/basic_timers.c",
         "src/core/lib/profiling/stap_timers.c",
-        "src/core/lib/support/arena.c",
         "src/core/lib/support/alloc.c",
+        "src/core/lib/support/arena.c",
         "src/core/lib/support/atm.c",
         "src/core/lib/support/avl.c",
         "src/core/lib/support/backoff.c",
@@ -354,8 +354,8 @@
         "src/core/lib/support/wrap_memcpy.c",
     ],
     hdrs = [
-        "src/core/lib/support/arena.h",
         "src/core/lib/profiling/timers.h",
+        "src/core/lib/support/arena.h",
         "src/core/lib/support/backoff.h",
         "src/core/lib/support/block_annotate.h",
         "src/core/lib/support/env.h",
@@ -527,6 +527,7 @@
         "src/core/lib/surface/channel_ping.c",
         "src/core/lib/surface/channel_stack_type.c",
         "src/core/lib/surface/completion_queue.c",
+        "src/core/lib/surface/completion_queue_factory.c",
         "src/core/lib/surface/event_string.c",
         "src/core/lib/surface/lame_client.c",
         "src/core/lib/surface/metadata_array.c",
@@ -636,6 +637,7 @@
         "src/core/lib/surface/channel_init.h",
         "src/core/lib/surface/channel_stack_type.h",
         "src/core/lib/surface/completion_queue.h",
+        "src/core/lib/surface/completion_queue_factory.h",
         "src/core/lib/surface/event_string.h",
         "src/core/lib/surface/init.h",
         "src/core/lib/surface/lame_client.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a8bff5..d4d52e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -968,6 +968,7 @@
   src/core/lib/surface/channel_ping.c
   src/core/lib/surface/channel_stack_type.c
   src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
   src/core/lib/surface/event_string.c
   src/core/lib/surface/lame_client.c
   src/core/lib/surface/metadata_array.c
@@ -1279,6 +1280,7 @@
   src/core/lib/surface/channel_ping.c
   src/core/lib/surface/channel_stack_type.c
   src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
   src/core/lib/surface/event_string.c
   src/core/lib/surface/lame_client.c
   src/core/lib/surface/metadata_array.c
@@ -1581,6 +1583,7 @@
   src/core/lib/surface/channel_ping.c
   src/core/lib/surface/channel_stack_type.c
   src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
   src/core/lib/surface/event_string.c
   src/core/lib/surface/lame_client.c
   src/core/lib/surface/metadata_array.c
@@ -1830,6 +1833,7 @@
   src/core/lib/surface/channel_ping.c
   src/core/lib/surface/channel_stack_type.c
   src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
   src/core/lib/surface/event_string.c
   src/core/lib/surface/lame_client.c
   src/core/lib/surface/metadata_array.c
@@ -2439,6 +2443,7 @@
   src/core/lib/surface/channel_ping.c
   src/core/lib/surface/channel_stack_type.c
   src/core/lib/surface/completion_queue.c
+  src/core/lib/surface/completion_queue_factory.c
   src/core/lib/surface/event_string.c
   src/core/lib/surface/lame_client.c
   src/core/lib/surface/metadata_array.c
diff --git a/Makefile b/Makefile
index a1659cc..d47ec94 100644
--- a/Makefile
+++ b/Makefile
@@ -2859,6 +2859,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
@@ -3173,6 +3174,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
@@ -3478,6 +3480,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
@@ -3707,6 +3710,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
@@ -4318,6 +4322,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
diff --git a/binding.gyp b/binding.gyp
index 2ec5776..37c281e 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -712,6 +712,7 @@
         'src/core/lib/surface/channel_ping.c',
         'src/core/lib/surface/channel_stack_type.c',
         'src/core/lib/surface/completion_queue.c',
+        'src/core/lib/surface/completion_queue_factory.c',
         'src/core/lib/surface/event_string.c',
         'src/core/lib/surface/lame_client.c',
         'src/core/lib/surface/metadata_array.c',
diff --git a/build.yaml b/build.yaml
index 72b1537..4e8119b 100644
--- a/build.yaml
+++ b/build.yaml
@@ -262,6 +262,7 @@
   - src/core/lib/surface/channel_init.h
   - src/core/lib/surface/channel_stack_type.h
   - src/core/lib/surface/completion_queue.h
+  - src/core/lib/surface/completion_queue_factory.h
   - src/core/lib/surface/event_string.h
   - src/core/lib/surface/init.h
   - src/core/lib/surface/lame_client.h
@@ -384,6 +385,7 @@
   - src/core/lib/surface/channel_ping.c
   - src/core/lib/surface/channel_stack_type.c
   - src/core/lib/surface/completion_queue.c
+  - src/core/lib/surface/completion_queue_factory.c
   - src/core/lib/surface/event_string.c
   - src/core/lib/surface/lame_client.c
   - src/core/lib/surface/metadata_array.c
diff --git a/config.m4 b/config.m4
index 2bf302b..379f3ce 100644
--- a/config.m4
+++ b/config.m4
@@ -185,6 +185,7 @@
     src/core/lib/surface/channel_ping.c \
     src/core/lib/surface/channel_stack_type.c \
     src/core/lib/surface/completion_queue.c \
+    src/core/lib/surface/completion_queue_factory.c \
     src/core/lib/surface/event_string.c \
     src/core/lib/surface/lame_client.c \
     src/core/lib/surface/metadata_array.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 6d1a597..4088a04 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -343,6 +343,7 @@
                       'src/core/lib/surface/channel_init.h',
                       'src/core/lib/surface/channel_stack_type.h',
                       'src/core/lib/surface/completion_queue.h',
+                      'src/core/lib/surface/completion_queue_factory.h',
                       'src/core/lib/surface/event_string.h',
                       'src/core/lib/surface/init.h',
                       'src/core/lib/surface/lame_client.h',
@@ -555,6 +556,7 @@
                       'src/core/lib/surface/channel_ping.c',
                       'src/core/lib/surface/channel_stack_type.c',
                       'src/core/lib/surface/completion_queue.c',
+                      'src/core/lib/surface/completion_queue_factory.c',
                       'src/core/lib/surface/event_string.c',
                       'src/core/lib/surface/lame_client.c',
                       'src/core/lib/surface/metadata_array.c',
@@ -782,6 +784,7 @@
                               'src/core/lib/surface/channel_init.h',
                               'src/core/lib/surface/channel_stack_type.h',
                               'src/core/lib/surface/completion_queue.h',
+                              'src/core/lib/surface/completion_queue_factory.h',
                               'src/core/lib/surface/event_string.h',
                               'src/core/lib/surface/init.h',
                               'src/core/lib/surface/lame_client.h',
diff --git a/grpc.def b/grpc.def
index 30d60b0..1589316 100644
--- a/grpc.def
+++ b/grpc.def
@@ -53,6 +53,9 @@
     grpc_shutdown
     grpc_version_string
     grpc_g_stands_for
+    grpc_completion_queue_factory_lookup
+    grpc_completion_queue_create_for_next
+    grpc_completion_queue_create_for_pluck
     grpc_completion_queue_create
     grpc_completion_queue_next
     grpc_completion_queue_pluck
diff --git a/grpc.gemspec b/grpc.gemspec
index 8074df2..127162e 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -260,6 +260,7 @@
   s.files += %w( src/core/lib/surface/channel_init.h )
   s.files += %w( src/core/lib/surface/channel_stack_type.h )
   s.files += %w( src/core/lib/surface/completion_queue.h )
+  s.files += %w( src/core/lib/surface/completion_queue_factory.h )
   s.files += %w( src/core/lib/surface/event_string.h )
   s.files += %w( src/core/lib/surface/init.h )
   s.files += %w( src/core/lib/surface/lame_client.h )
@@ -472,6 +473,7 @@
   s.files += %w( src/core/lib/surface/channel_ping.c )
   s.files += %w( src/core/lib/surface/channel_stack_type.c )
   s.files += %w( src/core/lib/surface/completion_queue.c )
+  s.files += %w( src/core/lib/surface/completion_queue_factory.c )
   s.files += %w( src/core/lib/surface/event_string.c )
   s.files += %w( src/core/lib/surface/lame_client.c )
   s.files += %w( src/core/lib/surface/metadata_array.c )
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index d8085a0..6218e3e 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -52,7 +52,7 @@
 Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
                          ClientContext* context, const InputMessage& request,
                          OutputMessage* result) {
-  CompletionQueue cq(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING);
+  CompletionQueue cq(true); // Pluckable completion queue
   Call call(channel->CreateCall(method, context, &cq));
   CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
             CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h
index f34b82d..0130e9c 100644
--- a/include/grpc++/impl/codegen/completion_queue.h
+++ b/include/grpc++/impl/codegen/completion_queue.h
@@ -103,7 +103,7 @@
  public:
   /// Default constructor. Implicitly creates a \a grpc_completion_queue
   /// instance.
-  CompletionQueue() : CompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING) {}
+  CompletionQueue() : CompletionQueue(false) {}
 
   /// Wrap \a take, taking ownership of the instance.
   ///
@@ -147,8 +147,9 @@
   ///
   /// \return true if read a regular event, false if the queue is shutting down.
   bool Next(void** tag, bool* ok) {
-    return (AsyncNextInternal(tag, ok, g_core_codegen_interface->gpr_inf_future(
-                                           GPR_CLOCK_REALTIME)) != SHUTDOWN);
+    return (AsyncNextInternal(tag, ok,
+                              g_core_codegen_interface->gpr_inf_future(
+                                  GPR_CLOCK_REALTIME)) != SHUTDOWN);
   }
 
   /// Request the shutdown of the queue.
@@ -217,10 +218,14 @@
                                   OutputMessage* result);
 
   /// Private constructor of CompletionQueue only visible to friend classes
-  CompletionQueue(grpc_cq_completion_type completion_type,
-                  grpc_cq_polling_type polling_type) {
-    cq_ = g_core_codegen_interface->grpc_completion_queue_create(
-        completion_type, polling_type, nullptr);
+  CompletionQueue(bool is_pluck) {
+    if (is_pluck) {
+      cq_ = g_core_codegen_interface->grpc_completion_queue_create_for_pluck(
+          nullptr);
+    } else {
+      cq_ = g_core_codegen_interface->grpc_completion_queue_create_for_next(
+          nullptr);
+    }
     InitialAvalanching();  // reserve this for the future shutdown
   }
 
diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h
index 4c8567f..af7abdf 100644
--- a/include/grpc++/impl/codegen/core_codegen.h
+++ b/include/grpc++/impl/codegen/core_codegen.h
@@ -46,9 +46,10 @@
 /// Implementation of the core codegen interface.
 class CoreCodegen : public CoreCodegenInterface {
  private:
-  grpc_completion_queue* grpc_completion_queue_create(
-      grpc_cq_completion_type completion_type,
-      grpc_cq_polling_type polling_type, void* reserved) override;
+  grpc_completion_queue* grpc_completion_queue_create_for_next(
+      void* reserved) override;
+  grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+      void* reserved) override;
   void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
   grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
                                          gpr_timespec deadline,
diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h
index 8f2b4a3..fd4767a 100644
--- a/include/grpc++/impl/codegen/core_codegen_interface.h
+++ b/include/grpc++/impl/codegen/core_codegen_interface.h
@@ -60,9 +60,10 @@
   virtual void assert_fail(const char* failed_assertion, const char* file,
                            int line) = 0;
 
-  virtual grpc_completion_queue* grpc_completion_queue_create(
-      grpc_cq_completion_type completion_type,
-      grpc_cq_polling_type polling_type, void* reserved) = 0;
+  virtual grpc_completion_queue* grpc_completion_queue_create_for_next(
+      void* reserved) = 0;
+  virtual grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+      void* reserved) = 0;
   virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0;
   virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq,
                                                  void* tag,
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index c09ab5e..4e12f32 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -138,7 +138,7 @@
   ClientReader(ChannelInterface* channel, const RpcMethod& method,
                ClientContext* context, const W& request)
       : context_(context),
-        cq_(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING),
+        cq_(true), // Pluckable cq
         call_(channel->CreateCall(method, context, &cq_)) {
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
               CallOpClientSendClose>
@@ -212,7 +212,7 @@
   ClientWriter(ChannelInterface* channel, const RpcMethod& method,
                ClientContext* context, R* response)
       : context_(context),
-        cq_(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING),
+        cq_(true), // Pluckable cq
         call_(channel->CreateCall(method, context, &cq_)) {
     finish_ops_.RecvMessage(response);
     finish_ops_.AllowNoMessage();
@@ -297,7 +297,7 @@
   ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
                      ClientContext* context)
       : context_(context),
-        cq_(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING),
+        cq_(true), // Pluckable cq
         call_(channel->CreateCall(method, context, &cq_)) {
     CallOpSet<CallOpSendInitialMetadata> ops;
     ops.SendInitialMetadata(context->send_initial_metadata_,
@@ -512,7 +512,7 @@
   Call* const call_;
   ServerContext* const ctx_;
 };
-}
+}  // namespace internal
 
 // class to represent the user API for a bidirectional streaming call
 template <class W, class R>
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 29fd304..d2c1879 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -97,6 +97,7 @@
 typedef enum {
   /** Events are popped out by calling grpc_completion_queue_next() API ONLY */
   GRPC_CQ_NEXT = 1,
+
   /** Events are popped out by calling grpc_completion_queue_pluck() API ONLY*/
   GRPC_CQ_PLUCK
 } grpc_cq_completion_type;
@@ -116,21 +117,51 @@
   GRPC_CQ_DEFAULT_POLLING,
 
   /** Similar to GRPC_CQ_DEFAULT_POLLING except that the completion queues will
-      not contain any 'listening file descriptors' (i.e file descriptors used to
-      listen to incoming channels */
+     not contain any 'listening file descriptors' (i.e file descriptors used to
+     listen to incoming channels) */
   GRPC_CQ_NON_LISTENING,
 
   /** The completion queue will not have an associated pollset. Note that
-      grpc_completion_queue_next() or grpc_completion_queue_pluck() MUST still
-      be called to pop events from the completion queue; it is not required to
-      call them actively to make I/O progress */
+     grpc_completion_queue_next() or grpc_completion_queue_pluck() MUST still be
+     called to pop events from the completion queue; it is not required to call
+     them actively to make I/O progress */
   GRPC_CQ_NON_POLLING
 } grpc_cq_polling_type;
 
+#define GRPC_CQ_CURRENT_VERSION 1
+typedef struct grpc_completion_queue_attributes {
+  /* The version number of this structure. More fields might be added to this
+     structure in future. */
+  int version; /* Set to GRPC_CQ_CURRENT_VERSION */
+
+  grpc_cq_completion_type cq_completion_type;
+
+  grpc_cq_polling_type cq_polling_type;
+} grpc_completion_queue_attributes;
+
+/** The completion queue factory structure is opaque to the callers of grpc */
+typedef struct grpc_completion_queue_factory grpc_completion_queue_factory;
+
+/** Returns the completion queue factory based on the attributes. MAY return a
+    NULL if no factory can be found */
+GRPCAPI const grpc_completion_queue_factory *
+grpc_completion_queue_factory_lookup(
+    const grpc_completion_queue_attributes *attributes);
+
+/** Helper function to create a completion queue with grpc_cq_completion_type
+    of GRPC_CQ_NEXT and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */
+GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_next(
+    void *reserved);
+
+/** Helper function to create a completion queue with grpc_cq_completion_type
+    of GRPC_CQ_PLUCK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */
+GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_pluck(
+    void *reserved);
+
 /** Create a completion queue */
 GRPCAPI grpc_completion_queue *grpc_completion_queue_create(
-    grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type,
-    void *reserved);
+    const grpc_completion_queue_factory *factory,
+    const grpc_completion_queue_attributes *attributes, void *reserved);
 
 /** Blocks until an event is available, the completion queue is being shut down,
     or deadline is reached.
diff --git a/package.xml b/package.xml
index f096869..6e72ff9 100644
--- a/package.xml
+++ b/package.xml
@@ -269,6 +269,7 @@
     <file baseinstalldir="/" name="src/core/lib/surface/channel_init.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/completion_queue.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/completion_queue_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/event_string.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
@@ -481,6 +482,7 @@
     <file baseinstalldir="/" name="src/core/lib/surface/channel_ping.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/completion_queue.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/completion_queue_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/event_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/lame_client.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/metadata_array.c" role="src" />
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index e571733..1e88e83 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -115,15 +115,17 @@
 static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
                                      grpc_error *error);
 
-grpc_completion_queue *grpc_completion_queue_create(
-    grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type,
-    void *reserved) {
+grpc_completion_queue *grpc_completion_queue_create_internal(
+    grpc_cq_completion_type completion_type,
+    grpc_cq_polling_type polling_type) {
   grpc_completion_queue *cc;
-  GPR_ASSERT(!reserved);
 
-  GPR_TIMER_BEGIN("grpc_completion_queue_create", 0);
+  GPR_TIMER_BEGIN("grpc_completion_queue_create_internal", 0);
 
-  GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
+  GRPC_API_TRACE(
+      "grpc_completion_queue_create_internal(completion_type=%d, "
+      "polling_type=%d)",
+      2, (completion_type, polling_type));
 
   cc = gpr_zalloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
   grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
@@ -153,7 +155,7 @@
   grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc,
                     grpc_schedule_on_exec_ctx);
 
-  GPR_TIMER_END("grpc_completion_queue_create", 0);
+  GPR_TIMER_END("grpc_completion_queue_create_internal", 0);
 
   return cc;
 }
@@ -381,8 +383,9 @@
       "deadline=gpr_timespec { tv_sec: %" PRId64
       ", tv_nsec: %d, clock_type: %d }, "
       "reserved=%p)",
-      5, (cc, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
-          reserved));
+      5,
+      (cc, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
+       reserved));
   GPR_ASSERT(!reserved);
 
   dump_pending_tags(cc);
@@ -556,8 +559,9 @@
         "deadline=gpr_timespec { tv_sec: %" PRId64
         ", tv_nsec: %d, clock_type: %d }, "
         "reserved=%p)",
-        6, (cc, tag, deadline.tv_sec, deadline.tv_nsec,
-            (int)deadline.clock_type, reserved));
+        6,
+        (cc, tag, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
+         reserved));
   }
   GPR_ASSERT(!reserved);
 
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index 21f28e9..1ff3d64 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -102,4 +102,7 @@
 grpc_cq_completion_type grpc_get_cq_completion_type(grpc_completion_queue *cc);
 grpc_cq_polling_type grpc_get_cq_polling_type(grpc_completion_queue *cc);
 
+grpc_completion_queue *grpc_completion_queue_create_internal(
+    grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type);
+
 #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/lib/surface/completion_queue_factory.c b/src/core/lib/surface/completion_queue_factory.c
new file mode 100644
index 0000000..d68b84e
--- /dev/null
+++ b/src/core/lib/surface/completion_queue_factory.c
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/lib/surface/completion_queue_factory.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+#include <grpc/support/log.h>
+
+/*
+ * == Default completion queue factory implementation ==
+ */
+
+static grpc_completion_queue* default_create(
+    const grpc_completion_queue_factory* factory,
+    const grpc_completion_queue_attributes* attr) {
+  return grpc_completion_queue_create_internal(attr->cq_completion_type,
+                                               attr->cq_polling_type);
+}
+
+static grpc_completion_queue_factory_vtable default_vtable = {default_create};
+
+static const grpc_completion_queue_factory g_default_cq_factory = {
+    "Default Factory", NULL, &default_vtable};
+
+/*
+ * == Completion queue factory APIs
+ */
+
+const grpc_completion_queue_factory* grpc_completion_queue_factory_lookup(
+    const grpc_completion_queue_attributes* attributes) {
+  GPR_ASSERT(attributes->version >= 1 &&
+             attributes->version <= GRPC_CQ_CURRENT_VERSION);
+
+  /* The default factory can handle version 1 of the attributes structure. We
+     may have to change this as more fields are added to the structure */
+  return &g_default_cq_factory;
+}
+
+/*
+ * == Completion queue creation APIs ==
+ */
+
+grpc_completion_queue* grpc_completion_queue_create_for_next(void* reserved) {
+  GPR_ASSERT(!reserved);
+  grpc_completion_queue_attributes attr = {1, GRPC_CQ_NEXT,
+                                           GRPC_CQ_DEFAULT_POLLING};
+  return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr);
+}
+
+grpc_completion_queue* grpc_completion_queue_create_for_pluck(void* reserved) {
+  GPR_ASSERT(!reserved);
+  grpc_completion_queue_attributes attr = {1, GRPC_CQ_PLUCK,
+                                           GRPC_CQ_DEFAULT_POLLING};
+  return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr);
+}
+
+grpc_completion_queue* grpc_completion_queue_create(
+    const grpc_completion_queue_factory* factory,
+    const grpc_completion_queue_attributes* attr, void* reserved) {
+  GPR_ASSERT(!reserved);
+  return factory->vtable->create(factory, attr);
+}
diff --git a/src/core/lib/surface/completion_queue_factory.h b/src/core/lib/surface/completion_queue_factory.h
new file mode 100644
index 0000000..57e90b5
--- /dev/null
+++ b/src/core/lib/surface/completion_queue_factory.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H
+#define GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H
+
+#include <grpc/grpc.h>
+#include "src/core/lib/surface/completion_queue.h"
+
+typedef struct grpc_completion_queue_factory_vtable {
+  grpc_completion_queue* (*create)(const grpc_completion_queue_factory*,
+                                   const grpc_completion_queue_attributes*);
+} grpc_completion_queue_factory_vtable;
+
+struct grpc_completion_queue_factory {
+  const char* name;
+  void* data; /* Factory specific data */
+  grpc_completion_queue_factory_vtable* vtable;
+};
+
+#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H */
diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc
index 81b3293..7d8a733 100644
--- a/src/cpp/common/core_codegen.cc
+++ b/src/cpp/common/core_codegen.cc
@@ -54,11 +54,14 @@
 
 namespace grpc {
 
-grpc_completion_queue* CoreCodegen::grpc_completion_queue_create(
-    grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type,
+grpc_completion_queue* CoreCodegen::grpc_completion_queue_create_for_next(
     void* reserved) {
-  return ::grpc_completion_queue_create(completion_type, polling_type,
-                                        reserved);
+  return ::grpc_completion_queue_create_for_next(reserved);
+}
+
+grpc_completion_queue* CoreCodegen::grpc_completion_queue_create_for_pluck(
+    void* reserved) {
+  return ::grpc_completion_queue_create_for_pluck(reserved);
 }
 
 void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) {
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index b11ea72..6adabef 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -153,10 +153,7 @@
     grpc_metadata_array_destroy(&request_metadata_);
   }
 
-  void SetupRequest() {
-    cq_ = grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
-                                       nullptr);
-  }
+  void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); }
 
   void TeardownRequest() {
     grpc_completion_queue_destroy(cq_);
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index ceb2671..27de7bc 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -355,12 +355,12 @@
 
 GPR_EXPORT grpc_completion_queue *GPR_CALLTYPE
 grpcsharp_completion_queue_create_async(void) {
-  return grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  return grpc_completion_queue_create_for_next(NULL);
 }
 
 GPR_EXPORT grpc_completion_queue *GPR_CALLTYPE
 grpcsharp_completion_queue_create_sync(void) {
-  return grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING, NULL);
+  return grpc_completion_queue_create_for_pluck(NULL);
 }
 
 GPR_EXPORT void GPR_CALLTYPE
diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc
index b5227ba..0b8bc01 100644
--- a/src/node/ext/completion_queue_threadpool.cc
+++ b/src/node/ext/completion_queue_threadpool.cc
@@ -141,8 +141,7 @@
   Nan::HandleScope scope;
   current_threads = 0;
   waiting_next_calls = 0;
-  queue =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  queue = grpc_completion_queue_create_for_next(NULL);
 }
 
 void CompletionQueueAsyncWorker::HandleOKCallback() {
diff --git a/src/node/ext/completion_queue_uv.cc b/src/node/ext/completion_queue_uv.cc
index 9c1f093..7290050 100644
--- a/src/node/ext/completion_queue_uv.cc
+++ b/src/node/ext/completion_queue_uv.cc
@@ -92,8 +92,7 @@
 }
 
 void CompletionQueueInit(Local<Object> exports) {
-  queue =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  queue = grpc_completion_queue_create_for_next(NULL);
   uv_prepare_init(uv_default_loop(), &prepare);
   pending_batches = 0;
 }
diff --git a/src/node/ext/server_generic.cc b/src/node/ext/server_generic.cc
index 787605a..24573bd 100644
--- a/src/node/ext/server_generic.cc
+++ b/src/node/ext/server_generic.cc
@@ -44,8 +44,7 @@
 namespace node {
 
 Server::Server(grpc_server *server) : wrapped_server(server) {
-  shutdown_queue = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                GRPC_CQ_DEFAULT_POLLING, NULL);
+  shutdown_queue = grpc_completion_queue_create_for_pluck(NULL);
   grpc_server_register_non_listening_completion_queue(server, shutdown_queue,
                                                       NULL);
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
index 8edb4ef..5ff77ea 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -48,9 +48,7 @@
 
 - (instancetype)init {
   if ((self = [super init])) {
-    _unmanagedQueue = grpc_completion_queue_create(GRPC_CQ_NEXT,
-                                                   GRPC_CQ_DEFAULT_POLLING,
-                                                   NULL);
+    _unmanagedQueue = grpc_completion_queue_create_for_next(NULL);
 
     // This is for the following block to capture the pointer by value (instead
     // of retaining self and doing self->_unmanagedQueue). This is essential
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
index c1bf4ce..8a7c4a7 100644
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
@@ -79,8 +79,7 @@
   gpr_join_host_port(&ffd->localaddr, "127.0.0.1", port);
 
   f.fixture_data = ffd;
-  f.cq = grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
-                                      NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
 
   return f;
 }
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 1840894..6fe4706 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -160,9 +160,7 @@
   int port = grpc_pick_unused_port_or_die();
   char *addr;
   gpr_join_host_port(&addr, "127.0.0.1", port);
-  grpc_completion_queue *cq =
-          grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
-                                       NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
   grpc_channel *client =
       grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL);
@@ -296,9 +294,7 @@
   int port = grpc_pick_unused_port_or_die();
   char *addr;
   gpr_join_host_port(&addr, "127.0.0.1", port);
-  grpc_completion_queue *cq =
-          grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
-                                       NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
   grpc_channel *client =
       grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL);
diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c
index 441088b..c75a524 100644
--- a/src/php/ext/grpc/completion_queue.c
+++ b/src/php/ext/grpc/completion_queue.c
@@ -38,9 +38,7 @@
 grpc_completion_queue *completion_queue;
 
 void grpc_php_init_completion_queue(TSRMLS_D) {
-  completion_queue = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                  GRPC_CQ_DEFAULT_POLLING,
-                                                  NULL);
+  completion_queue = grpc_completion_queue_create_for_pluck(NULL);
 }
 
 void grpc_php_shutdown_completion_queue(TSRMLS_D) {
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index 368919b..34b2623 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -40,7 +40,7 @@
   def __cinit__(self):
     grpc_init()
     with nogil:
-      self.c_completion_queue = grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL)
+      self.c_completion_queue = grpc_completion_queue_create_for_next(NULL)
     self.is_shutting_down = False
     self.is_shutdown = False
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index b26b240..0b2bdef 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -309,19 +309,7 @@
   void grpc_init() nogil
   void grpc_shutdown() nogil
 
-  ctypedef enum grpc_cq_completion_type:
-    GRPC_CQ_NEXT = 1
-    GRPC_CQ_PLUCK = 2
-
-  ctypedef enum grpc_cq_polling_type:
-    GRPC_CQ_DEFAULT_POLLING
-    GRPC_CQ_NON_LISTENING
-    GRPC_CQ_NON_POLLING
-
-  grpc_completion_queue *grpc_completion_queue_create(
-        grpc_cq_completion_type completion_type,
-        grpc_cq_polling_type polling_type,
-        void *reserved) nogil
+  grpc_completion_queue *grpc_completion_queue_create_for_next(void *reserved) nogil
 
   grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,
                                         gpr_timespec deadline,
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index cb6ca34..e1a4e29 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -179,6 +179,7 @@
   'src/core/lib/surface/channel_ping.c',
   'src/core/lib/surface/channel_stack_type.c',
   'src/core/lib/surface/completion_queue.c',
+  'src/core/lib/surface/completion_queue_factory.c',
   'src/core/lib/surface/event_string.c',
   'src/core/lib/surface/lame_client.c',
   'src/core/lib/surface/metadata_array.c',
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 2b9f03a..54b178a 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -171,8 +171,7 @@
   }
   rb_ivar_set(self, id_target, target);
   wrapper->wrapped = ch;
-  wrapper->queue = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                GRPC_CQ_DEFAULT_POLLING, NULL);
+  wrapper->queue = grpc_completion_queue_create_for_pluck(NULL);
   return self;
 }
 
@@ -270,8 +269,7 @@
     parent_call = grpc_rb_get_wrapped_call(parent);
   }
 
-  cq = grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
-                                    NULL);
+  cq = grpc_completion_queue_create_for_pluck(NULL);
   TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
   ch = wrapper->wrapped;
   if (ch == NULL) {
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 3ef6f0e..063f921 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -91,6 +91,9 @@
 grpc_shutdown_type grpc_shutdown_import;
 grpc_version_string_type grpc_version_string_import;
 grpc_g_stands_for_type grpc_g_stands_for_import;
+grpc_completion_queue_factory_lookup_type grpc_completion_queue_factory_lookup_import;
+grpc_completion_queue_create_for_next_type grpc_completion_queue_create_for_next_import;
+grpc_completion_queue_create_for_pluck_type grpc_completion_queue_create_for_pluck_import;
 grpc_completion_queue_create_type grpc_completion_queue_create_import;
 grpc_completion_queue_next_type grpc_completion_queue_next_import;
 grpc_completion_queue_pluck_type grpc_completion_queue_pluck_import;
@@ -385,6 +388,9 @@
   grpc_shutdown_import = (grpc_shutdown_type) GetProcAddress(library, "grpc_shutdown");
   grpc_version_string_import = (grpc_version_string_type) GetProcAddress(library, "grpc_version_string");
   grpc_g_stands_for_import = (grpc_g_stands_for_type) GetProcAddress(library, "grpc_g_stands_for");
+  grpc_completion_queue_factory_lookup_import = (grpc_completion_queue_factory_lookup_type) GetProcAddress(library, "grpc_completion_queue_factory_lookup");
+  grpc_completion_queue_create_for_next_import = (grpc_completion_queue_create_for_next_type) GetProcAddress(library, "grpc_completion_queue_create_for_next");
+  grpc_completion_queue_create_for_pluck_import = (grpc_completion_queue_create_for_pluck_type) GetProcAddress(library, "grpc_completion_queue_create_for_pluck");
   grpc_completion_queue_create_import = (grpc_completion_queue_create_type) GetProcAddress(library, "grpc_completion_queue_create");
   grpc_completion_queue_next_import = (grpc_completion_queue_next_type) GetProcAddress(library, "grpc_completion_queue_next");
   grpc_completion_queue_pluck_import = (grpc_completion_queue_pluck_type) GetProcAddress(library, "grpc_completion_queue_pluck");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index dccdbe7..e036ff7 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -224,7 +224,16 @@
 typedef const char *(*grpc_g_stands_for_type)(void);
 extern grpc_g_stands_for_type grpc_g_stands_for_import;
 #define grpc_g_stands_for grpc_g_stands_for_import
-typedef grpc_completion_queue *(*grpc_completion_queue_create_type)(grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type, void *reserved);
+typedef const grpc_completion_queue_factory *(*grpc_completion_queue_factory_lookup_type)(const grpc_completion_queue_attributes *attributes);
+extern grpc_completion_queue_factory_lookup_type grpc_completion_queue_factory_lookup_import;
+#define grpc_completion_queue_factory_lookup grpc_completion_queue_factory_lookup_import
+typedef grpc_completion_queue *(*grpc_completion_queue_create_for_next_type)(void *reserved);
+extern grpc_completion_queue_create_for_next_type grpc_completion_queue_create_for_next_import;
+#define grpc_completion_queue_create_for_next grpc_completion_queue_create_for_next_import
+typedef grpc_completion_queue *(*grpc_completion_queue_create_for_pluck_type)(void *reserved);
+extern grpc_completion_queue_create_for_pluck_type grpc_completion_queue_create_for_pluck_import;
+#define grpc_completion_queue_create_for_pluck grpc_completion_queue_create_for_pluck_import
+typedef grpc_completion_queue *(*grpc_completion_queue_create_type)(const grpc_completion_queue_factory *factory, const grpc_completion_queue_attributes *attributes, void *reserved);
 extern grpc_completion_queue_create_type grpc_completion_queue_create_import;
 #define grpc_completion_queue_create grpc_completion_queue_create_import
 typedef grpc_event(*grpc_completion_queue_next_type)(grpc_completion_queue *cq, gpr_timespec deadline, void *reserved);
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index a0e8f15..ef57d5b 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -132,8 +132,7 @@
 
   Initializes server instances. */
 static VALUE grpc_rb_server_init(VALUE self, VALUE channel_args) {
-  grpc_completion_queue *cq = grpc_completion_queue_create(
-      GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_pluck(NULL);
   grpc_rb_server *wrapper = NULL;
   grpc_server *srv = NULL;
   grpc_channel_args args;
@@ -190,8 +189,8 @@
   request_call_stack st;
   VALUE result;
   void *tag = (void *)&st;
-  grpc_completion_queue *call_queue = grpc_completion_queue_create(
-      GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *call_queue =
+      grpc_completion_queue_create_for_pluck(NULL);
   gpr_timespec deadline;
 
   TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index 2ecb758..cf3d9f6 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -125,8 +125,7 @@
 
   /* Create server, completion events */
   a.server = grpc_server_create(NULL, NULL);
-  a.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  a.cq = grpc_completion_queue_create_for_next(NULL);
   gpr_event_init(&a.done_thd);
   gpr_event_init(&a.done_write);
   a.validator = server_validator;
@@ -198,8 +197,7 @@
     grpc_exec_ctx_finish(&exec_ctx);
   }
 
-  shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
   grpc_server_shutdown_and_notify(a.server, shutdown_cq, NULL);
   GPR_ASSERT(grpc_completion_queue_pluck(
                  shutdown_cq, NULL, grpc_timeout_seconds_to_deadline(1), NULL)
diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c
index e0f1d27..b961ffa 100644
--- a/test/core/bad_ssl/bad_ssl_test.c
+++ b/test/core/bad_ssl/bad_ssl_test.c
@@ -61,8 +61,7 @@
   grpc_status_code status;
   grpc_call_error error;
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   cq_verifier *cqv = cq_verifier_create(cq);
 
   grpc_op ops[6];
diff --git a/test/core/bad_ssl/server_common.c b/test/core/bad_ssl/server_common.c
index 1176c07..6740471 100644
--- a/test/core/bad_ssl/server_common.c
+++ b/test/core/bad_ssl/server_common.c
@@ -67,8 +67,7 @@
   grpc_call_details call_details;
   grpc_metadata_array request_metadata_recv;
 
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   grpc_completion_queue *shutdown_cq;
 
   grpc_call_details_init(&call_details);
@@ -85,8 +84,7 @@
   while (!shutdown_finished) {
     if (got_sigint && !shutdown_started) {
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
-      shutdown_cq = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                 GRPC_CQ_NON_POLLING, NULL);
+      shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
       grpc_server_shutdown_and_notify(server, shutdown_cq, NULL);
       GPR_ASSERT(
           grpc_completion_queue_pluck(shutdown_cq, NULL,
@@ -97,8 +95,9 @@
       shutdown_started = 1;
     }
     ev = grpc_completion_queue_next(
-        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                         gpr_time_from_micros(1000000, GPR_TIMESPAN)),
+        cq,
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                     gpr_time_from_micros(1000000, GPR_TIMESPAN)),
         NULL);
     switch (ev.type) {
       case GRPC_OP_COMPLETE:
diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c
index f440e33..433f77d 100644
--- a/test/core/client_channel/lb_policies_test.c
+++ b/test/core/client_channel/lb_policies_test.c
@@ -65,9 +65,9 @@
 } servers_fixture;
 
 typedef struct request_sequences {
-  size_t n;         /* number of iterations */
-  int *connections; /* indexed by the interation number, value is the index of
-                       the server it connected to or -1 if none */
+  size_t n;                 /* number of iterations */
+  int *connections;         /* indexed by the interation number, value is the index of
+                               the server it connected to or -1 if none */
   int *connectivity_states; /* indexed by the interation number, value is the
                                client connectivity state */
 } request_sequences;
@@ -197,10 +197,8 @@
   /* Create servers. */
   f->servers = gpr_malloc(sizeof(grpc_server *) * num_servers);
   f->servers_hostports = gpr_malloc(sizeof(char *) * num_servers);
-  f->cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f->shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f->cq = grpc_completion_queue_create_for_next(NULL);
+  f->shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
   for (i = 0; i < num_servers; i++) {
     grpc_metadata_array_init(&f->request_metadata_recv[i]);
     gpr_join_host_port(&f->servers_hostports[i], server_host,
diff --git a/test/core/client_channel/set_initial_connect_string_test.c b/test/core/client_channel/set_initial_connect_string_test.c
index 999c89b..7f38418 100644
--- a/test/core/client_channel/set_initial_connect_string_test.c
+++ b/test/core/client_channel/set_initial_connect_string_test.c
@@ -130,8 +130,7 @@
 }
 
 static void start_rpc(int use_creds, int target_port) {
-  state.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  state.cq = grpc_completion_queue_create_for_next(NULL);
   if (use_creds) {
     state.creds = grpc_fake_transport_security_credentials_create();
   } else {
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index e4dc383..96052ed 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -178,8 +178,7 @@
   cq_verifier *cqv;
   grpc_slice details;
 
-  state.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  state.cq = grpc_completion_queue_create_for_next(NULL);
   cqv = cq_verifier_create(state.cq);
   gpr_join_host_port(&state.target, "127.0.0.1", target_port);
   state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c
index fe203dd..4d9908f 100644
--- a/test/core/end2end/connection_refused_test.c
+++ b/test/core/end2end/connection_refused_test.c
@@ -69,8 +69,7 @@
 
   grpc_metadata_array_init(&trailing_metadata_recv);
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   cqv = cq_verifier_create(cq);
 
   /* if using service config, create channel args */
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 19f9478..c61ea6d 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -108,8 +108,7 @@
   grpc_call_details_init(&call_details);
 
   /* Create server. */
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   server = grpc_server_create(NULL, NULL);
   grpc_server_register_completion_queue(server, cq, NULL);
   GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port(
@@ -261,8 +260,7 @@
   grpc_channel_destroy(client);
 
   /* Destroy server. */
-  shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
   grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000),
                                          grpc_timeout_seconds_to_deadline(5),
diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c
index 35a52fa..1a75483 100644
--- a/test/core/end2end/fixtures/h2_census.c
+++ b/test/core/end2end/fixtures/h2_census.c
@@ -65,10 +65,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -122,9 +120,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack+census", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                                    FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                                    FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack+census",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_compress.c b/test/core/end2end/fixtures/h2_compress.c
index e627007..b73d6d7 100644
--- a/test/core/end2end/fixtures/h2_compress.c
+++ b/test/core/end2end/fixtures/h2_compress.c
@@ -69,10 +69,8 @@
 
   memset(&f, 0, sizeof(f));
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -122,9 +120,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack_compression", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                                         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                                         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack_compression",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack_compression,
      chttp2_init_client_fullstack_compression,
      chttp2_init_server_fullstack_compression,
diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c
index 59ae3f0..5969b11 100644
--- a/test/core/end2end/fixtures/h2_fakesec.c
+++ b/test/core/end2end/fixtures/h2_fakesec.c
@@ -60,10 +60,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
diff --git a/test/core/end2end/fixtures/h2_fd.c b/test/core/end2end/fixtures/h2_fd.c
index b01b52c..53888db 100644
--- a/test/core/end2end/fixtures/h2_fd.c
+++ b/test/core/end2end/fixtures/h2_fd.c
@@ -70,10 +70,8 @@
   grpc_end2end_test_fixture f;
   memset(&f, 0, sizeof(f));
   f.fixture_data = fixture_data;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   create_sockets(fixture_data->fd_pair);
 
diff --git a/test/core/end2end/fixtures/h2_full+pipe.c b/test/core/end2end/fixtures/h2_full+pipe.c
index 6add997..927ca8a 100644
--- a/test/core/end2end/fixtures/h2_full+pipe.c
+++ b/test/core/end2end/fixtures/h2_full+pipe.c
@@ -70,10 +70,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -105,9 +103,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                             FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                             FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c
index 25a76ca..bb24f96 100644
--- a/test/core/end2end/fixtures/h2_full+trace.c
+++ b/test/core/end2end/fixtures/h2_full+trace.c
@@ -70,10 +70,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -105,9 +103,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                             FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                             FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_full.c b/test/core/end2end/fixtures/h2_full.c
index 435d9df..d8d4d95 100644
--- a/test/core/end2end/fixtures/h2_full.c
+++ b/test/core/end2end/fixtures/h2_full.c
@@ -64,10 +64,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -99,9 +97,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                             FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                             FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c
index 7f8f55f..451c556 100644
--- a/test/core/end2end/fixtures/h2_http_proxy.c
+++ b/test/core/end2end/fixtures/h2_http_proxy.c
@@ -69,10 +69,8 @@
   ffd->proxy = grpc_end2end_http_proxy_create();
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -110,9 +108,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                             FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                             FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_load_reporting.c b/test/core/end2end/fixtures/h2_load_reporting.c
index 5b8721a..31f9a46 100644
--- a/test/core/end2end/fixtures/h2_load_reporting.c
+++ b/test/core/end2end/fixtures/h2_load_reporting.c
@@ -67,10 +67,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 1992047..c94f1f6 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -113,10 +113,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
diff --git a/test/core/end2end/fixtures/h2_proxy.c b/test/core/end2end/fixtures/h2_proxy.c
index 55eec11..af7d277 100644
--- a/test/core/end2end/fixtures/h2_proxy.c
+++ b/test/core/end2end/fixtures/h2_proxy.c
@@ -79,10 +79,8 @@
   ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -116,10 +114,11 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack+proxy", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                                   FEATURE_MASK_SUPPORTS_REQUEST_PROXYING |
-                                   FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                                   FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack+proxy",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_REQUEST_PROXYING |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 069b880..0528b5d 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -94,10 +94,8 @@
   grpc_end2end_test_fixture f;
   memset(&f, 0, sizeof(f));
   f.fixture_data = sfd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
   *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c
index c19d485..ca16de0 100644
--- a/test/core/end2end/fixtures/h2_sockpair.c
+++ b/test/core/end2end/fixtures/h2_sockpair.c
@@ -88,10 +88,8 @@
   grpc_end2end_test_fixture f;
   memset(&f, 0, sizeof(f));
   f.fixture_data = sfd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
   *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index 05883b5..79b39aa 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -88,10 +88,8 @@
   grpc_end2end_test_fixture f;
   memset(&f, 0, sizeof(f));
   f.fixture_data = sfd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
   *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 1);
diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c
index d704b97..c6a1ca0 100644
--- a/test/core/end2end/fixtures/h2_ssl.c
+++ b/test/core/end2end/fixtures/h2_ssl.c
@@ -64,10 +64,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
index cf3bc45..59a7283 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -67,10 +67,8 @@
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -206,15 +204,17 @@
 
 typedef enum { SUCCESS, FAIL } test_result;
 
-#define SSL_TEST(request_type, cert_type, result)                         \
-  {                                                                       \
-    {TEST_NAME(request_type, cert_type, result),                          \
-     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |                           \
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |                     \
-         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL,                            \
-     chttp2_create_fixture_secure_fullstack, CLIENT_INIT_NAME(cert_type), \
-     SERVER_INIT_NAME(request_type), chttp2_tear_down_secure_fullstack},  \
-        result                                                            \
+#define SSL_TEST(request_type, cert_type, result)     \
+  {                                                   \
+    {TEST_NAME(request_type, cert_type, result),      \
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |       \
+         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | \
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL,        \
+     chttp2_create_fixture_secure_fullstack,          \
+     CLIENT_INIT_NAME(cert_type),                     \
+     SERVER_INIT_NAME(request_type),                  \
+     chttp2_tear_down_secure_fullstack},              \
+        result                                        \
   }
 
 /* All test configurations */
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c
index 61bcfeb..9a6c9f5 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.c
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.c
@@ -100,10 +100,8 @@
   ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
diff --git a/test/core/end2end/fixtures/h2_uds.c b/test/core/end2end/fixtures/h2_uds.c
index 8f04356..89b4b5e 100644
--- a/test/core/end2end/fixtures/h2_uds.c
+++ b/test/core/end2end/fixtures/h2_uds.c
@@ -70,10 +70,8 @@
                unique++);
 
   f.fixture_data = ffd;
-  f.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  f.shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  f.cq = grpc_completion_queue_create_for_next(NULL);
+  f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
 
   return f;
 }
@@ -104,9 +102,10 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fullstack_uds", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-                                 FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
-                                 FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fullstack_uds",
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
+         FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
+         FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
      chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index 7d306c6..b8b1e5c 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -104,8 +104,7 @@
   gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port,
           proxy->server_port);
 
-  proxy->cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  proxy->cq = grpc_completion_queue_create_for_next(NULL);
   proxy->server = def->create_server(proxy->proxy_port, server_args);
   proxy->client = def->create_client(proxy->server_port, client_args);
 
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 88026d9..afeaf73 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -314,8 +314,9 @@
       cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT;
       const char *access_token = read_cred_artifact(&ctx, inp, NULL, 0);
       grpc_call_credentials *out =
-          access_token == NULL ? NULL : grpc_access_token_credentials_create(
-                                            access_token, NULL);
+          access_token == NULL
+              ? NULL
+              : grpc_access_token_credentials_create(access_token, NULL);
       cred_artifact_ctx_finish(&ctx);
       return out;
     }
@@ -409,8 +410,9 @@
   r->on_done = on_done;
   r->addrs = addresses;
   grpc_timer_init(
-      exec_ctx, &r->timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
-                                        gpr_time_from_seconds(1, GPR_TIMESPAN)),
+      exec_ctx, &r->timer,
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                   gpr_time_from_seconds(1, GPR_TIMESPAN)),
       grpc_closure_create(finish_resolve, r, grpc_schedule_on_exec_ctx),
       gpr_now(GPR_CLOCK_MONOTONIC));
 }
@@ -471,8 +473,9 @@
   fc->ep = ep;
   fc->deadline = deadline;
   grpc_timer_init(
-      exec_ctx, &fc->timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
-                                         gpr_time_from_millis(1, GPR_TIMESPAN)),
+      exec_ctx, &fc->timer,
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                   gpr_time_from_millis(1, GPR_TIMESPAN)),
       grpc_closure_create(do_connect, fc, grpc_schedule_on_exec_ctx),
       gpr_now(GPR_CLOCK_MONOTONIC));
 }
@@ -735,8 +738,7 @@
   g_active_call = new_call(NULL, ROOT);
   g_resource_quota = grpc_resource_quota_create("api_fuzzer");
 
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
 
   while (!is_eof(&inp) || g_channel != NULL || g_server != NULL ||
          pending_channel_watches > 0 || pending_pings > 0 ||
@@ -749,8 +751,9 @@
       if (g_server != NULL) {
         if (!server_shutdown) {
           grpc_server_shutdown_and_notify(
-              g_server, cq, create_validator(assert_success_and_decrement,
-                                             &pending_server_shutdowns));
+              g_server, cq,
+              create_validator(assert_success_and_decrement,
+                               &pending_server_shutdowns));
           server_shutdown = true;
           pending_server_shutdowns++;
         } else if (pending_server_shutdowns == 0) {
@@ -855,8 +858,9 @@
       case 5: {
         if (g_server != NULL) {
           grpc_server_shutdown_and_notify(
-              g_server, cq, create_validator(assert_success_and_decrement,
-                                             &pending_server_shutdowns));
+              g_server, cq,
+              create_validator(assert_success_and_decrement,
+                               &pending_server_shutdowns));
           pending_server_shutdowns++;
           server_shutdown = true;
         } else {
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
index 46acf7d..bc322e4 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.c
+++ b/test/core/end2end/fuzzers/client_fuzzer.c
@@ -65,8 +65,7 @@
       grpc_mock_endpoint_create(discard_write, resource_quota);
   grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
 
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   grpc_transport *transport =
       grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 1);
   grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 33c8ed4..97b436c 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -67,8 +67,7 @@
       grpc_slice_from_copied_buffer((const char *)data, size));
 
   grpc_server *server = grpc_server_create(NULL, NULL);
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   grpc_server_register_completion_queue(server, cq, NULL);
   // TODO(ctiller): add registered methods (one for POST, one for PUT)
   // void *registered_method =
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index 92ea7a7..c394a03 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -121,8 +121,7 @@
   grpc_metadata_array_init(&request_metadata2);
   grpc_call_details_init(&request_details2);
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   cqv = cq_verifier_create(cq);
 
   /* reserve two ports */
diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c
index 7aa8d98..6890cfd 100644
--- a/test/core/end2end/invalid_call_argument_test.c
+++ b/test/core/end2end/invalid_call_argument_test.c
@@ -73,8 +73,7 @@
   grpc_metadata_array_init(&g_state.initial_metadata_recv);
   grpc_metadata_array_init(&g_state.trailing_metadata_recv);
   g_state.deadline = grpc_timeout_seconds_to_deadline(2);
-  g_state.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  g_state.cq = grpc_completion_queue_create_for_next(NULL);
   g_state.cqv = cq_verifier_create(g_state.cq);
   g_state.details = grpc_empty_slice();
   memset(g_state.ops, 0, sizeof(g_state.ops));
@@ -133,8 +132,7 @@
   grpc_metadata_array_destroy(&g_state.trailing_metadata_recv);
 
   if (!g_state.is_client) {
-    shutdown_cq =
-        grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+    shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
     grpc_call_destroy(g_state.server_call);
     grpc_server_shutdown_and_notify(g_state.server, shutdown_cq, tag(1000));
     GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000),
diff --git a/test/core/end2end/multiple_server_queues_test.c b/test/core/end2end/multiple_server_queues_test.c
index 7da5ee5..4696ecd 100644
--- a/test/core/end2end/multiple_server_queues_test.c
+++ b/test/core/end2end/multiple_server_queues_test.c
@@ -38,14 +38,26 @@
   grpc_completion_queue *cq1;
   grpc_completion_queue *cq2;
   grpc_completion_queue *cq3;
+  grpc_completion_queue_attributes attr;
+
   grpc_server *server;
 
   grpc_test_init(argc, argv);
   grpc_init();
-  cq1 =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
-  cq2 = grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_NON_LISTENING, NULL);
-  cq3 = grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, NULL);
+
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_NEXT;
+  attr.cq_polling_type = GRPC_CQ_DEFAULT_POLLING;
+  cq1 = grpc_completion_queue_create(
+      grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
+
+  attr.cq_polling_type = GRPC_CQ_NON_LISTENING;
+  cq2 = grpc_completion_queue_create(
+      grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
+
+  attr.cq_polling_type = GRPC_CQ_NON_POLLING;
+  cq3 = grpc_completion_queue_create(
+      grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
   server = grpc_server_create(NULL, NULL);
   grpc_server_register_completion_queue(server, cq1, NULL);
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index fd8a2f8..dd18b0c 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -59,8 +59,7 @@
 
   grpc_metadata_array_init(&trailing_metadata_recv);
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   cqv = cq_verifier_create(cq);
 
   /* create a call, channel to a non existant server */
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index a9f6a3d..ecb73cf 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -208,8 +208,7 @@
   }
 
   channel = grpc_insecure_channel_create(target, NULL, NULL);
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   the_buffer = grpc_raw_byte_buffer_create(&slice, (size_t)payload_size);
   histogram = gpr_histogram_create(0.01, 60e9);
 
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 4a47fe4..ebcb8f0 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -215,8 +215,7 @@
   }
   gpr_log(GPR_INFO, "creating server on: %s", addr);
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
   if (secure) {
     grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                     test_server1_cert};
@@ -245,8 +244,7 @@
     if (got_sigint && !shutdown_started) {
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
 
-      shutdown_cq = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                 GRPC_CQ_NON_POLLING, NULL);
+      shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
       grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000));
 
       GPR_ASSERT(
@@ -259,8 +257,9 @@
       shutdown_started = 1;
     }
     ev = grpc_completion_queue_next(
-        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                         gpr_time_from_micros(1000000, GPR_TIMESPAN)),
+        cq,
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                     gpr_time_from_micros(1000000, GPR_TIMESPAN)),
         NULL);
     s = ev.tag;
     switch (ev.type) {
diff --git a/test/core/handshake/client_ssl.c b/test/core/handshake/client_ssl.c
index 5ebbc42..16a1f47 100644
--- a/test/core/handshake/client_ssl.c
+++ b/test/core/handshake/client_ssl.c
@@ -289,8 +289,7 @@
   // completed and we know that the client's ALPN list satisfied the server.
   int retries = 10;
   grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
 
   while (state != GRPC_CHANNEL_READY && retries-- > 0) {
     grpc_channel_watch_connectivity_state(
diff --git a/test/core/handshake/server_ssl.c b/test/core/handshake/server_ssl.c
index 6ac22ea..2f93277 100644
--- a/test/core/handshake/server_ssl.c
+++ b/test/core/handshake/server_ssl.c
@@ -104,8 +104,7 @@
   GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
   free(addr);
 
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
 
   grpc_server_register_completion_queue(server, cq, NULL);
   grpc_server_start(server);
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index 582ede4..4fb9921 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -223,8 +223,7 @@
     calls[k].details = grpc_empty_slice();
   }
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
 
   struct grpc_memory_counters client_channel_start =
       grpc_memory_counters_snapshot();
@@ -262,8 +261,9 @@
 
   do {
     event = grpc_completion_queue_next(
-        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                         gpr_time_from_micros(10000, GPR_TIMESPAN)),
+        cq,
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                     gpr_time_from_micros(10000, GPR_TIMESPAN)),
         NULL);
   } while (event.type != GRPC_QUEUE_TIMEOUT);
 
diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c
index 437b547..94d90a5 100644
--- a/test/core/memory_usage/server.c
+++ b/test/core/memory_usage/server.c
@@ -189,8 +189,7 @@
   }
   gpr_log(GPR_INFO, "creating server on: %s", addr);
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
 
   struct grpc_memory_counters before_server_create =
       grpc_memory_counters_snapshot();
@@ -233,8 +232,7 @@
     if (got_sigint && !shutdown_started) {
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
 
-      shutdown_cq = grpc_completion_queue_create(GRPC_CQ_PLUCK,
-                                                 GRPC_CQ_NON_POLLING, NULL);
+      shutdown_cq = grpc_completion_queue_create_for_pluck(NULL);
       grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000));
       GPR_ASSERT(
           grpc_completion_queue_pluck(shutdown_cq, tag(1000),
@@ -245,8 +243,9 @@
       shutdown_started = 1;
     }
     ev = grpc_completion_queue_next(
-        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                         gpr_time_from_micros(1000000, GPR_TIMESPAN)),
+        cq,
+        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                     gpr_time_from_micros(1000000, GPR_TIMESPAN)),
         NULL);
     fling_call *s = ev.tag;
     switch (ev.type) {
diff --git a/test/core/surface/alarm_test.c b/test/core/surface/alarm_test.c
index 2c555db..6ea3444 100644
--- a/test/core/surface/alarm_test.c
+++ b/test/core/surface/alarm_test.c
@@ -58,8 +58,7 @@
   grpc_completion_queue *cc;
 
   LOG_TEST("test_alarm");
-  cc =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cc = grpc_completion_queue_create_for_next(NULL);
   {
     /* regular expiry */
     grpc_event ev;
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index c90e72c..35bda5b 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -78,12 +78,16 @@
   grpc_cq_completion_type completion_types[] = {GRPC_CQ_NEXT, GRPC_CQ_PLUCK};
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
+  grpc_completion_queue_attributes attr;
   LOG_TEST("test_no_op");
 
+  attr.version = 1;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) {
     for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) {
+      attr.cq_completion_type = completion_types[i];
+      attr.cq_polling_type = polling_types[j];
       shutdown_and_destroy(grpc_completion_queue_create(
-          completion_types[i], polling_types[j], NULL));
+          grpc_completion_queue_factory_lookup(&attr), &attr, NULL));
     }
   }
 }
@@ -93,13 +97,17 @@
   grpc_cq_polling_type polling_types[] = {GRPC_CQ_DEFAULT_POLLING,
                                           GRPC_CQ_NON_LISTENING};
   grpc_completion_queue *cq;
+  grpc_completion_queue_attributes attr;
 
   LOG_TEST("test_pollset_conversion");
 
+  attr.version = 1;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) {
     for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) {
-      cq = grpc_completion_queue_create(completion_types[i], polling_types[j],
-                                        NULL);
+      attr.cq_completion_type = completion_types[i];
+      attr.cq_polling_type = polling_types[j];
+      cq = grpc_completion_queue_create(
+          grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
       GPR_ASSERT(grpc_cq_from_pollset(grpc_cq_pollset(cq)) == cq);
       shutdown_and_destroy(cq);
     }
@@ -110,12 +118,17 @@
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
   grpc_completion_queue *cc;
+  grpc_completion_queue_attributes attr;
   grpc_event event;
 
   LOG_TEST("test_wait_empty");
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_NEXT;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) {
-    cc = grpc_completion_queue_create(GRPC_CQ_NEXT, polling_types[i], NULL);
+    attr.cq_polling_type = polling_types[i];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
     event = grpc_completion_queue_next(cc, gpr_now(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT);
     shutdown_and_destroy(cc);
@@ -131,16 +144,20 @@
   grpc_cq_completion completion;
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
-
+  grpc_completion_queue_attributes attr;
   grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_exec_ctx exec_ctx;
   void *tag = create_test_tag();
 
   LOG_TEST("test_cq_end_op");
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_NEXT;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) {
     exec_ctx = init_exec_ctx;  // Reset exec_ctx
-    cc = grpc_completion_queue_create(GRPC_CQ_NEXT, polling_types[i], NULL);
+    attr.cq_polling_type = polling_types[i];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
     grpc_cq_begin_op(cc, tag);
     grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE,
@@ -160,11 +177,16 @@
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
   grpc_completion_queue *cc;
+  grpc_completion_queue_attributes attr;
   grpc_event event;
   LOG_TEST("test_shutdown_then_next_polling");
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_NEXT;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) {
-    cc = grpc_completion_queue_create(GRPC_CQ_NEXT, polling_types[i], NULL);
+    attr.cq_polling_type = polling_types[i];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
     grpc_completion_queue_shutdown(cc);
     event =
         grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
@@ -177,11 +199,16 @@
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
   grpc_completion_queue *cc;
+  grpc_completion_queue_attributes attr;
   grpc_event event;
   LOG_TEST("test_shutdown_then_next_with_timeout");
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_NEXT;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) {
-    cc = grpc_completion_queue_create(GRPC_CQ_NEXT, polling_types[i], NULL);
+    attr.cq_polling_type = polling_types[i];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
     grpc_completion_queue_shutdown(cc);
     event = grpc_completion_queue_next(cc, gpr_inf_future(GPR_CLOCK_REALTIME),
@@ -198,6 +225,7 @@
   grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)];
   grpc_cq_polling_type polling_types[] = {
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
+  grpc_completion_queue_attributes attr;
   grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_exec_ctx exec_ctx;
   unsigned i, j;
@@ -211,9 +239,13 @@
     }
   }
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_PLUCK;
   for (size_t pidx = 0; pidx < GPR_ARRAY_SIZE(polling_types); pidx++) {
     exec_ctx = init_exec_ctx;  // reset exec_ctx
-    cc = grpc_completion_queue_create(GRPC_CQ_PLUCK, polling_types[pidx], NULL);
+    attr.cq_polling_type = polling_types[pidx];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
 
     for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
       grpc_cq_begin_op(cc, tags[i]);
@@ -249,11 +281,16 @@
       GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING};
   grpc_event ev;
   grpc_completion_queue *cc;
+  grpc_completion_queue_attributes attr;
 
   LOG_TEST("test_pluck_after_shutdown");
 
+  attr.version = 1;
+  attr.cq_completion_type = GRPC_CQ_PLUCK;
   for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) {
-    cc = grpc_completion_queue_create(GRPC_CQ_PLUCK, polling_types[i], NULL);
+    attr.cq_polling_type = polling_types[i];
+    cc = grpc_completion_queue_create(
+        grpc_completion_queue_factory_lookup(&attr), &attr, NULL);
     grpc_completion_queue_shutdown(cc);
     ev = grpc_completion_queue_pluck(cc, NULL,
                                      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
diff --git a/test/core/surface/completion_queue_threading_test.c b/test/core/surface/completion_queue_threading_test.c
index 6a23aee..bff69ec 100644
--- a/test/core/surface/completion_queue_threading_test.c
+++ b/test/core/surface/completion_queue_threading_test.c
@@ -101,8 +101,7 @@
 
   LOG_TEST("test_too_many_plucks");
 
-  cc = grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
-                                    NULL);
+  cc = grpc_completion_queue_create_for_pluck(NULL);
   gpr_thd_options_set_joinable(&thread_options);
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -228,8 +227,7 @@
       gpr_malloc((producers + consumers) * sizeof(test_thread_options));
   gpr_event phase1 = GPR_EVENT_INIT;
   gpr_event phase2 = GPR_EVENT_INIT;
-  grpc_completion_queue *cc =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cc = grpc_completion_queue_create_for_next(NULL);
   size_t i;
   size_t total_consumed = 0;
   static int optid = 101;
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index 69f00f4..f9197fb 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -66,8 +66,7 @@
 
 void create_loop_destroy(void *addr) {
   for (int i = 0; i < NUM_OUTER_LOOPS; ++i) {
-    grpc_completion_queue *cq = grpc_completion_queue_create(
-        GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+    grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
     grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL);
 
     for (int j = 0; j < NUM_INNER_LOOPS; ++j) {
@@ -196,8 +195,7 @@
   gpr_asprintf(&args.addr, "localhost:%d", port);
   args.server = grpc_server_create(NULL, NULL);
   grpc_server_add_insecure_http2_port(args.server, args.addr);
-  args.cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  args.cq = grpc_completion_queue_create_for_next(NULL);
   grpc_server_register_completion_queue(args.server, args.cq, NULL);
   grpc_server_start(args.server);
   gpr_thd_new(&server, server_thread, &args, &options);
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index 6531e5e..6c14a5d 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -108,8 +108,7 @@
   GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN ==
              grpc_channel_check_connectivity_state(chan, 0));
 
-  cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cq = grpc_completion_queue_create_for_next(NULL);
 
   grpc_slice host = grpc_slice_from_static_string("anywhere");
   call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
diff --git a/test/core/surface/sequential_connectivity_test.c b/test/core/surface/sequential_connectivity_test.c
index 1880c0b..fbecdd7 100644
--- a/test/core/surface/sequential_connectivity_test.c
+++ b/test/core/surface/sequential_connectivity_test.c
@@ -77,7 +77,7 @@
   grpc_server *server = grpc_server_create(NULL, NULL);
   fixture->add_server_port(server, addr);
   grpc_completion_queue *server_cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+      grpc_completion_queue_create_for_next(NULL);
   grpc_server_register_completion_queue(server, server_cq, NULL);
   grpc_server_start(server);
 
@@ -87,8 +87,7 @@
   gpr_thd_options_set_joinable(&thdopt);
   gpr_thd_new(&server_thread, server_thread_func, &sta, &thdopt);
 
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   grpc_channel *channels[NUM_CONNECTIONS];
   for (size_t i = 0; i < NUM_CONNECTIONS; i++) {
     channels[i] = fixture->create_channel(addr);
diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c
index 47e8eea..0d4de0e 100644
--- a/test/core/surface/server_chttp2_test.c
+++ b/test/core/surface/server_chttp2_test.c
@@ -60,8 +60,7 @@
 
   int port = grpc_pick_unused_port_or_die();
   char *addr = NULL;
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_pluck(NULL);
   grpc_server *server = grpc_server_create(&args, NULL);
   grpc_server_credentials *fake_creds =
       grpc_fake_transport_security_server_credentials_create();
diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c
index e488966..81a39de 100644
--- a/test/core/surface/server_test.c
+++ b/test/core/surface/server_test.c
@@ -70,8 +70,7 @@
 }
 
 void test_request_call_on_no_server_cq(void) {
-  grpc_completion_queue *cc =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cc = grpc_completion_queue_create_for_next(NULL);
   grpc_server *server = grpc_server_create(NULL, NULL);
   GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE ==
              grpc_server_request_call(server, NULL, NULL, NULL, cc, cc, NULL));
@@ -92,8 +91,7 @@
   char *addr;
   grpc_server *server1 = grpc_server_create(&args, NULL);
   grpc_server *server2 = grpc_server_create(&args, NULL);
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   int port = grpc_pick_unused_port_or_die();
   gpr_asprintf(&addr, "[::]:%d", port);
   grpc_server_register_completion_queue(server1, cq, NULL);
@@ -130,8 +128,7 @@
   } else {
     GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr));
   }
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   grpc_server_register_completion_queue(server, cq, NULL);
   grpc_server_start(server);
   grpc_server_shutdown_and_notify(server, cq, NULL);
diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc
index c9c569c..b85ad94 100644
--- a/test/cpp/grpclb/grpclb_test.cc
+++ b/test/cpp/grpclb/grpclb_test.cc
@@ -354,8 +354,9 @@
     }
     GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
     const string expected_token =
-        strlen(sf->lb_token_prefix) == 0 ? "" : sf->lb_token_prefix +
-                                                    std::to_string(sf->port);
+        strlen(sf->lb_token_prefix) == 0
+            ? ""
+            : sf->lb_token_prefix + std::to_string(sf->port);
     GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token",
                                  expected_token.c_str()));
 
@@ -593,8 +594,7 @@
       grpc_channel_args_copy_and_add(NULL, &expected_target_arg, 1);
   gpr_free(expected_target_names);
 
-  cf->cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  cf->cq = grpc_completion_queue_create_for_next(NULL);
   cf->server_uri = lb_uri;
   grpc_channel_credentials *fake_creds =
       grpc_fake_transport_security_credentials_create();
@@ -617,8 +617,7 @@
 static void setup_server(const char *host, server_fixture *sf) {
   int assigned_port;
 
-  sf->cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  sf->cq = grpc_completion_queue_create_for_next(NULL);
   const char *colon_idx = strchr(host, ':');
   if (colon_idx) {
     const char *port_str = colon_idx + 1;
@@ -647,7 +646,7 @@
   gpr_log(GPR_INFO, "Server[%s] shutting down", sf->servers_hostport);
 
   grpc_completion_queue *shutdown_cq =
-      grpc_completion_queue_create(GRPC_CQ_PLUCK, GRPC_CQ_NON_POLLING, NULL);
+      grpc_completion_queue_create_for_pluck(NULL);
   grpc_server_shutdown_and_notify(sf->server, shutdown_cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000),
                                          grpc_timeout_seconds_to_deadline(5),
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index ec6073e..24d2a1b 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -114,8 +114,7 @@
 static void BM_CallCreateDestroy(benchmark::State &state) {
   TrackCounters track_counters;
   Fixture fixture;
-  grpc_completion_queue *cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
   void *method_hdl =
       grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc
index 14eae82..eaba7d8 100644
--- a/test/cpp/microbenchmarks/bm_cq.cc
+++ b/test/cpp/microbenchmarks/bm_cq.cc
@@ -64,8 +64,7 @@
   while (state.KeepRunning()) {
     // TODO: sreek Templatize this benchmark and pass completion type and
     // polling type as parameters
-    grpc_completion_queue_destroy(grpc_completion_queue_create(
-        GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL));
+    grpc_completion_queue_destroy(grpc_completion_queue_create_for_next(NULL));
   }
   track_counters.Finish(state);
 }
@@ -102,8 +101,7 @@
 static void BM_Pass1Core(benchmark::State& state) {
   TrackCounters track_counters;
   // TODO: sreek Templatize this benchmark and pass polling_type as a param
-  grpc_completion_queue* cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_next(NULL);
   gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
   while (state.KeepRunning()) {
     grpc_cq_completion completion;
@@ -122,8 +120,7 @@
 static void BM_Pluck1Core(benchmark::State& state) {
   TrackCounters track_counters;
   // TODO: sreek Templatize this benchmark and pass polling_type as a param
-  grpc_completion_queue* cq = grpc_completion_queue_create(
-      GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_pluck(NULL);
   gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
   while (state.KeepRunning()) {
     grpc_cq_completion completion;
@@ -142,8 +139,7 @@
 static void BM_EmptyCore(benchmark::State& state) {
   TrackCounters track_counters;
   // TODO: sreek Templatize this benchmark and pass polling_type as a param
-  grpc_completion_queue* cq =
-      grpc_completion_queue_create(GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, NULL);
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_next(NULL);
   gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
   while (state.KeepRunning()) {
     grpc_completion_queue_next(cq, deadline, NULL);
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index dba0f4c..14ac1f4 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1309,6 +1309,8 @@
 src/core/lib/surface/channel_stack_type.h \
 src/core/lib/surface/completion_queue.c \
 src/core/lib/surface/completion_queue.h \
+src/core/lib/surface/completion_queue_factory.c \
+src/core/lib/surface/completion_queue_factory.h \
 src/core/lib/surface/event_string.c \
 src/core/lib/surface/event_string.h \
 src/core/lib/surface/init.c \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 14ad133..1a7d5c9 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7551,6 +7551,7 @@
       "src/core/lib/surface/channel_init.h", 
       "src/core/lib/surface/channel_stack_type.h", 
       "src/core/lib/surface/completion_queue.h", 
+      "src/core/lib/surface/completion_queue_factory.h", 
       "src/core/lib/surface/event_string.h", 
       "src/core/lib/surface/init.h", 
       "src/core/lib/surface/lame_client.h", 
@@ -7775,6 +7776,8 @@
       "src/core/lib/surface/channel_stack_type.h", 
       "src/core/lib/surface/completion_queue.c", 
       "src/core/lib/surface/completion_queue.h", 
+      "src/core/lib/surface/completion_queue_factory.c", 
+      "src/core/lib/surface/completion_queue_factory.h", 
       "src/core/lib/surface/event_string.c", 
       "src/core/lib/surface/event_string.h", 
       "src/core/lib/surface/init.h", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index afe7274..7bf54b3 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -388,6 +388,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
@@ -705,6 +706,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index a7d32af..6380761 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -310,6 +310,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
@@ -1043,6 +1046,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 62969e3..70a6d18 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -283,6 +283,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
@@ -548,6 +549,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 3008810..b4de56e 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -367,6 +367,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
@@ -830,6 +833,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 4606913..43afaab 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -378,6 +378,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
@@ -672,6 +673,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index d658f4d..fb03ee8 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -313,6 +313,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.c">
+      <Filter>src\core\lib\surface</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
@@ -953,6 +956,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue_factory.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>