diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h
index 9a14faa7fa691c83bb54c6dc4df64dc5c7018e4f..47fd6cf1c85911f16fb7bf8bf3df1264c29fef0f 100644
--- a/include/grpc++/server_context.h
+++ b/include/grpc++/server_context.h
@@ -34,12 +34,16 @@
 #ifndef __GRPCPP_SERVER_CONTEXT_H_
 #define __GRPCPP_SERVER_CONTEXT_H_
 
+#include <chrono>
+
 namespace grpc {
 
 // Interface of server side rpc context.
 class ServerContext {
  public:
   virtual ~ServerContext() {}
+
+  virtual std::chrono::system_clock::time_point absolute_deadline() const = 0;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/server/server_context_impl.cc b/src/cpp/server/server_context_impl.cc
index a229fcb6c99189f448cc1f7ac641c8a076f60ceb..13f2a3ae1ac0d151e58012195416b4b39c6ce96c 100644
--- a/src/cpp/server/server_context_impl.cc
+++ b/src/cpp/server/server_context_impl.cc
@@ -35,6 +35,4 @@
 
 namespace grpc {
 
-ServerContextImpl::ServerContextImpl() {}
-
 }  // namespace grpc
diff --git a/src/cpp/server/server_context_impl.h b/src/cpp/server/server_context_impl.h
index 58c4293b4f70302d37b49a76985e34ba7c1f99ae..c6016b763575027273a72a3f404a1aefb1ffaec2 100644
--- a/src/cpp/server/server_context_impl.h
+++ b/src/cpp/server/server_context_impl.h
@@ -36,12 +36,24 @@
 
 #include <grpc++/server_context.h>
 
+#include <chrono>
+
+#include <grpc/support/time.h>
+
 namespace grpc {
 
 class ServerContextImpl : public ServerContext {
  public:
-  ServerContextImpl();
+  explicit ServerContextImpl(std::chrono::system_clock::time_point deadline)
+      : absolute_deadline_(deadline) {}
   ~ServerContextImpl() {}
+
+  std::chrono::system_clock::time_point absolute_deadline() const {
+    return absolute_deadline_;
+  }
+
+ private:
+  std::chrono::system_clock::time_point absolute_deadline_;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/server/server_rpc_handler.cc b/src/cpp/server/server_rpc_handler.cc
index c32722f81ade04139b57580a0a541b475de4ae8d..3954f04f978ebcc9a44020d5e9fa423679d06302 100644
--- a/src/cpp/server/server_rpc_handler.cc
+++ b/src/cpp/server/server_rpc_handler.cc
@@ -53,7 +53,7 @@ void ServerRpcHandler::StartRpc() {
     return;
   }
 
-  ServerContextImpl user_context;
+  ServerContextImpl user_context(async_server_context_->absolute_deadline());
 
   if (method_->method_type() == RpcMethod::NORMAL_RPC) {
     // Start the rpc on this dedicated completion queue.
diff --git a/src/cpp/util/time.cc b/src/cpp/util/time.cc
index 6976fa1b32155379ece88bc8da5d5679ee16dcde..e58dde82a3ea775ac909d331bac51d6dd34a774c 100644
--- a/src/cpp/util/time.cc
+++ b/src/cpp/util/time.cc
@@ -53,6 +53,9 @@ void Timepoint2Timespec(const system_clock::time_point& from,
 }
 
 system_clock::time_point Timespec2Timepoint(gpr_timespec t) {
+  if (gpr_time_cmp(t, gpr_inf_future) == 0) {
+    return system_clock::time_point::max();
+  }
   system_clock::time_point tp;
   tp += duration_cast<system_clock::time_point::duration>(seconds(t.tv_sec));
   tp +=
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 4b5a9a8e6afa27743497947a31c9e03574af2089..83037b5ab1836ff201e83e861ecda3dc830ade1d 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -31,10 +31,12 @@
  *
  */
 
+#include <chrono>
 #include <thread>
-#include "src/cpp/server/rpc_service_method.h"
+
 #include "test/cpp/util/echo.pb.h"
-#include "net/util/netutil.h"
+#include "src/cpp/server/rpc_service_method.h"
+#include "src/cpp/util/time.h"
 #include <grpc++/channel_arguments.h>
 #include <grpc++/channel_interface.h>
 #include <grpc++/client_context.h>
@@ -44,22 +46,43 @@
 #include <grpc++/server_context.h>
 #include <grpc++/status.h>
 #include <grpc++/stream.h>
+#include "net/util/netutil.h"
 #include <gtest/gtest.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/thd.h>
+#include <grpc/support/time.h>
 
 using grpc::cpp::test::util::EchoRequest;
 using grpc::cpp::test::util::EchoResponse;
 using grpc::cpp::test::util::TestService;
+using std::chrono::system_clock;
 
 namespace grpc {
+namespace testing {
+
+namespace {
+
+// When echo_deadline is requested, deadline seen in the ServerContext is set in
+// the response in seconds.
+void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
+                       EchoResponse* response) {
+  if (request->has_param() && request->param().echo_deadline()) {
+    gpr_timespec deadline = gpr_inf_future;
+    if (context->absolute_deadline() != system_clock::time_point::max()) {
+      Timepoint2Timespec(context->absolute_deadline(), &deadline);
+    }
+    response->mutable_param()->set_request_deadline(deadline.tv_sec);
+  }
+}
+}  // namespace
 
 class TestServiceImpl : public TestService::Service {
  public:
   Status Echo(ServerContext* context, const EchoRequest* request,
               EchoResponse* response) {
     response->set_message(request->message());
+    MaybeEchoDeadline(context, request, response);
     return Status::OK;
   }
 
@@ -179,6 +202,71 @@ TEST_F(End2endTest, RpcDeadlineExpires) {
   delete stub;
 }
 
+// Set a long but finite deadline.
+TEST_F(End2endTest, RpcLongDeadline) {
+  std::shared_ptr<ChannelInterface> channel =
+      CreateChannel(server_address_.str(), ChannelArguments());
+  TestService::Stub* stub = TestService::NewStub(channel);
+  EchoRequest request;
+  EchoResponse response;
+  request.set_message("Hello");
+
+  ClientContext context;
+  std::chrono::system_clock::time_point deadline =
+      std::chrono::system_clock::now() + std::chrono::hours(1);
+  context.set_absolute_deadline(deadline);
+  Status s = stub->Echo(&context, request, &response);
+  EXPECT_EQ(response.message(), request.message());
+  EXPECT_TRUE(s.IsOk());
+
+  delete stub;
+}
+
+// Ask server to echo back the deadline it sees.
+TEST_F(End2endTest, EchoDeadline) {
+  std::shared_ptr<ChannelInterface> channel =
+      CreateChannel(server_address_.str(), ChannelArguments());
+  TestService::Stub* stub = TestService::NewStub(channel);
+  EchoRequest request;
+  EchoResponse response;
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_deadline(true);
+
+  ClientContext context;
+  std::chrono::system_clock::time_point deadline =
+      std::chrono::system_clock::now() + std::chrono::seconds(100);
+  context.set_absolute_deadline(deadline);
+  Status s = stub->Echo(&context, request, &response);
+  EXPECT_EQ(response.message(), request.message());
+  EXPECT_TRUE(s.IsOk());
+  gpr_timespec sent_deadline;
+  Timepoint2Timespec(deadline, &sent_deadline);
+  // Allow 1 second error.
+  EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1);
+  EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1);
+
+  delete stub;
+}
+
+// Ask server to echo back the deadline it sees. The rpc has no deadline.
+TEST_F(End2endTest, EchoDeadlineForNoDeadlineRpc) {
+  std::shared_ptr<ChannelInterface> channel =
+      CreateChannel(server_address_.str(), ChannelArguments());
+  TestService::Stub* stub = TestService::NewStub(channel);
+  EchoRequest request;
+  EchoResponse response;
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_deadline(true);
+
+  ClientContext context;
+  Status s = stub->Echo(&context, request, &response);
+  EXPECT_EQ(response.message(), request.message());
+  EXPECT_TRUE(s.IsOk());
+  EXPECT_EQ(response.param().request_deadline(), gpr_inf_future.tv_sec);
+
+  delete stub;
+}
+
 TEST_F(End2endTest, UnimplementedRpc) {
   std::shared_ptr<ChannelInterface> channel =
       CreateChannel(server_address_.str(), ChannelArguments());
@@ -300,6 +388,7 @@ TEST_F(End2endTest, BidiStream) {
   delete stub;
 }
 
+}  // namespace testing
 }  // namespace grpc
 
 int main(int argc, char** argv) {
diff --git a/test/cpp/util/echo.proto b/test/cpp/util/echo.proto
index abce7ad03a6d70470f1bf5d89f8c622d268b4d20..1240399bf88df3c013854db73358d37ebdbf2e9c 100644
--- a/test/cpp/util/echo.proto
+++ b/test/cpp/util/echo.proto
@@ -2,12 +2,22 @@ syntax = "proto2";
 
 package grpc.cpp.test.util;
 
+message RequestParams {
+  optional bool echo_deadline = 1;
+}
+
 message EchoRequest {
   optional string message = 1;
+  optional RequestParams param = 2;
+}
+
+message ResponseParams {
+  optional int64 request_deadline = 1;
 }
 
 message EchoResponse {
   optional string message = 1;
+  optional ResponseParams param = 2;
 }
 
 service TestService {
@@ -15,6 +25,5 @@ service TestService {
   rpc RequestStream(stream EchoRequest) returns (EchoResponse);
   rpc ResponseStream(EchoRequest) returns (stream EchoResponse);
   rpc BidiStream(stream EchoRequest) returns (stream EchoResponse);
-  rpc Unimplemented(EchoRequest) returns (EchoResponse) {
-  }
+  rpc Unimplemented(EchoRequest) returns (EchoResponse);
 }
diff --git a/test/cpp/util/time_test.cc b/test/cpp/util/time_test.cc
index 97499fed28ac3273bce45ae662ffb709722b1df5..c5718086331585747ccac8705c2a58958d16463c 100644
--- a/test/cpp/util/time_test.cc
+++ b/test/cpp/util/time_test.cc
@@ -62,5 +62,11 @@ TEST_F(TimeTest, AbsolutePointTest) {
   EXPECT_TRUE(tp == tp_converted_2);
 }
 
+// gpr_inf_future is treated specially and mapped to time_point::max()
+TEST_F(TimeTest, InfFuture) {
+  EXPECT_EQ(system_clock::time_point::max(),
+            Timespec2Timepoint(gpr_inf_future));
+}
+
 }  // namespace
 }  // namespace grpc