diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index a8e8ebe6ea92875441187a5ea7782bd902f19fb5..191cdd0e5fb02b82b5bd6a5d738fc5f1f4b896f5 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -148,11 +148,13 @@ typedef struct {
 /** Maximum number of concurrent incoming streams to allow on a http2
     connection. Int valued. */
 #define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams"
-/** Maximum message length that the channel can receive. Int valued, bytes. */
+/** Maximum message length that the channel can receive. Int valued, bytes.
+    -1 means unlimited. */
 #define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length"
 /** \deprecated For backward compatibility. */
 #define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
-/** Maximum message length that the channel can send. Int valued, bytes. */
+/** Maximum message length that the channel can send. Int valued, bytes.
+    -1 means unlimited. */
 #define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
 /** Initial sequence number for http2 transports. Int valued. */
 #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 6613785deaaa2450e58f2a100a450995d1850271..7528184d898dfe7d2197325694342f2c4caad27b 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -40,8 +40,9 @@
 
 #include "src/core/lib/channel/channel_args.h"
 
+#define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1  // Unlimited.
 // The protobuf library will (by default) start warning at 100 megs.
-#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024)
+#define DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024)
 
 typedef struct call_data {
   // Receive closures are chained: we inject this closure as the
@@ -55,8 +56,8 @@ typedef struct call_data {
 } call_data;
 
 typedef struct channel_data {
-  size_t max_send_size;
-  size_t max_recv_size;
+  long max_send_size;
+  long max_recv_size;
 } channel_data;
 
 // Callback invoked when we receive a message.  Here we check the max
@@ -66,7 +67,7 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
   grpc_call_element* elem = user_data;
   call_data* calld = elem->call_data;
   channel_data* chand = elem->channel_data;
-  if (*calld->recv_message != NULL &&
+  if (*calld->recv_message != NULL && chand->max_recv_size >= 0 &&
       (*calld->recv_message)->length > chand->max_recv_size) {
     char* message_string;
     gpr_asprintf(
@@ -88,7 +89,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx,
   call_data* calld = elem->call_data;
   channel_data* chand = elem->channel_data;
   // Check max send message size.
-  if (op->send_message != NULL &&
+  if (op->send_message != NULL && chand->max_send_size >= 0 &&
       op->send_message->length > chand->max_send_size) {
     char* message_string;
     gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)",
@@ -130,17 +131,20 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
   GPR_ASSERT(!args->is_last);
   channel_data* chand = elem->channel_data;
   memset(chand, 0, sizeof(*chand));
-  chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH;
-  chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH;
-  const grpc_integer_options options = {DEFAULT_MAX_MESSAGE_LENGTH, 0, INT_MAX};
+  chand->max_send_size = DEFAULT_MAX_SEND_MESSAGE_LENGTH;
+  chand->max_recv_size = DEFAULT_MAX_RECV_MESSAGE_LENGTH;
   for (size_t i = 0; i < args->channel_args->num_args; ++i) {
     if (strcmp(args->channel_args->args[i].key,
                GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
+      const grpc_integer_options options = {DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0,
+                                            INT_MAX};
       chand->max_send_size = (size_t)grpc_channel_arg_get_integer(
           &args->channel_args->args[i], options);
     }
     if (strcmp(args->channel_args->args[i].key,
                GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
+      const grpc_integer_options options = {DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0,
+                                            INT_MAX};
       chand->max_recv_size = (size_t)grpc_channel_arg_get_integer(
           &args->channel_args->args[i], options);
     }