diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index ae446653a956a3b830d18013dd5e812c13448759..fa8d8a756ebc901850504ddb7b78a97db0e3dd3e 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -24,6 +24,7 @@
 #include "miscadmin.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
+#include "storage/indexfsm.h"
 
 /* GUC parameter */
 int			gin_pending_list_limit = 0;
@@ -521,10 +522,12 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
 		int64		nDeletedHeapTuples = 0;
 		ginxlogDeleteListPages data;
 		Buffer		buffers[GIN_NDELETE_AT_ONCE];
+		BlockNumber	freespace[GIN_NDELETE_AT_ONCE];
 
 		data.ndeleted = 0;
 		while (data.ndeleted < GIN_NDELETE_AT_ONCE && blknoToDelete != newHead)
 		{
+			freespace[data.ndeleted] = blknoToDelete;
 			buffers[data.ndeleted] = ReadBuffer(index, blknoToDelete);
 			LockBuffer(buffers[data.ndeleted], GIN_EXCLUSIVE);
 			page = BufferGetPage(buffers[data.ndeleted]);
@@ -609,6 +612,10 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
 			UnlockReleaseBuffer(buffers[i]);
 
 		END_CRIT_SECTION();
+
+		for (i = 0; i < data.ndeleted; i++)
+			RecordFreeIndexPage(index, freespace[i]);
+
 	} while (blknoToDelete != newHead);
 
 	return false;
@@ -744,6 +751,7 @@ ginInsertCleanup(GinState *ginstate,
 	BuildAccumulator accum;
 	KeyArray	datums;
 	BlockNumber blkno;
+	bool		fsm_vac = false;
 
 	metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
 	LockBuffer(metabuffer, GIN_SHARE);
@@ -793,6 +801,7 @@ ginInsertCleanup(GinState *ginstate,
 		{
 			/* another cleanup process is running concurrently */
 			UnlockReleaseBuffer(buffer);
+			fsm_vac = false;
 			break;
 		}
 
@@ -857,6 +866,7 @@ ginInsertCleanup(GinState *ginstate,
 				/* another cleanup process is running concurrently */
 				UnlockReleaseBuffer(buffer);
 				LockBuffer(metabuffer, GIN_UNLOCK);
+				fsm_vac = false;
 				break;
 			}
 
@@ -895,9 +905,13 @@ ginInsertCleanup(GinState *ginstate,
 			{
 				/* another cleanup process is running concurrently */
 				LockBuffer(metabuffer, GIN_UNLOCK);
+				fsm_vac = false;
 				break;
 			}
 
+			/* At this point, some pending pages have been freed up */
+			fsm_vac = true;
+
 			Assert(blkno == metadata->head);
 			LockBuffer(metabuffer, GIN_UNLOCK);
 
@@ -931,6 +945,15 @@ ginInsertCleanup(GinState *ginstate,
 
 	ReleaseBuffer(metabuffer);
 
+	/*
+	 * As pending list pages can have a high churn rate, it is
+	 * desirable to recycle them immediately to the FreeSpace Map when
+	 * ordinary backends clean the list.
+	 */
+	if (fsm_vac && !vac_delay)
+		IndexFreeSpaceMapVacuum(index);
+
+
 	/* Clean up temporary space */
 	MemoryContextSwitchTo(oldCtx);
 	MemoryContextDelete(opCtx);