diff --git a/BUILD b/BUILD
index 1cf4782eaf787077b161b496126adfc5e11b4170..d6598487fbab566e0859d55a5c8bb77debdd9344 100644
--- a/BUILD
+++ b/BUILD
@@ -511,6 +511,7 @@ grpc_cc_library(
         "src/core/lib/json/json_reader.c",
         "src/core/lib/json/json_string.c",
         "src/core/lib/json/json_writer.c",
+        "src/core/lib/security/util/b64.c",
         "src/core/lib/slice/percent_encoding.c",
         "src/core/lib/slice/slice.c",
         "src/core/lib/slice/slice_buffer.c",
@@ -629,6 +630,7 @@ grpc_cc_library(
         "src/core/lib/json/json_common.h",
         "src/core/lib/json/json_reader.h",
         "src/core/lib/json/json_writer.h",
+        "src/core/lib/security/util/b64.h",
         "src/core/lib/slice/percent_encoding.h",
         "src/core/lib/slice/slice_hash_table.h",
         "src/core/lib/slice/slice_internal.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dac4095a5452ee515c4052ccee47c5aa45cfc902..c9d0098539df42bddbcb30bd31c882a9af9d37a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -993,6 +993,7 @@ add_library(grpc
   src/core/lib/json/json_reader.c
   src/core/lib/json/json_string.c
   src/core/lib/json/json_writer.c
+  src/core/lib/security/util/b64.c
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
@@ -1075,7 +1076,6 @@ add_library(grpc
   src/core/lib/security/transport/security_handshaker.c
   src/core/lib/security/transport/server_auth_filter.c
   src/core/lib/security/transport/tsi_error.c
-  src/core/lib/security/util/b64.c
   src/core/lib/security/util/json_util.c
   src/core/lib/surface/init_secure.c
   src/core/lib/tsi/fake_transport_security.c
@@ -1314,6 +1314,7 @@ add_library(grpc_cronet
   src/core/lib/json/json_reader.c
   src/core/lib/json/json_string.c
   src/core/lib/json/json_writer.c
+  src/core/lib/security/util/b64.c
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
@@ -1419,7 +1420,6 @@ add_library(grpc_cronet
   src/core/lib/security/transport/security_handshaker.c
   src/core/lib/security/transport/server_auth_filter.c
   src/core/lib/security/transport/tsi_error.c
-  src/core/lib/security/util/b64.c
   src/core/lib/security/util/json_util.c
   src/core/lib/surface/init_secure.c
   src/core/lib/tsi/fake_transport_security.c
@@ -1622,6 +1622,7 @@ add_library(grpc_test_util
   src/core/lib/json/json_reader.c
   src/core/lib/json/json_string.c
   src/core/lib/json/json_writer.c
+  src/core/lib/security/util/b64.c
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
@@ -1881,6 +1882,7 @@ add_library(grpc_unsecure
   src/core/lib/json/json_reader.c
   src/core/lib/json/json_string.c
   src/core/lib/json/json_writer.c
+  src/core/lib/security/util/b64.c
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
@@ -2511,6 +2513,7 @@ add_library(grpc++_cronet
   src/core/lib/json/json_reader.c
   src/core/lib/json/json_string.c
   src/core/lib/json/json_writer.c
+  src/core/lib/security/util/b64.c
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
diff --git a/Makefile b/Makefile
index 4985907f5c1e9d34f0906beb5d2100f231c642db..ddd1ffb19165092c541af464e901d7bd593e9384 100644
--- a/Makefile
+++ b/Makefile
@@ -2887,6 +2887,7 @@ LIBGRPC_SRC = \
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -2969,7 +2970,6 @@ LIBGRPC_SRC = \
     src/core/lib/security/transport/security_handshaker.c \
     src/core/lib/security/transport/server_auth_filter.c \
     src/core/lib/security/transport/tsi_error.c \
-    src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/lib/tsi/fake_transport_security.c \
@@ -3206,6 +3206,7 @@ LIBGRPC_CRONET_SRC = \
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -3311,7 +3312,6 @@ LIBGRPC_CRONET_SRC = \
     src/core/lib/security/transport/security_handshaker.c \
     src/core/lib/security/transport/server_auth_filter.c \
     src/core/lib/security/transport/tsi_error.c \
-    src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/lib/tsi/fake_transport_security.c \
@@ -3513,6 +3513,7 @@ LIBGRPC_TEST_UTIL_SRC = \
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -3744,6 +3745,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -4360,6 +4362,7 @@ LIBGRPC++_CRONET_SRC = \
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -18806,7 +18809,6 @@ src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/tsi_error.c: $(OPENSSL_DEP)
-src/core/lib/security/util/b64.c: $(OPENSSL_DEP)
 src/core/lib/security/util/json_util.c: $(OPENSSL_DEP)
 src/core/lib/surface/init_secure.c: $(OPENSSL_DEP)
 src/core/lib/tsi/fake_transport_security.c: $(OPENSSL_DEP)
diff --git a/binding.gyp b/binding.gyp
index 26904ae2f7b7d645714848bf2d2851df09b116d8..b91f5f61e21a367f346c9cd85b803a3f7b06e851 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -700,6 +700,7 @@
         'src/core/lib/json/json_reader.c',
         'src/core/lib/json/json_string.c',
         'src/core/lib/json/json_writer.c',
+        'src/core/lib/security/util/b64.c',
         'src/core/lib/slice/percent_encoding.c',
         'src/core/lib/slice/slice.c',
         'src/core/lib/slice/slice_buffer.c',
@@ -782,7 +783,6 @@
         'src/core/lib/security/transport/security_handshaker.c',
         'src/core/lib/security/transport/server_auth_filter.c',
         'src/core/lib/security/transport/tsi_error.c',
-        'src/core/lib/security/util/b64.c',
         'src/core/lib/security/util/json_util.c',
         'src/core/lib/surface/init_secure.c',
         'src/core/lib/tsi/fake_transport_security.c',
diff --git a/build.yaml b/build.yaml
index b11a3cf3190ed8d9de1deca2a7763a7364d4ff89..c0587331411c0b64a4065ae65b935b94dfd0d21c 100644
--- a/build.yaml
+++ b/build.yaml
@@ -369,6 +369,7 @@ filegroups:
   - src/core/lib/json/json_reader.c
   - src/core/lib/json/json_string.c
   - src/core/lib/json/json_writer.c
+  - src/core/lib/security/util/b64.c
   - src/core/lib/slice/percent_encoding.c
   - src/core/lib/slice/slice.c
   - src/core/lib/slice/slice_buffer.c
diff --git a/config.m4 b/config.m4
index 94e3ba1ab59e8ecf1abe32c17ad66f1143cb374b..b6f0bff7ef0bdb068c2a08425331ca04d408d583 100644
--- a/config.m4
+++ b/config.m4
@@ -168,6 +168,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/json/json_reader.c \
     src/core/lib/json/json_string.c \
     src/core/lib/json/json_writer.c \
+    src/core/lib/security/util/b64.c \
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
@@ -250,7 +251,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/lib/security/transport/security_handshaker.c \
     src/core/lib/security/transport/server_auth_filter.c \
     src/core/lib/security/transport/tsi_error.c \
-    src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
     src/core/lib/tsi/fake_transport_security.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index f9408ab1dbc1808f9bc49d1dbe6ee991dd34b668..8ea9e5fbdec53cb85a4b5ad854b0732b7732897f 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -543,6 +543,7 @@ Pod::Spec.new do |s|
                       'src/core/lib/json/json_reader.c',
                       'src/core/lib/json/json_string.c',
                       'src/core/lib/json/json_writer.c',
+                      'src/core/lib/security/util/b64.c',
                       'src/core/lib/slice/percent_encoding.c',
                       'src/core/lib/slice/slice.c',
                       'src/core/lib/slice/slice_buffer.c',
@@ -625,7 +626,6 @@ Pod::Spec.new do |s|
                       'src/core/lib/security/transport/security_handshaker.c',
                       'src/core/lib/security/transport/server_auth_filter.c',
                       'src/core/lib/security/transport/tsi_error.c',
-                      'src/core/lib/security/util/b64.c',
                       'src/core/lib/security/util/json_util.c',
                       'src/core/lib/surface/init_secure.c',
                       'src/core/lib/tsi/fake_transport_security.c',
diff --git a/grpc.gemspec b/grpc.gemspec
index 46097cb4e70ce3b391adfd036a6817f032c0b0ae..06da332bed5b5cb4ce3f30b321414aaee6f84b24 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -459,6 +459,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/json/json_reader.c )
   s.files += %w( src/core/lib/json/json_string.c )
   s.files += %w( src/core/lib/json/json_writer.c )
+  s.files += %w( src/core/lib/security/util/b64.c )
   s.files += %w( src/core/lib/slice/percent_encoding.c )
   s.files += %w( src/core/lib/slice/slice.c )
   s.files += %w( src/core/lib/slice/slice_buffer.c )
@@ -541,7 +542,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/lib/security/transport/security_handshaker.c )
   s.files += %w( src/core/lib/security/transport/server_auth_filter.c )
   s.files += %w( src/core/lib/security/transport/tsi_error.c )
-  s.files += %w( src/core/lib/security/util/b64.c )
   s.files += %w( src/core/lib/security/util/json_util.c )
   s.files += %w( src/core/lib/surface/init_secure.c )
   s.files += %w( src/core/lib/tsi/fake_transport_security.c )
diff --git a/package.xml b/package.xml
index f9407bb3edd21d78b563f5a0343e90cb8f248a70..5d585845556eb652f7bd812e02855eefe956de28 100644
--- a/package.xml
+++ b/package.xml
@@ -468,6 +468,7 @@
     <file baseinstalldir="/" name="src/core/lib/json/json_reader.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/json/json_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/json/json_writer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
@@ -550,7 +551,6 @@
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.c" role="src" />
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 028e9a5d04e0468779352e29b78638fc7dca31ca..967904df1eeb40d249b81f778b12f73a7f7f58ee 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -36,6 +36,7 @@
 #include <grpc/support/string_util.h>
 #include <string.h>
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/security/util/b64.h"
 #include "src/core/lib/slice/percent_encoding.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
@@ -56,7 +57,6 @@ typedef struct call_data {
   grpc_linked_mdelem te_trailers;
   grpc_linked_mdelem content_type;
   grpc_linked_mdelem user_agent;
-  grpc_linked_mdelem payload_bin;
 
   grpc_metadata_batch *recv_initial_metadata;
   grpc_metadata_batch *recv_trailing_metadata;
@@ -292,19 +292,58 @@ static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx,
       continue_send_message(exec_ctx, elem);
 
       if (calld->send_message_blocked == false) {
-        /* when all the send_message data is available, then create a MDELEM and
-        append to headers */
-        grpc_mdelem payload_bin = grpc_mdelem_from_slices(
-            exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
-            grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
-                                          op->send_message->length));
-        error =
-            grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
-                                         &calld->payload_bin, payload_bin);
+        /* when all the send_message data is available, then modify the path
+         * MDELEM by appending base64 encoded query to the path */
+        const int k_url_safe = 1;
+        const int k_multi_line = 0;
+        const unsigned char k_query_separator = '?';
+
+        grpc_slice path_slice =
+            GRPC_MDVALUE(op->send_initial_metadata->idx.named.path->md);
+        /* sum up individual component's lengths and allocate enough memory to
+         * hold combined path+query */
+        size_t estimated_len = GRPC_SLICE_LENGTH(path_slice);
+        estimated_len++; /* for the '?' */
+        estimated_len += grpc_base64_estimate_encoded_size(
+            op->send_message->length, k_url_safe, k_multi_line);
+        estimated_len += 1; /* for the trailing 0 */
+        grpc_slice path_with_query_slice = grpc_slice_malloc(estimated_len);
+
+        /* memcopy individual pieces into this slice */
+        uint8_t *write_ptr =
+            (uint8_t *)GRPC_SLICE_START_PTR(path_with_query_slice);
+        uint8_t *original_path = (uint8_t *)GRPC_SLICE_START_PTR(path_slice);
+        memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice));
+        write_ptr += GRPC_SLICE_LENGTH(path_slice);
+
+        *write_ptr = k_query_separator;
+        write_ptr++; /* for the '?' */
+
+        grpc_base64_encode_core((char *)write_ptr, calld->payload_bytes,
+                                op->send_message->length, k_url_safe,
+                                k_multi_line);
+
+        /* remove trailing unused memory and add trailing 0 to terminate string
+         */
+        char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice);
+        /* safe to use strlen since base64_encode will always add '\0' */
+        size_t path_length = strlen(t) + 1;
+        *(t + path_length) = '\0';
+        path_with_query_slice =
+            grpc_slice_sub(path_with_query_slice, 0, path_length);
+
+        /* substitute previous path with the new path+query */
+        grpc_mdelem mdelem_path_and_query = grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice);
+        grpc_metadata_batch *b = op->send_initial_metadata;
+        error = grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
+                                               mdelem_path_and_query);
         if (error != GRPC_ERROR_NONE) return error;
+
         calld->on_complete = op->on_complete;
         op->on_complete = &calld->hc_on_complete;
         op->send_message = NULL;
+        grpc_slice_unref_internal(exec_ctx, path_with_query_slice);
       } else {
         /* Not all data is available. Fall back to POST. */
         gpr_log(GPR_DEBUG,
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index 41a325bc04b6e5a866dee602176f46f0216bf2f2..8d3c488ea0ace4415f7888aec77ad422fdad4a74 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -37,6 +37,7 @@
 #include <grpc/support/log.h>
 #include <string.h>
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/security/util/b64.h"
 #include "src/core/lib/slice/percent_encoding.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
@@ -51,8 +52,8 @@ typedef struct call_data {
   grpc_linked_mdelem status;
   grpc_linked_mdelem content_type;
 
-  /* did this request come with payload-bin */
-  bool seen_payload_bin;
+  /* did this request come with path query containing request payload */
+  bool seen_path_with_query;
   /* flag to ensure payload_bin is delivered only once */
   bool payload_bin_delivered;
 
@@ -61,7 +62,7 @@ typedef struct call_data {
   bool *recv_cacheable_request;
   /** Closure to call when finished with the hs_on_recv hook */
   grpc_closure *on_done_recv;
-  /** Closure to call when we retrieve read message from the payload-bin header
+  /** Closure to call when we retrieve read message from the path URI
    */
   grpc_closure *recv_message_ready;
   grpc_closure *on_complete;
@@ -205,6 +206,43 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
               grpc_error_set_str(
                   GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
                   GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path")));
+  } else if (*calld->recv_cacheable_request == true) {
+    /* We have a cacheable request made with GET verb. The path contains the
+     * query parameter which is base64 encoded request payload. */
+    const char k_query_separator = '?';
+    grpc_slice path_slice = GRPC_MDVALUE(b->idx.named.path->md);
+    uint8_t *path_ptr = (uint8_t *)GRPC_SLICE_START_PTR(path_slice);
+    size_t path_length = GRPC_SLICE_LENGTH(path_slice);
+    /* offset of the character '?' */
+    size_t offset = 0;
+    for (offset = 0; *path_ptr != k_query_separator && offset < path_length;
+         path_ptr++, offset++)
+      ;
+    if (offset < path_length) {
+      grpc_slice query_slice =
+          grpc_slice_sub(path_slice, offset + 1, path_length);
+
+      /* substitute path metadata with just the path (not query) */
+      grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices(
+          exec_ctx, GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset));
+
+      grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
+                                     mdelem_path_without_query);
+
+      /* decode payload from query and add to the slice buffer to be returned */
+      const int k_url_safe = 1;
+      grpc_slice_buffer_add(
+          &calld->read_slice_buffer,
+          grpc_base64_decode(exec_ctx,
+                             (const char *)GRPC_SLICE_START_PTR(query_slice),
+                             k_url_safe));
+      grpc_slice_buffer_stream_init(&calld->read_stream,
+                                    &calld->read_slice_buffer, 0);
+      calld->seen_path_with_query = true;
+      grpc_slice_unref_internal(exec_ctx, query_slice);
+    } else {
+      gpr_log(GPR_ERROR, "GET request without QUERY");
+    }
   }
 
   if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
@@ -228,16 +266,6 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
             GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority")));
   }
 
-  if (b->idx.named.grpc_payload_bin != NULL) {
-    calld->seen_payload_bin = true;
-    grpc_slice_buffer_add(&calld->read_slice_buffer,
-                          grpc_slice_ref_internal(
-                              GRPC_MDVALUE(b->idx.named.grpc_payload_bin->md)));
-    grpc_slice_buffer_stream_init(&calld->read_stream,
-                                  &calld->read_slice_buffer, 0);
-    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_payload_bin);
-  }
-
   return error;
 }
 
