diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 475f8d11bc1702338e3e02fc84bda6458edc6fb9..6869c4de19e433528dac0f5ecb3eb91eaefa5677 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -175,7 +175,7 @@ template <int I>
 class CallNoOp {
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {}
-  void FinishOp(bool* status, int max_receive_message_size) {}
+  void FinishOp(bool* status) {}
 };
 
 class CallOpSendInitialMetadata {
@@ -213,7 +213,7 @@ class CallOpSendInitialMetadata {
     op->data.send_initial_metadata.maybe_compression_level.level =
         maybe_compression_level_.level;
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!send_) return;
     g_core_codegen_interface->gpr_free(initial_metadata_);
     send_ = false;
@@ -253,7 +253,7 @@ class CallOpSendMessage {
     // Flags are per-message: clear them after use.
     write_options_.Clear();
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
     send_buf_ = nullptr;
   }
@@ -301,14 +301,12 @@ class CallOpRecvMessage {
     op->data.recv_message.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (message_ == nullptr) return;
     if (recv_buf_) {
       if (*status) {
         got_message = *status =
-            SerializationTraits<R>::Deserialize(recv_buf_, message_,
-                                                max_receive_message_size)
-                .ok();
+            SerializationTraits<R>::Deserialize(recv_buf_, message_).ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -331,8 +329,7 @@ class CallOpRecvMessage {
 namespace CallOpGenericRecvMessageHelper {
 class DeserializeFunc {
  public:
-  virtual Status Deserialize(grpc_byte_buffer* buf,
-                             int max_receive_message_size) = 0;
+  virtual Status Deserialize(grpc_byte_buffer* buf) = 0;
   virtual ~DeserializeFunc() {}
 };
 
@@ -340,10 +337,8 @@ template <class R>
 class DeserializeFuncType final : public DeserializeFunc {
  public:
   DeserializeFuncType(R* message) : message_(message) {}
-  Status Deserialize(grpc_byte_buffer* buf,
-                     int max_receive_message_size) override {
-    return SerializationTraits<R>::Deserialize(buf, message_,
-                                               max_receive_message_size);
+  Status Deserialize(grpc_byte_buffer* buf) override {
+    return SerializationTraits<R>::Deserialize(buf, message_);
   }
 
   ~DeserializeFuncType() override {}
@@ -382,13 +377,12 @@ class CallOpGenericRecvMessage {
     op->data.recv_message.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!deserialize_) return;
     if (recv_buf_) {
       if (*status) {
         got_message = true;
-        *status =
-            deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
+        *status = deserialize_->Deserialize(recv_buf_).ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -422,7 +416,7 @@ class CallOpClientSendClose {
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_receive_message_size) { send_ = false; }
+  void FinishOp(bool* status) { send_ = false; }
 
  private:
   bool send_;
@@ -457,7 +451,7 @@ class CallOpServerSendStatus {
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!send_status_available_) return;
     g_core_codegen_interface->gpr_free(trailing_metadata_);
     send_status_available_ = false;
@@ -491,7 +485,7 @@ class CallOpRecvInitialMetadata {
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (recv_initial_metadata_ == nullptr) return;
     FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
     recv_initial_metadata_ = nullptr;
@@ -530,7 +524,7 @@ class CallOpClientRecvStatus {
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (recv_status_ == nullptr) return;
     FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
     *recv_status_ = Status(
@@ -567,22 +561,17 @@ class CallOpSetCollectionInterface
 /// API.
 class CallOpSetInterface : public CompletionQueueTag {
  public:
-  CallOpSetInterface() : max_receive_message_size_(0) {}
+  CallOpSetInterface() {}
   /// Fills in grpc_op, starting from ops[*nops] and moving
   /// upwards.
   virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
 
-  void set_max_receive_message_size(int max_receive_message_size) {
-    max_receive_message_size_ = max_receive_message_size;
-  }
-
   /// Mark this as belonging to a collection if needed
   void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
     collection_ = collection;
   }
 
  protected:
-  int max_receive_message_size_;
   std::shared_ptr<CallOpSetCollectionInterface> collection_;
 };
 
@@ -614,12 +603,12 @@ class CallOpSet : public CallOpSetInterface,
   }
 
   bool FinalizeResult(void** tag, bool* status) override {
-    this->Op1::FinishOp(status, max_receive_message_size_);
-    this->Op2::FinishOp(status, max_receive_message_size_);
-    this->Op3::FinishOp(status, max_receive_message_size_);
-    this->Op4::FinishOp(status, max_receive_message_size_);
-    this->Op5::FinishOp(status, max_receive_message_size_);
-    this->Op6::FinishOp(status, max_receive_message_size_);
+    this->Op1::FinishOp(status);
+    this->Op2::FinishOp(status);
+    this->Op3::FinishOp(status);
+    this->Op4::FinishOp(status);
+    this->Op5::FinishOp(status);
+    this->Op6::FinishOp(status);
     *tag = return_tag_;
     collection_.reset();  // drop the ref at this point
     return true;
@@ -651,35 +640,19 @@ class Call final {
  public:
   /* call is owned by the caller */
   Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
-      : call_hook_(call_hook),
-        cq_(cq),
-        call_(call),
-        max_receive_message_size_(-1) {}
-
-  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
-       int max_receive_message_size)
-      : call_hook_(call_hook),
-        cq_(cq),
-        call_(call),
-        max_receive_message_size_(max_receive_message_size) {}
+      : call_hook_(call_hook), cq_(cq), call_(call) {}
 
   void PerformOps(CallOpSetInterface* ops) {
-    if (max_receive_message_size_ > 0) {
-      ops->set_max_receive_message_size(max_receive_message_size_);
-    }
     call_hook_->PerformOpsOnCall(ops, this);
   }
 
   grpc_call* call() const { return call_; }
   CompletionQueue* cq() const { return cq_; }
 
-  int max_receive_message_size() { return max_receive_message_size_; }
-
  private:
   CallHook* call_hook_;
   CompletionQueue* cq_;
   grpc_call* call_;
-  int max_receive_message_size_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index d5d27e15cd6e81dc7663473afc0afbb781e43c09..83b569ce74fe83332d8b6752da04ea5ad8cce70b 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -52,8 +52,8 @@ class RpcMethodHandler : public MethodHandler {
 
   void RunHandler(const HandlerParameter& param) final {
     RequestType req;
-    Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_receive_message_size);
+    Status status =
+        SerializationTraits<RequestType>::Deserialize(param.request, &req);
     ResponseType rsp;
     if (status.ok()) {
       status = func_(service_, param.server_context, &req, &rsp);
@@ -138,8 +138,8 @@ class ServerStreamingHandler : public MethodHandler {
 
   void RunHandler(const HandlerParameter& param) final {
     RequestType req;
-    Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_receive_message_size);
+    Status status =
+        SerializationTraits<RequestType>::Deserialize(param.request, &req);
 
     if (status.ok()) {
       ServerWriter<ResponseType> writer(param.call, param.server_context);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index 2f154875916e2b13dd08d5047a3314c5ae0c4bac..2123b62ed9e17d64ad5abb784f1eb3c3eadd9891 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -203,8 +203,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
   }
 
   static Status Deserialize(grpc_byte_buffer* buffer,
-                            grpc::protobuf::Message* msg,
-                            int max_receive_message_size) {
+                            grpc::protobuf::Message* msg) {
     if (buffer == nullptr) {
       return Status(StatusCode::INTERNAL, "No payload");
     }
@@ -215,10 +214,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
         return reader.status();
       }
       ::grpc::protobuf::io::CodedInputStream decoder(&reader);
-      if (max_receive_message_size > 0) {
-        decoder.SetTotalBytesLimit(max_receive_message_size,
-                                   max_receive_message_size);
-      }
+      decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
       if (!msg->ParseFromCodedStream(&decoder)) {
         result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
       }
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 78c54e377115f9eda3af939846a1d5177c9eb494..eb8f9a1096eff3bd6474f0e10ecf0e8dd7d36dcb 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -57,17 +57,12 @@ class MethodHandler {
  public:
   virtual ~MethodHandler() {}
   struct HandlerParameter {
-    HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req,
-                     int max_size)
-        : call(c),
-          server_context(context),
-          request(req),
-          max_receive_message_size(max_size) {}
+    HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
+        : call(c), server_context(context), request(req) {}
     Call* call;
     ServerContext* server_context;
     // Handler required to grpc_byte_buffer_destroy this
     grpc_byte_buffer* request;
-    int max_receive_message_size;
   };
   virtual void RunHandler(const HandlerParameter& param) = 0;
 };
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 666b9ff66eb4f792384f240d1db7b77e05757278..752e493a9eba45356d88279351b794d23b9b43b9 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -199,9 +199,7 @@ class ServerInterface : public CallHook {
     bool FinalizeResult(void** tag, bool* status) override {
       bool serialization_status =
           *status && payload_ &&
-          SerializationTraits<Message>::Deserialize(
-              payload_, request_, server_->max_receive_message_size())
-              .ok();
+          SerializationTraits<Message>::Deserialize(payload_, request_).ok();
       bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
       *status = serialization_status && *status;
       return ret;
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index 4d9b074e95f92b8db5a7641b277813056cf5dfd1..1f7708bab94efbfc54110ceaa918bc32e53cb5f6 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -160,7 +160,7 @@ class ClientReader final : public ClientReaderInterface<R> {
   }
 
   bool NextMessageSize(uint32_t* sz) override {
-    *sz = call_.max_receive_message_size();
+    *sz = INT_MAX;
     return true;
   }
 
@@ -310,7 +310,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
   }
 
   bool NextMessageSize(uint32_t* sz) override {
-    *sz = call_.max_receive_message_size();
+    *sz = INT_MAX;
     return true;
   }
 
@@ -382,7 +382,7 @@ class ServerReader final : public ServerReaderInterface<R> {
   }
 
   bool NextMessageSize(uint32_t* sz) override {
-    *sz = call_->max_receive_message_size();
+    *sz = INT_MAX;
     return true;
   }
 
@@ -474,7 +474,7 @@ class ServerReaderWriterBody final {
   }
 
   bool NextMessageSize(uint32_t* sz) {
-    *sz = call_->max_receive_message_size();
+    *sz = INT_MAX;
     return true;
   }
 
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 1f317df6634eba7b0d2f6dab980b833e675b9813..064a03b977b874e815b0c1806a3f63a1931359c6 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -95,8 +95,7 @@ class ByteBuffer final {
 template <>
 class SerializationTraits<ByteBuffer, void> {
  public:
-  static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest,
-                            int max_receive_message_size) {
+  static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) {
     dest->set_buffer(byte_buffer);
     return Status::OK;
   }
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 817d85a81ca2da1da19b198638d7c306ac817b2e..7785a1f12412f3bee15afdaed1f5c17702c34a80 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -186,7 +186,7 @@ class Server::SyncRequest final : public CompletionQueueTag {
    public:
     explicit CallData(Server* server, SyncRequest* mrd)
         : cq_(mrd->cq_),
-          call_(mrd->call_, server, &cq_, server->max_receive_message_size_),
+          call_(mrd->call_, server, &cq_),
           ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
                mrd->request_metadata_.count),
           has_request_payload_(mrd->has_request_payload_),
@@ -208,8 +208,8 @@ class Server::SyncRequest final : public CompletionQueueTag {
     void Run(std::shared_ptr<GlobalCallbacks> global_callbacks) {
       ctx_.BeginCompletionOp(&call_);
       global_callbacks->PreSynchronousRequest(&ctx_);
-      method_->handler()->RunHandler(MethodHandler::HandlerParameter(
-          &call_, &ctx_, request_payload_, call_.max_receive_message_size()));
+      method_->handler()->RunHandler(
+          MethodHandler::HandlerParameter(&call_, &ctx_, request_payload_));
       global_callbacks->PostSynchronousRequest(&ctx_);
       request_payload_ = nullptr;
       void* ignored_tag;
@@ -598,7 +598,7 @@ bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
   grpc_metadata_array_destroy(&initial_metadata_array_);
   context_->set_call(call_);
   context_->cq_ = call_cq_;
-  Call call(call_, server_, call_cq_, server_->max_receive_message_size());
+  Call call(call_, server_, call_cq_);
   if (*status && call_) {
     context_->BeginCompletionOp(&call);
   }
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 1a1a94e87c74ffe43eaaad71cb7b71a83d80ea5f..edd56cef8861e603d30a7e9f8e094b3edab42064 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -891,6 +891,8 @@ TEST_P(End2endTest, RpcMaxMessageSize) {
   EchoRequest request;
   EchoResponse response;
   request.set_message(string(kMaxMessageSize_ * 2, 'a'));
+  // cancelled is not guaranteed to appear before the end of the service handler
+  request.mutable_param()->set_skip_cancelled_check(true);
 
   ClientContext context;
   Status s = stub_->Echo(&context, request, &response);