diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 0f661f5010c7685282afb892ee17b300c5e9b4bc..a2ad5ebfe82b1d0287ad200a10b990862dc4c6c0 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7254,10 +7254,9 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
 }
 
 /*
- * This must be called during startup of a backend process, except that
- * it need not be called in a standalone backend (which does StartupXLOG
- * instead).  We need to initialize the local copies of ThisTimeLineID and
- * RedoRecPtr.
+ * This must be called in a backend process before creating WAL records
+ * (except in a standalone backend, which does StartupXLOG instead).  We need
+ * to initialize the local copies of ThisTimeLineID and RedoRecPtr.
  *
  * Note: before Postgres 8.0, we went to some effort to keep the postmaster
  * process's copies of ThisTimeLineID and RedoRecPtr valid too.  This was
@@ -7594,6 +7593,16 @@ CreateCheckPoint(int flags)
 	if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
 		elog(ERROR, "can't create a checkpoint during recovery");
 
+	/*
+	 * Initialize InitXLogInsert working areas before entering the critical
+	 * section.  Normally, this is done by the first call to
+	 * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
+	 * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
+	 * done below in a critical section, and InitXLogInsert cannot be called
+	 * in a critical section.
+	 */
+	InitXLogInsert();
+
 	/*
 	 * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
 	 * (This is just pro forma, since in the present system structure there is
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 34e44e4f235a7b5f30e4168c3e5366246fe0060a..f1bf728c3d2ddb45394d6ad5b96b70dc2c81ac4a 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -891,5 +891,6 @@ InitXLogInsert(void)
 	 * Allocate a buffer to hold the header information for a WAL record.
 	 */
 	if (hdr_scratch == NULL)
-		hdr_scratch = palloc0(HEADER_SCRATCH_SIZE);
+		hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
+											 HEADER_SCRATCH_SIZE);
 }