@@ -258,8 +286,8 @@ static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
                            grpc_error *err) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
-  /* Call recv_message_ready if we got the payload via the header field */
-  if (calld->seen_payload_bin && calld->recv_message_ready != NULL) {
+  /* Call recv_message_ready if we got the payload via the path field */
+  if (calld->seen_path_with_query && calld->recv_message_ready != NULL) {
     *calld->pp_recv_message = calld->payload_bin_delivered
                                   ? NULL
                                   : (grpc_byte_stream *)&calld->read_stream;
@@ -274,7 +302,7 @@ static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
                                   grpc_error *err) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
-  if (calld->seen_payload_bin) {
+  if (calld->seen_path_with_query) {
     /* do nothing. This is probably a GET request, and payload will be returned
     in hs_on_complete callback. */
   } else {
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
index 09c821313162069aaaccaede30609d0d9447e5b6..0d5a9176602c876477e512c658cc95c2e6666960 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/security/util/b64.c
@@ -71,15 +71,31 @@ static const char base64_url_safe_chars[] =
 
 char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
                          int multiline) {
-  const unsigned char *data = vdata;
-  const char *base64_chars =
-      url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
+  size_t result_projected_size =
+      grpc_base64_estimate_encoded_size(data_size, url_safe, multiline);
+  char *result = gpr_malloc(result_projected_size);
+  grpc_base64_encode_core(result, vdata, data_size, url_safe, multiline);
+  return result;
+}
+
+size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe,
+                                         int multiline) {
   size_t result_projected_size =
       4 * ((data_size + 3) / 3) +
       2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS))
                      : 0) +
       1;
