diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index b4abeed5ac978405d255e3b737e2d95494e8b184..5d6d031b4812450b94d2f9f75eae028b6a0fb199 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -1213,13 +1213,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 
 	PageRepairFragmentation(page);
 
-	/*
-	 * Now that we have removed the dead tuples from the page, once again
-	 * check if the page has become all-visible.
-	 */
-	if (heap_page_is_all_visible(onerel, buffer, &visibility_cutoff_xid))
-		PageSetAllVisible(page);
-
 	/*
 	 * Mark buffer dirty before we write WAL.
 	 */
@@ -1237,6 +1230,23 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 		PageSetLSN(page, recptr);
 	}
 
+	/*
+	 * End critical section, so we safely can do visibility tests (which
+	 * possibly need to perform IO and allocate memory!). If we crash now the
+	 * page (including the corresponding vm bit) might not be marked all
+	 * visible, but that's fine. A later vacuum will fix that.
+	 */
+	END_CRIT_SECTION();
+
+	/*
+	 * Now that we have removed the dead tuples from the page, once again
+	 * check if the page has become all-visible.  The page is already marked
+	 * dirty, exclusively locked, and, if needed, a full page image has been
+	 * emitted in the log_heap_clean() above.
+	 */
+	if (heap_page_is_all_visible(onerel, buffer, &visibility_cutoff_xid))
+		PageSetAllVisible(page);
+
 	/*
 	 * All the changes to the heap page have been done. If the all-visible
 	 * flag is now set, also set the VM bit.
@@ -1249,8 +1259,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 						  visibility_cutoff_xid);
 	}
 
-	END_CRIT_SECTION();
-
 	return tupindex;
 }