diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 29fcb6a76e..10316d2f10 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -109,6 +109,7 @@ static void pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql,
 								bool toplevel);
 static bool UserMappingPasswordRequired(UserMapping *user);
 static bool disconnect_cached_connections(Oid serverid);
+static bool pgfdw_connection_check_internal(PGconn *conn);
 
 /*
  * Get a PGconn which can be used to execute queries on the remote PostgreSQL
@@ -153,11 +154,17 @@ GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
 									  pgfdw_inval_callback, (Datum) 0);
 		CacheRegisterSyscacheCallback(USERMAPPINGOID,
 									  pgfdw_inval_callback, (Datum) 0);
+
+		/* Register a callback fore checking remote servers */
+		RegisterCheckingRemoteServersCallback(pgfdw_connection_check, NULL);
 	}
 
 	/* Set flag that we did GetConnection during the current transaction */
 	xact_got_connection = true;
 
+	/* Start checking timer */
+	EnableForeignCheckTimeout();
+
 	/* Create hash key for the entry.  Assume no pad bytes in key struct */
 	key = user->umid;
 
@@ -1709,3 +1716,71 @@ disconnect_cached_connections(Oid serverid)
 
 	return result;
 }
+
+/*
+ * Callback function for checking remote servers.
+ *
+ * This function searches the hash table from the beginning
+ * and performs a health-check on each entry.
+ *
+ * Raise SIGINT if someone might be down, otherwise do nothing.
+ */
+void
+pgfdw_connection_check(void *args)
+{
+	HASH_SEQ_STATUS scan;
+	ConnCacheEntry *entry;
+
+	/* Exit immediately if hash is not initialized. */
+	if (!ConnectionHash)
+		return;
+
+	/*
+	 * checking will be done by waiting WL_SOCKET_CLOSED event,
+	 * so exit immediately if it cannot be used in this system.
+	 */
+	if (!WaitEventSetCanReportClosed())
+		return;
+
+	hash_seq_init(&scan, ConnectionHash);
+	while ((entry = (ConnCacheEntry *) hash_seq_search(&scan)))
+	{
+		if (entry->conn == NULL || entry->xact_depth == 0)
+			continue;
+		if (!pgfdw_connection_check_internal(entry->conn))
+		{
+			ForeignServer *server = GetForeignServer(entry->serverid);
+			elog(LOG, "Foreign Server %s might be down.", server->servername);
+			disconnect_pg_server(entry);
+			raise(SIGINT);
+		}
+	}
+
+	return;
+}
+
+/*
+ * helper function for pgfdw_connection_check
+ */
+static bool
+pgfdw_connection_check_internal(PGconn *conn)
+{
+	WaitEventSet *eventset;
+	WaitEvent events;
+
+	Assert(WaitEventSetCanReportClosed());
+
+	eventset = CreateWaitEventSet(CurrentMemoryContext, 1);
+	AddWaitEventToSet(eventset, WL_SOCKET_CLOSED, PQsocket(conn), NULL, NULL);
+
+	WaitEventSetWait(eventset, 0, &events, 1, 0);
+
+	if (events.events & WL_SOCKET_CLOSED)
+	{
+		FreeWaitEventSet(eventset);
+		return false;
+	}
+	FreeWaitEventSet(eventset);
+
+	return true;
+}
diff --git a/contrib/postgres_fdw/postgres_fdw.h b/contrib/postgres_fdw/postgres_fdw.h
index 8ae79e97e4..0f4f4641c6 100644
--- a/contrib/postgres_fdw/postgres_fdw.h
+++ b/contrib/postgres_fdw/postgres_fdw.h
@@ -151,6 +151,7 @@ extern PGresult *pgfdw_exec_query(PGconn *conn, const char *query,
 								  PgFdwConnState *state);
 extern void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn,
 							   bool clear, const char *sql);
+extern void pgfdw_connection_check(void *args);
 
 /* in option.c */
 extern int	ExtractConnectionOptions(List *defelems,
diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml
index 2bb31f1125..228f4629a5 100644
--- a/doc/src/sgml/postgres-fdw.sgml
+++ b/doc/src/sgml/postgres-fdw.sgml
@@ -774,6 +774,16 @@ postgres=# SELECT postgres_fdw_disconnect_all();
    connections that are no longer necessary, thereby releasing
    connections on the foreign server.
   </para>
+
+  <para>
+   During a remote transaction, postgres_fdw checks the health of used connections
+   if <xref linkend="guc-remote-servers-connection-check-interval"/> sets to
+   greater than zero. When losing a remote connection is detected,
+   the running transaction is aborted. Note that this feature is performed
+   by polling the socket, and available platforms are the
+   same as <xref linkend="guc-client-connection-check-interval"/>.
+  </para>
+
  </sect2>
 
  <sect2>