-  char *result = gpr_malloc(result_projected_size);
+  return result_projected_size;
+}
+
+void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size,
+                             int url_safe, int multiline) {
+  const unsigned char *data = vdata;
+  const char *base64_chars =
+      url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
+  const size_t result_projected_size =
+      grpc_base64_estimate_encoded_size(data_size, url_safe, multiline);
+
   char *current = result;
   size_t num_blocks = 0;
   size_t i = 0;
@@ -119,7 +135,6 @@ char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
   GPR_ASSERT(current >= result);
   GPR_ASSERT((uintptr_t)(current - result) < result_projected_size);
   result[current - result] = '\0';
-  return result;
 }
 
 grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
diff --git a/src/core/lib/security/util/b64.h b/src/core/lib/security/util/b64.h
index d42a136f61a2a85e4e02b3c316feb6caf3a4ca45..ef52291c6a45e32066d218c3287883ac8cab934a 100644
--- a/src/core/lib/security/util/b64.h
+++ b/src/core/lib/security/util/b64.h
@@ -37,10 +37,22 @@
 #include <grpc/slice.h>
 
 /* Encodes data using base64. It is the caller's responsability to free
-   the returned char * using gpr_free. Returns NULL on NULL input. */
+   the returned char * using gpr_free. Returns NULL on NULL input.
+   TODO(makdharma) : change the flags to bool from int */
 char *grpc_base64_encode(const void *data, size_t data_size, int url_safe,
                          int multiline);
 
