diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index d078501814c7a55f6fadac59b2da56921893e3cb..0ad6804e55204355849faa3da273ec3fac7eb6b7 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -315,6 +315,16 @@ StartReplication(StartReplicationCmd * cmd)
 {
 	StringInfoData buf;
 
+	/*
+	 * Let postmaster know that we're streaming. Once we've declared us as
+	 * a WAL sender process, postmaster will let us outlive the bgwriter and
+	 * kill us last in the shutdown sequence, so we get a chance to stream
+	 * all remaining WAL at shutdown, including the shutdown checkpoint.
+	 * Note that there's no going back, and we mustn't write any WAL records
+	 * after this.
+	 */
+	MarkPostmasterChildWalSender();
+
 	/*
 	 * Check that we're logging enough information in the WAL for
 	 * log-shipping.
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index 155bd751bf2ce6f194a7a0f9024af16ba83bafd8..391d6a6ea046e45b88a8c9bd3d47ea7e25fa18e7 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -49,6 +49,8 @@
  *
  * Actually there is a fourth state, WALSENDER.  This is just like ACTIVE,
  * but carries the extra information that the child is a WAL sender.
+ * WAL senders too start in ACTIVE state, but switch to WALSENDER once they
+ * start streaming the WAL (and they never go back to ACTIVE after that).
  */
 
 #define PM_CHILD_UNUSED		0	/* these values must fit in sig_atomic_t */
@@ -225,8 +227,25 @@ MarkPostmasterChildActive(void)
 	Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
 	slot--;
 	Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
-	PMSignalState->PMChildFlags[slot] =
-		(am_walsender ? PM_CHILD_WALSENDER : PM_CHILD_ACTIVE);
+	PMSignalState->PMChildFlags[slot] = PM_CHILD_ACTIVE;
+}
+
+/*
+ * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender
+ * process.  This is called in the child process, sometime after marking the
+ * child as active.
+ */
+void
+MarkPostmasterChildWalSender(void)
+{
+	int			slot = MyPMChildSlot;
+
+	Assert(am_walsender);
+
+	Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
+	slot--;
+	Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ACTIVE);
+	PMSignalState->PMChildFlags[slot] = PM_CHILD_WALSENDER;
 }
 
 /*
diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h
index 2deff728ecd3e38fcfa0a8de5b4ac9f677b21e7a..97bdc7bc86d7f5d78e8ede1eee4edd8742e94ad8 100644
--- a/src/include/storage/pmsignal.h
+++ b/src/include/storage/pmsignal.h
@@ -48,6 +48,7 @@ extern bool ReleasePostmasterChildSlot(int slot);
 extern bool IsPostmasterChildWalSender(int slot);
 extern void MarkPostmasterChildActive(void);
 extern void MarkPostmasterChildInactive(void);
+extern void MarkPostmasterChildWalSender(void);
 extern bool PostmasterIsAlive(bool amDirectChild);
 
 #endif   /* PMSIGNAL_H */