diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 33b5ca2..ac8d62b 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -37,6 +37,8 @@
 #include "access/transam.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "storage/procarray.h"
+#include "utils/snapmgr.h"
 
 /*
  * Defines for CLOG page sizes.  A page is the same BLCKSZ as is used
@@ -691,6 +693,41 @@ CLOGPagePrecedes(int page1, int page2)
 
 
 /*
+ * Write dirty CLOG pages that won't receive any more updates.
+ *
+ * Return true if we do any work, and false otherwise.
+ */
+bool
+BackgroundWriteCLOG()
+{
+	int			pageno;
+	bool		result;
+	static SnapshotData DummySnapshotData;
+
+	/*
+	 * Compute cutoff page - i.e. the point before which we don't expect to
+	 * do any more writes.  During recovery it may not be possible to compute
+	 * a snapshot, so we just skip it in that case.  (There might be a way
+	 * to improve this.)
+	 */
+	if (RecoveryInProgress())
+		return false;
+	GetSnapshotData(&DummySnapshotData);
+	pageno = TransactionIdToPage(RecentXmin);
+
+	/*
+	 * The actual write is done by the SLRU code, but we must acquire the
+	 * lock first.
+	 */
+	LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
+	result = SimpleLruBackgroundFlush(ClogCtl, pageno);
+	LWLockRelease(CLogControlLock);
+
+	return result;
+}
+
+
+/*
  * Write a ZEROPAGE xlog record
  */
 static void
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index a8e3f19..6f9b993 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -1091,6 +1091,42 @@ SimpleLruFlush(SlruCtl ctl, bool checkpoint)
 }
 
 /*
+ * Write out a dirty page, if there's one that precedes the cutoff point.
+ *
+ * The intention here is that pageno should be chosen so that no further writes
+ * are expected in any preceding page.  That way, we won't do background writes
+ * of pages that will be re-dirtied.
+ */
+bool
+SimpleLruBackgroundFlush(SlruCtl ctl, int pageno)
+{
+	SlruShared	shared = ctl->shared;
+	int			slotno;
+	int			target_slot = -1;
+	int			target_page = pageno;
+
+	/* Find the oldest valid, dirty page before the cutoff point. */
+	for (slotno = 0; slotno < shared->num_slots; slotno++)
+	{
+		if (shared->page_status[slotno] == SLRU_PAGE_VALID &&
+			shared->page_dirty[slotno] &&
+			ctl->PagePrecedes(shared->page_number[slotno], target_page))
+		{
+			target_slot = slotno;
+			target_page = shared->page_number[slotno];
+		}
+	}
+
+	/* No qualifying pages, so indicate that there's no work to be done. */
+	if (target_slot == -1)
+		return false;
+
+	/* Write the page. */
+	SlruInternalWritePage(ctl, target_slot, NULL);
+	return true;
+}
+
+/*
  * Remove all segments before the one holding the passed page number
  */
 void
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 59c539a..971f03f 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -42,6 +42,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include "access/clog.h"
 #include "access/xlog_internal.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
@@ -285,6 +286,10 @@ BackgroundWriterMain(void)
 			ResetLatch(&MyProc->procLatch);
 		lapped = BgBufferSync();
 
+		/* Consider writing old CLOG pages. */
+		if (BackgroundWriteCLOG())
+			lapped = false;
+
 		if (lapped && !hibernating)
 		{
 			/*
diff --git a/src/include/access/clog.h b/src/include/access/clog.h
index bed3b8c..577df43 100644
--- a/src/include/access/clog.h
+++ b/src/include/access/clog.h
@@ -40,6 +40,7 @@ extern void StartupCLOG(void);
 extern void TrimCLOG(void);
 extern void ShutdownCLOG(void);
 extern void CheckPointCLOG(void);
+extern bool BackgroundWriteCLOG(void);
 extern void ExtendCLOG(TransactionId newestXact);
 extern void TruncateCLOG(TransactionId oldestXact);
 
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 41cd484..52dfe31 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -143,6 +143,7 @@ extern int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
 extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno,
 						   TransactionId xid);
 extern void SimpleLruWritePage(SlruCtl ctl, int slotno);
+extern bool SimpleLruBackgroundFlush(SlruCtl ctl, int pageno);
 extern void SimpleLruFlush(SlruCtl ctl, bool checkpoint);
 extern void SimpleLruTruncate(SlruCtl ctl, int cutoffPage);
 
