diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 559a91b4c88..a410b5ad752 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7044,6 +7044,8 @@ CreateCheckPoint(int flags)
 		checkPoint.redo = RedoRecPtr;
 	}
 
+	LWLockAcquire(ReplicationSlotReserveWALLock, LW_EXCLUSIVE);
+
 	/* Update the info_lck-protected copy of RedoRecPtr as well */
 	SpinLockAcquire(&XLogCtl->info_lck);
 	XLogCtl->RedoRecPtr = checkPoint.redo;
@@ -7117,6 +7119,8 @@ CreateCheckPoint(int flags)
 	ReplicationSlotsComputeRequiredLSN();
 	slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
 
+	LWLockRelease(ReplicationSlotReserveWALLock);
+
 	/*
 	 * In some cases there are groups of actions that must all occur on one
 	 * side or the other of a checkpoint record. Before flushing the
@@ -7653,6 +7657,8 @@ CreateRestartPoint(int flags)
 		return false;
 	}
 
+	LWLockAcquire(ReplicationSlotReserveWALLock, LW_EXCLUSIVE);
+
 	/*
 	 * Update the shared RedoRecPtr so that the startup process can calculate
 	 * the number of segments replayed since last restartpoint, and request a
@@ -7696,6 +7702,8 @@ CreateRestartPoint(int flags)
 	ReplicationSlotsComputeRequiredLSN();
 	slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
 
+	LWLockRelease(ReplicationSlotReserveWALLock);
+
 	if (log_checkpoints)
 		LogCheckpointStart(flags, true);
 
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index c0aa8aac39d..728ae81fc2a 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1435,6 +1435,8 @@ ReplicationSlotReserveWal(void)
 	Assert(slot != NULL);
 	Assert(slot->data.restart_lsn == InvalidXLogRecPtr);
 
+	LWLockAcquire(ReplicationSlotReserveWALLock, LW_SHARED);
+
 	/*
 	 * The replication slot mechanism is used to prevent removal of required
 	 * WAL. As there is no interlock between this routine and checkpoints, WAL
@@ -1490,6 +1492,8 @@ ReplicationSlotReserveWal(void)
 			break;
 	}
 
+	LWLockRelease(ReplicationSlotReserveWALLock);
+
 	if (!RecoveryInProgress() && SlotIsLogical(slot))
 	{
 		XLogRecPtr	flushptr;
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 16144c2b72d..ff199626eea 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -345,6 +345,7 @@ WALSummarizer	"Waiting to read or update WAL summarization state."
 DSMRegistry	"Waiting to read or update the dynamic shared memory registry."
 InjectionPoint	"Waiting to read or update information related to injection points."
 SerialControl	"Waiting to read or update shared <filename>pg_serial</filename> state."
+ReplicationSlotReserveWAL	"Wait for replication slot's WAL reservation."
 
 #
 # END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index 6a2f64c54fb..c7af5b410ae 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -83,3 +83,4 @@ PG_LWLOCK(49, WALSummarizer)
 PG_LWLOCK(50, DSMRegistry)
 PG_LWLOCK(51, InjectionPoint)
 PG_LWLOCK(52, SerialControl)
+PG_LWLOCK(53, ReplicationSlotReserveWAL)
