diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8a7c560..f06d345 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4745,9 +4745,11 @@ RelationGetIndexPredicate(Relation relation)
  * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
  * we can include system attributes (e.g., OID) in the bitmap representation.
  *
- * Caller had better hold at least RowExclusiveLock on the target relation
- * to ensure that it has a stable set of indexes.  This also makes it safe
- * (deadlock-free) for us to take locks on the relation's indexes.
+ * While all callers should at least RowExclusiveLock on the target relation,
+ * we still can't guarantee a stable set of indexes because CREATE INDEX
+ * CONCURRENTLY and DROP INDEX CONCURRENTLY can change set of indexes, without
+ * taking any conflicting lock. So we must be prepared to handle changes in the
+ * set of indexes and recompute bitmaps, when necessary.
  *
  * The returned result is palloc'd in the caller's memory context and should
  * be bms_free'd when not needed anymore.
@@ -4787,6 +4789,7 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
 	if (!RelationGetForm(relation)->relhasindex)
 		return NULL;
 
+recheck:
 	/*
 	 * Get cached list of index OIDs
 	 */
@@ -4798,15 +4801,16 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
 
 	/*
 	 * Copy the rd_pkindex and rd_replidindex value computed by
-	 * RelationGetIndexList before proceeding.  This is needed because a
-	 * relcache flush could occur inside index_open below, resetting the
-	 * fields managed by RelationGetIndexList. (The values we're computing
-	 * will still be valid, assuming that caller has a sufficient lock on
-	 * the relation.)
+	 * RelationGetIndexList before proceeding. If a relcache flush could occur
+	 * inside index_open below, resetting the fields managed by
+	 * RelationGetIndexList, we compare the old and new values and recompute
+	 * attribute maps again.
 	 */
 	relpkindex = relation->rd_pkindex;
 	relreplindex = relation->rd_replidindex;
 
+	Assert(relation->rd_indexvalid != 0);
+
 	/*
 	 * For each index, add referenced attributes to indexattrs.
 	 *
@@ -4882,6 +4886,30 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
 
 	list_free(indexoidlist);
 
+	/*
+	 * If a relcache flush happened during index_open, we may have computed
+	 * stale values of the bitmaps since we used the old information. Since all
+	 * these bitmaps are closely tied with the index list as well as other
+	 * information such as the primary index and the replica identity, we must
+	 * recompute everything. Otherwise we could be end up with a wrongly cached
+	 * values of these bitmaps.
+	 *
+	 * Note that a subsequent call to RelationGetIndexList() will reload the
+	 * new list of indexes, but that does not invalidate the cached attribute
+	 * bitmaps. So we handle that here itself.
+	 */
+	if (relpkindex != relation->rd_pkindex ||
+		relreplindex != relation->rd_replidindex ||
+		relation->rd_indexvalid == 0)
+	{
+		bms_free(uindexattrs);
+		bms_free(pkindexattrs);
+		bms_free(idindexattrs);
+		bms_free(indexattrs);
+
+		goto recheck;
+	}
+
 	/* Don't leak the old values of these bitmaps, if any */
 	bms_free(relation->rd_indexattr);
 	relation->rd_indexattr = NULL;
