diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 0d494e2..20c0424 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -433,6 +433,11 @@ typedef struct XLogCtlData
 	Latch		recoveryWakeupLatch;
 
 	/*
+	 * WALWriterLatch is used to wake up the WALWriter to write some WAL.
+	 */
+	Latch		WALWriterLatch;
+
+	/*
 	 * During recovery, we keep a copy of the latest checkpoint record here.
 	 * Used by the background writer when it wants to create a restartpoint.
 	 *
@@ -1916,19 +1921,35 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
 }
 
 /*
- * Record the LSN for an asynchronous transaction commit/abort.
+ * Record the LSN for an asynchronous transaction commit/abort
+ * and nudge the WALWriter if there is a complete page to write.
  * (This should not be called for for synchronous commits.)
  */
 void
 XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
 {
+	XLogRecPtr	WriteRqstPtr = asyncXactLSN;
+
 	/* use volatile pointer to prevent code rearrangement */
 	volatile XLogCtlData *xlogctl = XLogCtl;
 
 	SpinLockAcquire(&xlogctl->info_lck);
+	LogwrtResult = xlogctl->LogwrtResult;
 	if (XLByteLT(xlogctl->asyncXactLSN, asyncXactLSN))
 		xlogctl->asyncXactLSN = asyncXactLSN;
 	SpinLockRelease(&xlogctl->info_lck);
+
+	/* back off to last completed page boundary */
+	WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
+
+	/* if we have already flushed that far, we're done */
+	if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
+		return;
+
+	/*
+	 * Nudge the WALWriter if we have a full page of WAL to write.
+	 */
+	SetLatch(&XLogCtl->WALWriterLatch);
 }
 
 /*
@@ -5072,6 +5093,7 @@ XLOGShmemInit(void)
 	XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
 	SpinLockInit(&XLogCtl->info_lck);
 	InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
+	InitSharedLatch(&XLogCtl->WALWriterLatch);
 
 	/*
 	 * If we are not in bootstrap mode, pg_control should already exist. Read
@@ -10013,3 +10035,12 @@ WakeupRecovery(void)
 {
 	SetLatch(&XLogCtl->recoveryWakeupLatch);
 }
+
+/*
+ * Manage the WALWriterLatch
+ */
+Latch *
+WALWriterLatch(void)
+{
+	return &XLogCtl->WALWriterLatch;
+}
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 23c4aac..157728e 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -11,7 +11,8 @@
  *
  * Note that as with the bgwriter for shared buffers, regular backends are
  * still empowered to issue WAL writes and fsyncs when the walwriter doesn't
- * keep up.
+ * keep up. This means that the WALWriter is not an essential process and
+ * can shutdown quickly when requested.
  *
  * Because the walwriter's cycle is directly linked to the maximum delay
  * before async-commit transactions are guaranteed committed, it's probably
@@ -76,7 +77,6 @@ static void wal_quickdie(SIGNAL_ARGS);
 static void WalSigHupHandler(SIGNAL_ARGS);
 static void WalShutdownHandler(SIGNAL_ARGS);
 
-
 /*
  * Main entry point for walwriter process
  *
@@ -89,6 +89,8 @@ WalWriterMain(void)
 	sigjmp_buf	local_sigjmp_buf;
 	MemoryContext walwriter_context;
 
+	InitLatch(WALWriterLatch()); /* initialize latch used in main loop */
+
 	/*
 	 * If possible, make this process a group leader, so that the postmaster
 	 * can signal any child processes too.	(walwriter probably never has any
@@ -220,7 +222,7 @@ WalWriterMain(void)
 	 */
 	for (;;)
 	{
-		long		udelay;
+		ResetLatch(WALWriterLatch());
 
 		/*
 		 * Emergency bailout if postmaster has died.  This is to avoid the
@@ -248,20 +250,9 @@ WalWriterMain(void)
 		 */
 		XLogBackgroundFlush();
 
-		/*
-		 * Delay until time to do something more, but fall out of delay
-		 * reasonably quickly if signaled.
-		 */
-		udelay = WalWriterDelay * 1000L;
-		while (udelay > 999999L)
-		{
-			if (got_SIGHUP || shutdown_requested)
-				break;
-			pg_usleep(1000000L);
-			udelay -= 1000000L;
-		}
-		if (!(got_SIGHUP || shutdown_requested))
-			pg_usleep(udelay);
+		(void) WaitLatch(WALWriterLatch(),
+							   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
+							   WalWriterDelay /* ms */);
 	}
 }
 
@@ -308,6 +299,7 @@ static void
 WalSigHupHandler(SIGNAL_ARGS)
 {
 	got_SIGHUP = true;
+	SetLatch(WALWriterLatch());
 }
 
 /* SIGTERM: set flag to exit normally */
@@ -315,4 +307,5 @@ static void
 WalShutdownHandler(SIGNAL_ARGS)
 {
 	shutdown_requested = true;
+	SetLatch(WALWriterLatch());
 }
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 83106b8..6344a85 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -16,6 +16,7 @@
 #include "datatype/timestamp.h"
 #include "lib/stringinfo.h"
 #include "storage/buf.h"
+#include "storage/latch.h"
 #include "utils/pg_crc.h"
 
 /*
@@ -319,6 +320,7 @@ extern TimeLineID GetRecoveryTargetTLI(void);
 
 extern bool CheckPromoteSignal(void);
 extern void WakeupRecovery(void);
+extern Latch *WALWriterLatch(void);
 
 /*
  * Starting/stopping a base backup
