diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 58d432a9af1..ff802708e0d 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11827,6 +11827,59 @@ SELECT o.x FROM (VALUES (2505), (3505)) o(x), LATERAL (SELECT a FROM async_pt WH
  3505
 (2 rows)
 
+-- Test rescanning an async Append that has both a child ready for a new
+-- request and a child waiting for another Append using the same connection.
+CREATE VIEW base_tbl2_slow AS
+  WITH delay AS MATERIALIZED (SELECT pg_sleep(0.1))
+  SELECT t.* FROM base_tbl2 t, delay;
+ALTER FOREIGN TABLE async_p2 OPTIONS (SET table_name 'base_tbl2_slow');
+SET statement_timeout = '10s';
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT o.a AS outer_a, i.a AS inner_a
+FROM (SELECT a FROM async_pt LIMIT 2) o,
+LATERAL (SELECT a FROM async_pt WHERE a >= o.a LIMIT 1) i;
+                                           QUERY PLAN                                           
+------------------------------------------------------------------------------------------------
+ Nested Loop
+   Output: async_pt.a, async_pt_4.a
+   ->  Limit
+         Output: async_pt.a
+         ->  Append
+               ->  Async Foreign Scan on public.async_p1 async_pt_1
+                     Output: async_pt_1.a
+                     Remote SQL: SELECT a FROM public.base_tbl1
+               ->  Async Foreign Scan on public.async_p2 async_pt_2
+                     Output: async_pt_2.a
+                     Remote SQL: SELECT a FROM public.base_tbl2_slow
+               ->  Async Foreign Scan on public.async_p3 async_pt_3
+                     Output: async_pt_3.a
+                     Remote SQL: SELECT a FROM public.base_tbl3
+   ->  Limit
+         Output: async_pt_4.a
+         ->  Append
+               ->  Async Foreign Scan on public.async_p1 async_pt_5
+                     Output: async_pt_5.a
+                     Remote SQL: SELECT a FROM public.base_tbl1 WHERE ((a >= $1::integer))
+               ->  Async Foreign Scan on public.async_p2 async_pt_6
+                     Output: async_pt_6.a
+                     Remote SQL: SELECT a FROM public.base_tbl2_slow WHERE ((a >= $1::integer))
+               ->  Async Foreign Scan on public.async_p3 async_pt_7
+                     Output: async_pt_7.a
+                     Remote SQL: SELECT a FROM public.base_tbl3 WHERE ((a >= $1::integer))
+(26 rows)
+
+SELECT o.a AS outer_a, i.a AS inner_a
+FROM (SELECT a FROM async_pt LIMIT 2) o,
+LATERAL (SELECT a FROM async_pt WHERE a >= o.a LIMIT 1) i;
+ outer_a | inner_a 
+---------+---------
+    1000 |    1000
+    1005 |    1005
+(2 rows)
+
+RESET statement_timeout;
+ALTER FOREIGN TABLE async_p2 OPTIONS (SET table_name 'base_tbl2');
+DROP VIEW base_tbl2_slow;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 525a6ff394f..bdde6dffe97 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -4065,6 +4065,26 @@ EXPLAIN (VERBOSE, COSTS OFF)
 SELECT o.x FROM (VALUES (2505), (3505)) o(x), LATERAL (SELECT a FROM async_pt WHERE (a = 1505 AND o.x = 2505) OR a = o.x LIMIT 1) s ORDER BY o.x;
 SELECT o.x FROM (VALUES (2505), (3505)) o(x), LATERAL (SELECT a FROM async_pt WHERE (a = 1505 AND o.x = 2505) OR a = o.x LIMIT 1) s ORDER BY o.x;
 
+-- Test rescanning an async Append that has both a child ready for a new
+-- request and a child waiting for another Append using the same connection.
+CREATE VIEW base_tbl2_slow AS
+  WITH delay AS MATERIALIZED (SELECT pg_sleep(0.1))
+  SELECT t.* FROM base_tbl2 t, delay;
+ALTER FOREIGN TABLE async_p2 OPTIONS (SET table_name 'base_tbl2_slow');
+SET statement_timeout = '10s';
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT o.a AS outer_a, i.a AS inner_a
+FROM (SELECT a FROM async_pt LIMIT 2) o,
+LATERAL (SELECT a FROM async_pt WHERE a >= o.a LIMIT 1) i;
+SELECT o.a AS outer_a, i.a AS inner_a
+FROM (SELECT a FROM async_pt LIMIT 2) o,
+LATERAL (SELECT a FROM async_pt WHERE a >= o.a LIMIT 1) i;
+
+RESET statement_timeout;
+ALTER FOREIGN TABLE async_p2 OPTIONS (SET table_name 'base_tbl2');
+DROP VIEW base_tbl2_slow;
+
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 692f73171e5..83f4497d227 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -1145,6 +1145,15 @@ ExecAppendAsyncReset(AppendState *node)
 	{
 		bool		found = false;
 
+		/*
+		 * Discard results and new-request markers generated by the old scan.
+		 * Do this on every iteration, since callbacks invoked below can add them
+		 * again, and FDWs may use as_needrequest when configuring wait events.
+		 */
+		node->as_nasyncresults = 0;
+		bms_free(node->as_needrequest);
+		node->as_needrequest = NULL;
+
 		i = -1;
 		while ((i = bms_next_member(node->as_asyncplans, i)) >= 0)
 		{
@@ -1178,10 +1187,7 @@ ExecAppendAsyncReset(AppendState *node)
 		areq->result = NULL;
 	}
 
-	node->as_nasyncresults = 0;
 	node->as_nasyncremain = 0;
-	bms_free(node->as_needrequest);
-	node->as_needrequest = NULL;
 }
 
 /* ----------------------------------------------------------------
