diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 3894f4a270..a9c0090eef 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -168,6 +168,8 @@ static bool IsCheckpointOnSchedule(double progress);
 static bool ImmediateCheckpointRequested(void);
 static bool CompactCheckpointerRequestQueue(void);
 static void UpdateSharedMemoryConfig(void);
+static void pgstat_beshutdown_hook(int code, Datum arg);
+static void pgstat_send_checkpointer(void);
 
 /* Signal handlers */
 static void ReqCheckpointHandler(SIGNAL_ARGS);
@@ -187,6 +189,9 @@ CheckpointerMain(void)
 
 	CheckpointerShmem->checkpointer_pid = MyProcPid;
 
+	/* Arrange to send statistics to the stats collector at checkpointer exit */
+	on_shmem_exit(pgstat_beshutdown_hook, 0);
+
 	/*
 	 * Properly accept or ignore signals the postmaster might send us
 	 *
@@ -495,17 +500,8 @@ CheckpointerMain(void)
 		/* Check for archive_timeout and switch xlog files if necessary. */
 		CheckArchiveTimeout();
 
-		/*
-		 * Send off activity statistics to the stats collector.  (The reason
-		 * why we re-use bgwriter-related code for this is that the bgwriter
-		 * and checkpointer used to be just one process.  It's probably not
-		 * worth the trouble to split the stats support into two independent
-		 * stats message types.)
-		 */
-		pgstat_send_bgwriter();
-
-		/* Send WAL statistics to the stats collector. */
-		pgstat_report_wal();
+		/* Send statistics to the stats collector */
+		pgstat_send_checkpointer();
 
 		/*
 		 * If any checkpoint flags have been set, redo the loop to handle the
@@ -1313,6 +1309,35 @@ UpdateSharedMemoryConfig(void)
 	elog(DEBUG2, "checkpointer updated shared memory configuration values");
 }
 
+/*
+ * Flush any remaining statistics counts for the checkpointer out to
+ * the collector at process exits
+ */
+static void
+pgstat_beshutdown_hook(int code, Datum arg)
+{
+	pgstat_send_checkpointer();
+}
+
+/*
+ * Send the statistics for the checkpointer to the stats collector
+ */
+static void
+pgstat_send_checkpointer(void)
+{
+	/*
+	 * Send off activity statistics to the stats collector.  (The reason why
+	 * we re-use bgwriter-related code for this is that the bgwriter and
+	 * checkpointer used to be just one process.  It's probably not worth the
+	 * trouble to split the stats support into two independent stats message
+	 * types.)
+	 */
+	pgstat_send_bgwriter();
+
+	/* Send WAL statistics to the stats collector. */
+	pgstat_report_wal();
+}
+
 /*
  * FirstCallSinceLastCheckpoint allows a process to take an action once
  * per checkpoint cycle by asynchronously checking for checkpoint completion.
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 132df29aba..55cd0154bd 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -78,6 +78,9 @@ int			WalWriterFlushAfter = 128;
 #define LOOPS_UNTIL_HIBERNATE		50
 #define HIBERNATE_FACTOR			25
 
+/* Prototypes for private functions */
+static void pgstat_beshutdown_hook(int code, Datum arg);
+
 /*
  * Main entry point for walwriter process
  *
@@ -92,6 +95,9 @@ WalWriterMain(void)
 	int			left_till_hibernate;
 	bool		hibernating;
 
+	/* Arrange to send statistics to the stats collector at walwriter exit */
+	on_shmem_exit(pgstat_beshutdown_hook, 0);
+
 	/*
 	 * Properly accept or ignore signals the postmaster might send us
 	 *
@@ -272,3 +278,14 @@ WalWriterMain(void)
 						 WAIT_EVENT_WAL_WRITER_MAIN);
 	}
 }
+
+/*
+ * Flush any remaining statistics counts for the walwriter out to
+ * the collector at process exits
+ */
+static void
+pgstat_beshutdown_hook(int code, Datum arg)
+{
+	/* Send WAL statistics to the stats collector */
+	pgstat_send_wal(false);
+}