+/* estimate the upper bound on size of base64 encoded data. The actual size
+ * is guaranteed to be less than or equal to the size returned here. */
+size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe,
+                                         int multiline);
+
+/* Encodes data using base64 and write it to memory pointed to by result. It is
+ * the caller's responsiblity to allocate enough memory in |result| to fit the
+ * encoded data. */
+void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size,
+                             int url_safe, int multiline);
+
 /* Decodes data according to the base64 specification. Returns an empty
    slice in case of failure. */
 grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 86445393cec25efa69ca1022d59458e2bcfacc07..258c65c08e983de01d219969ad48b181fa7a6270 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -162,6 +162,7 @@ CORE_SOURCE_FILES = [
   'src/core/lib/json/json_reader.c',
   'src/core/lib/json/json_string.c',
   'src/core/lib/json/json_writer.c',
+  'src/core/lib/security/util/b64.c',
   'src/core/lib/slice/percent_encoding.c',
   'src/core/lib/slice/slice.c',
   'src/core/lib/slice/slice_buffer.c',
@@ -244,7 +245,6 @@ CORE_SOURCE_FILES = [
   'src/core/lib/security/transport/security_handshaker.c',
   'src/core/lib/security/transport/server_auth_filter.c',
   'src/core/lib/security/transport/tsi_error.c',
-  'src/core/lib/security/util/b64.c',
   'src/core/lib/security/util/json_util.c',
   'src/core/lib/surface/init_secure.c',
   'src/core/lib/tsi/fake_transport_security.c',
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index e3190152447f88e378c62247cb07ccf1b041d851..61d3c5e88e9b1910256aed1007619b9fe707485c 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7787,6 +7787,7 @@
       "src/core/lib/json/json_string.c", 
       "src/core/lib/json/json_writer.c", 
       "src/core/lib/json/json_writer.h", 
+      "src/core/lib/security/util/b64.c", 
       "src/core/lib/slice/percent_encoding.c", 
       "src/core/lib/slice/percent_encoding.h", 
       "src/core/lib/slice/slice.c", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 0b2127f308c6489a424945b24e0219589fe5eb64..7abff218ddec49cdef951514ad7bfe6dadeb47a0 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -675,6 +675,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice.c">
@@ -839,8 +841,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init_secure.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 0a3c9c621d000b8d32cee6a10aa5639e79533592..aa3e5a77aa6b5a28d979a2ce97df15171ff35e3d 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -259,6 +259,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
       <Filter>src\core\lib\json</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -505,9 +508,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.c">
       <Filter>src\core\lib\security\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
-      <Filter>src\core\lib\security\util</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.c">
       <Filter>src\core\lib\security\util</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 04d6d9f55a32d0328b519eea885790d8a6f337fb..9f3743b238e6ced3942c7d8e70147b33883cc273 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -516,6 +516,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice.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 a2849888a14d12c5455acd9f846ce4ef008f57cd..bc52644206e7b70a7d9ff1280888617bb76cb930 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -316,6 +316,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
       <Filter>src\core\lib\json</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -941,6 +944,12 @@
     <Filter Include="src\core\lib\json">
       <UniqueIdentifier>{89bc8f83-e29a-ddab-8f6b-22df11cdc867}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\lib\security">
+      <UniqueIdentifier>{83d9c8a0-c579-769e-e2df-270c67b8c159}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\util">
+      <UniqueIdentifier>{d55417ff-35a3-ef69-80c4-e6a95673728b}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib\slice">
       <UniqueIdentifier>{4d172bbc-20c4-6e7d-872a-2d287b589aa0}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 86549398dc87d16bab7f6f4d89adeb8dea12d6cc..1a0c38cecbf921838b201f2aae7a80f2f38f415b 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -642,6 +642,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 625f276a55eefaeebfc0eaae09e2617a172ec680..b11766ecfd9448997628a52c58e8fe84a4b2eeb9 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -262,6 +262,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
       <Filter>src\core\lib\json</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
+      <Filter>src\core\lib\security\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -1352,6 +1355,12 @@
     <Filter Include="src\core\lib\json">
       <UniqueIdentifier>{681cdaeb-c47f-8853-d985-bf13c2873947}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\lib\security">
+      <UniqueIdentifier>{02c849c5-66eb-e42f-c9f7-2cf7cc9db06a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\lib\security\util">
+      <UniqueIdentifier>{c22aef1f-8b7b-6b5c-9e22-321b11f6352d}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\lib\slice">
       <UniqueIdentifier>{74c81ab7-e329-a362-3890-4c41b90f0511}</UniqueIdentifier>
     </Filter>