diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml
index a48f75ad7b..e2b0016e18 100644
--- a/doc/src/sgml/ref/vacuum.sgml
+++ b/doc/src/sgml/ref/vacuum.sgml
@@ -207,6 +207,16 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="paramet
       for tables that do not have an index and is ignored if the
       <literal>FULL</literal> option is used.
      </para>
+
+     <note>
+       <para>
+         When performing an aggressive vacuum, <command>VACUUM</command>
+         doesn't skip index cleanup phase even if
+         <literal>INDEX_CLEANUP</literal> is set to false.  Therefore, index
+         cleanup phase is performed depending on the result of
+         <xref linkend="guc-vacuum-cleanup-index-scale-factor"/> check.
+       </para>
+     </note>
     </listitem>
    </varlistentry>
 
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 3bef0e124b..cef92e38cf 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -332,7 +332,7 @@ static BufferAccessStrategy vac_strategy;
 /* non-export function prototypes */
 static void lazy_scan_heap(Relation onerel, VacuumParams *params,
 						   LVRelStats *vacrelstats, Relation *Irel, int nindexes,
-						   bool aggressive);
+						   bool aggressive, bool xid_wrap);
 static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
 static bool lazy_check_needs_freeze(Buffer buf, bool *hastup);
 static void lazy_vacuum_all_indexes(Relation onerel, Relation *Irel,
@@ -416,6 +416,7 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
 	int			usecs;
 	double		read_rate,
 				write_rate;
+	bool		xid_wrap;
 	bool		aggressive;		/* should we scan all unfrozen pages? */
 	bool		scanned_all_unfrozen;	/* actually scanned all such pages? */
 	TransactionId xidFullScanLimit;
@@ -466,10 +467,11 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
 	 * table's minimum MultiXactId is older than or equal to the requested
 	 * mxid full-table scan limit; or if DISABLE_PAGE_SKIPPING was specified.
 	 */
-	aggressive = TransactionIdPrecedesOrEquals(onerel->rd_rel->relfrozenxid,
-											   xidFullScanLimit);
-	aggressive |= MultiXactIdPrecedesOrEquals(onerel->rd_rel->relminmxid,
-											  mxactFullScanLimit);
+	xid_wrap = TransactionIdPrecedesOrEquals(onerel->rd_rel->relfrozenxid,
+												 xidFullScanLimit);
+	xid_wrap |= MultiXactIdPrecedesOrEquals(onerel->rd_rel->relminmxid,
+												mxactFullScanLimit);
+	aggressive = xid_wrap;
 	if (params->options & VACOPT_DISABLE_PAGE_SKIPPING)
 		aggressive = true;
 
@@ -507,7 +509,8 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
 	error_context_stack = &errcallback;
 
 	/* Do the vacuuming */
-	lazy_scan_heap(onerel, params, vacrelstats, Irel, nindexes, aggressive);
+	lazy_scan_heap(onerel, params, vacrelstats, Irel, nindexes, aggressive,
+				   xid_wrap);
 
 	/* Done with indexes */
 	vac_close_indexes(nindexes, Irel, NoLock);
@@ -749,7 +752,7 @@ vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats)
  */
 static void
 lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
-			   Relation *Irel, int nindexes, bool aggressive)
+			   Relation *Irel, int nindexes, bool aggressive, bool xid_wrap)
 {
 	LVParallelState *lps = NULL;
 	LVDeadTuples *dead_tuples;
@@ -1695,8 +1698,13 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
 	/* report all blocks vacuumed */
 	pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno);
 
-	/* Do post-vacuum cleanup */
-	if (vacrelstats->useindex)
+	/*
+	 * Do post-vacuum cleanup.  If this vacuum scan is for avoiding XID wraparound,
+	 * we do index cleanup even if INDEX_CLEANUP is disabled.  Index AM such as
+	 * btree has an XID in recyclable pages and we need to process those pages
+	 * before XID wraparound.  Otherwise we would miss those recyclable pages.
+	 */
+	if (vacrelstats->useindex || (nindexes > 0 && xid_wrap))
 		lazy_cleanup_all_indexes(Irel, indstats, vacrelstats, lps, nindexes);
 
 	/*
