diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 4b16fb5682..9093af42bd 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -69,16 +69,18 @@
  *
  *	  After commit we are called another time (AtCommit_Notify()). Here we
  *	  make the actual updates to the effective listen state (listenChannels).
+ *	  Also we check if we need to signal listening backends.  In
+ *	  SignalBackends() we scan the list of listening backends and send a
+ *	  PROCSIG_NOTIFY_INTERRUPT signal to every listening backend (we don't know
+ *	  which backend is listening on which channel so we must signal them all).
+ *	  We can exclude backends that are already up to date, though, and we can
+ *	  also exclude backends that are in other databases (unless they are way
+ *	  behind and should be kicked to make them advance their pointers).
+ *	  We don't bother with a self-signal either.
  *
  *	  Finally, after we are out of the transaction altogether, we check if
- *	  we need to signal listening backends.  In SignalBackends() we scan the
- *	  list of listening backends and send a PROCSIG_NOTIFY_INTERRUPT signal
- *	  to every listening backend (we don't know which backend is listening on
- *	  which channel so we must signal them all). We can exclude backends that
- *	  are already up to date, though, and we can also exclude backends that
- *	  are in other databases (unless they are way behind and should be kicked
- *	  to make them advance their pointers).  We don't bother with a
- *	  self-signal either, but just process the queue directly.
+ *	  we need to send out self-notifies.  In ProcessCompletedNotifies() we just
+ *	  process the queue directly.
  *
  * 5. Upon receipt of a PROCSIG_NOTIFY_INTERRUPT signal, the signal handler
  *	  sets the process's latch, which triggers the event to be processed
@@ -984,7 +986,9 @@ PreCommit_Notify(void)
  *
  *		This is called at transaction commit, after committing to clog.
  *
- *		Update listenChannels and clear transaction-local state.
+ *		Update listenChannels and clear transaction-local state.  If we issued
+ *		any notifications in the transaction, send signals to other backends to
+ *		process them.
  */
 void
 AtCommit_Notify(void)
@@ -1027,6 +1031,13 @@ AtCommit_Notify(void)
 	if (amRegisteredListener && listenChannels == NIL)
 		asyncQueueUnregister();
 
+	/*
+	 * Send signals to other backends. We call SignalBackends() only if there
+	 * are pending notifies which are added to the queue by PreCommit_Notify().
+	 */
+	if (pendingNotifies != NULL)
+		SignalBackends();
+
 	/* And clean up */
 	ClearPendingActionsAndNotifies();
 }
@@ -1200,14 +1211,13 @@ Exec_UnlistenAllCommit(void)
 }
 
 /*
- * ProcessCompletedNotifies --- send out signals and self-notifies
+ * ProcessCompletedNotifies --- send out self-notifies
  *
  * This is called from postgres.c just before going idle at the completion
  * of a transaction.  If we issued any notifications in the just-completed
- * transaction, send signals to other backends to process them, and also
- * process the queue ourselves to send messages to our own frontend.
- * Also, if we filled enough queue pages with new notifies, try to advance
- * the queue tail pointer.
+ * transaction, process the queue ourselves to send messages to our own
+ * frontend.  Also, if we filled enough queue pages with new notifies, try to
+ * advance the queue tail pointer.
  *
  * The reason that this is not done in AtCommit_Notify is that there is
  * a nonzero chance of errors here (for example, encoding conversion errors
@@ -1216,9 +1226,8 @@ Exec_UnlistenAllCommit(void)
  * to ensure that a transaction's self-notifies are delivered to the frontend
  * before it gets the terminating ReadyForQuery message.
  *
- * Note that we send signals and process the queue even if the transaction
- * eventually aborted.  This is because we need to clean out whatever got
- * added to the queue.
+ * Note that we process the queue even if the transaction eventually aborted.
+ * This is because we need to clean out whatever got added to the queue.
  *
  * NOTE: we are outside of any transaction here.
  */
@@ -1253,9 +1262,6 @@ ProcessCompletedNotifies(void)
 	 */
 	StartTransactionCommand();
 
-	/* Send signals to other backends */
-	SignalBackends();
-
 	if (listenChannels != NIL)
 	{
 		/* Read the queue ourselves, and send relevant stuff to the frontend */
@@ -1658,7 +1664,8 @@ asyncQueueFillWarning(void)
 /*
  * Send signals to listening backends.
  *
- * We never signal our own process; that should be handled by our caller.
+ * We never signal our own process; that should be handled by
+ * ProcessCompletedNotifies().
  *
  * Normally we signal only backends in our own database, since only those
  * backends could be interested in notifies we send.  However, if there's
@@ -2268,6 +2275,7 @@ ProcessIncomingNotify(void)
 	/* We *must* reset the flag */
 	notifyInterruptPending = false;
 
+
 	/* Do nothing else if we aren't actively listening */
 	if (listenChannels == NIL)
 		return;
