diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 4aff315b7c..30becdeddb 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,6 +154,7 @@ GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
 									  pgfdw_inval_callback, (Datum) 0);
 		CacheRegisterSyscacheCallback(USERMAPPINGOID,
 									  pgfdw_inval_callback, (Datum) 0);
+		RegisterCheckingRemoteServersCallback(pgfdw_connection_check, NULL);
 	}
 
 	/* Set flag that we did GetConnection during the current transaction */
@@ -1638,3 +1640,66 @@ 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.
+ *
+ * Note that this might be expensive because create and wait
+ * eventset many times.
+ */
+void
+pgfdw_connection_check(void *args)
+{
+	HASH_SEQ_STATUS scan;
+	ConnCacheEntry *entry;
+
+	/* Exit immediately if hash is not initialized. */
+	if (!ConnectionHash)
+		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);
+			disconnect_pg_server(entry);
+			ereport(ERROR,
+					errcode(ERRCODE_CONNECTION_FAILURE),
+					errmsg("foreign server \"%s\"disconnected due to the health-check failure",
+							server->servername),
+					errdetail("Foreign server might be down."),
+					errhint("Please check the server and network health."));
+		}
+	}
+}
+
+/*
+ * helper fucntion for pgfdw_connection_check
+ */
+static bool
+pgfdw_connection_check_internal(PGconn *conn)
+{
+	WaitEventSet *eventset;
+	WaitEvent events;
+
+	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 90b72e9ec5..4630ca05d7 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,
