diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index c1d1b6b2db..32f95360f2 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1249,6 +1249,27 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       </listitem>
      </varlistentry>
 
+     <varlistentry id="socket_timeout" xreflabel="socket_timeout">
+      <term><literal>socket_timeout</literal></term>
+      <listitem>
+       <para>
+        Number of seconds to wait for socket read/write operation before
+        closing the connection, as a decimal integer. This can be used as a
+        stop-gap timeout mean. A value of zero (the default) turns this off,
+        which means wait indefinitely. The minimum allowed timeout is
+        2 seconds, so a value of 1 is interpreted as 2.
+       </para>
+       <note>
+        <para>
+         It is recommended to set greater than the value of other timeout paramters,
+         <literal>connect_timeout</literal>, <literal>statement_timeout</literal>,
+         <literal>TCP_KEEP_ALIVES</literal>, <literal>TCP_USER_TIMEOUT</literal>
+         because setting smaller value can cause not desirable disconnection.
+        </para>
+       </note>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="libpq-connect-tty" xreflabel="tty">
       <term><literal>tty</literal></term>
       <listitem>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index e3bf6a7449..df8d7fe6a9 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -208,6 +208,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"Connect-timeout", "", 10,	/* strlen(INT32_MAX) == 10 */
 	offsetof(struct pg_conn, connect_timeout)},
 
+	{"socket_timeout", NULL, NULL, NULL,
+		"Socket-timeout", "", 10,   /* strlen(INT32_MAX) == 10 */
+	offsetof(struct pg_conn, pgsocket_timeout)},
+
 	{"dbname", "PGDATABASE", NULL, NULL,
 		"Database-Name", "", 20,
 	offsetof(struct pg_conn, dbName)},
@@ -405,6 +409,8 @@ static char *passwordFromFile(const char *hostname, const char *port, const char
 				 const char *username, const char *pgpassfile);
 static void pgpassfileWarning(PGconn *conn);
 static void default_threadlock(int acquire);
+static bool parse_int_param(const char *value, int *result, PGconn *conn,
+				 const char *context);
 
 
 /* global variable because fe-auth.c needs to access it */
@@ -1238,6 +1244,22 @@ connectOptions2(PGconn *conn)
 			goto oom_error;
 	}
 
+	if (conn->pgsocket_timeout)
+	{
+		if (parse_int_param(conn->pgsocket_timeout,
+			&conn->socket_timeout, conn, "socket_timeout"))
+		{
+			/*
+			 * Rounding could cause communication to fail;
+			 * insist on at least two seconds.
+			 */
+			if(conn->socket_timeout > 0 && conn->socket_timeout < 2)
+				conn->socket_timeout = 2;
+		}
+		else
+			goto iiv_error;
+	}
+
 	/*
 	 * Validate target_session_attrs option.
 	 */
@@ -1268,6 +1290,12 @@ oom_error:
 	printfPQExpBuffer(&conn->errorMessage,
 					  libpq_gettext("out of memory\n"));
 	return false;
+
+iiv_error:
+	conn->status = CONNECTION_BAD;
+	printfPQExpBuffer(&conn->errorMessage,
+					  libpq_gettext("invalid integer value for socket_timeout\n"));
+	return false;
 }
 
 /*
@@ -3655,6 +3683,8 @@ freePGconn(PGconn *conn)
 		free(conn->pgtty);
 	if (conn->connect_timeout)
 		free(conn->connect_timeout);
+	if (conn->pgsocket_timeout)
+		free(conn->pgsocket_timeout);
 	if (conn->pgoptions)
 		free(conn->pgoptions);
 	if (conn->appname)
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index ea4c9d2ee0..633430b54e 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -1020,6 +1020,32 @@ pqFlush(PGconn *conn)
 int
 pqWait(int forRead, int forWrite, PGconn *conn)
 {
+	int result;
+
+	if (conn->socket_timeout > 0)
+	{
+		time_t		finish_time;
+
+		finish_time = time(NULL) + conn->socket_timeout;
+		result = pqSocketCheck(conn, forRead, forWrite, finish_time);
+
+		if (result < 0)
+			return EOF;
+
+		if (result == 0)
+		{
+			printfPQExpBuffer(&conn->errorMessage,
+					libpq_gettext("timeout expired\n"));
+			conn->status = CONNECTION_BAD;
+			pqsecure_close(conn);
+			closesocket(conn->sock);
+			conn->sock = -1;
+			return EOF;
+		}
+
+		return 0;
+	}
+
 	return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
 }
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index dbe0f7e5c0..5addc2e746 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -336,6 +336,7 @@ struct pg_conn
 	char	   *pgtty;			/* tty on which the backend messages is
 								 * displayed (OBSOLETE, NOT USED) */
 	char	   *connect_timeout;	/* connection timeout (numeric string) */
+	char	   *pgsocket_timeout;	/* socket timeout (numeric string) */
 	char	   *client_encoding_initial;	/* encoding to use */
 	char	   *pgoptions;		/* options to start the backend with */
 	char	   *appname;		/* application name */
@@ -502,6 +503,7 @@ struct pg_conn
 
 	/* Buffer for receiving various parts of messages */
 	PQExpBufferData workBuffer; /* expansible string */
+	int			socket_timeout;		/* socket timeout (numeric)*/
 };
 
 /* PGcancel stores all data necessary to cancel a connection. A copy of this
