XLogRecPtr pagePtr,
                                                  TimeLineID newTLI);
 static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
-static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo);
+static void KeepLogSeg(XLogRecPtr recptr, XLogRecPtr slotsMinLSN,
+                      XLogSegNo *logSegNo);
 static XLogRecPtr XLogGetReplicationSlotMinimumLSN(void);
 
 static void AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli,
    VirtualTransactionId *vxids;
    int         nvxids;
    int         oldXLogAllowed = 0;
+   XLogRecPtr  slotsMinReqLSN;
 
    /*
     * An end-of-recovery checkpoint is really a shutdown checkpoint, just
     */
    END_CRIT_SECTION();
 
+   /*
+    * Get the current minimum LSN to be used later in the WAL segment
+    * cleanup.  We may clean up only WAL segments, which are not needed
+    * according to synchronized LSNs of replication slots.  The slot's LSN
+    * might be advanced concurrently, so we call this before
+    * CheckPointReplicationSlots() synchronizes replication slots.
+    */
+   slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
+
    /*
     * 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
     * prevent the disk holding the xlog from growing full.
     */
    XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
-   KeepLogSeg(recptr, &_logSegNo);
+   KeepLogSeg(recptr, slotsMinReqLSN, &_logSegNo);
    if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED,
                                           _logSegNo, InvalidOid,
                                           InvalidTransactionId))
    {
+       /*
+        * Recalculate the current minimum LSN to be used in the WAL segment
+        * cleanup.  Then, we must synchronize the replication slots again in
+        * order to make this LSN safe to use.
+        */
+       slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
+       CheckPointReplicationSlots();
+
        /*
         * Some slots have been invalidated; recalculate the old-segment
         * horizon, starting again from RedoRecPtr.
         */
        XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
-       KeepLogSeg(recptr, &_logSegNo);
+       KeepLogSeg(recptr, slotsMinReqLSN, &_logSegNo);
    }
    _logSegNo--;
    RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
    XLogRecPtr  endptr;
    XLogSegNo   _logSegNo;
    TimestampTz xtime;
+   XLogRecPtr  slotsMinReqLSN;
 
    /* Concurrent checkpoint/restartpoint cannot happen */
    Assert(!IsUnderPostmaster || MyBackendType == B_CHECKPOINTER);
    MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
    CheckpointStats.ckpt_start_t = GetCurrentTimestamp();
 
+   /*
+    * Get the current minimum LSN to be used later in the WAL segment
+    * cleanup.  We may clean up only WAL segments, which are not needed
+    * according to synchronized LSNs of replication slots.  The slot's LSN
+    * might be advanced concurrently, so we call this before
+    * CheckPointReplicationSlots() synchronizes replication slots.
+    */
+   slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
+
    if (log_checkpoints)
        LogCheckpointStart(flags, true);
 
    receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
    replayPtr = GetXLogReplayRecPtr(&replayTLI);
    endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
-   KeepLogSeg(endptr, &_logSegNo);
+   KeepLogSeg(endptr, slotsMinReqLSN, &_logSegNo);
    if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED,
                                           _logSegNo, InvalidOid,
                                           InvalidTransactionId))
    {
+       /*
+        * Recalculate the current minimum LSN to be used in the WAL segment
+        * cleanup.  Then, we must synchronize the replication slots again in
+        * order to make this LSN safe to use.
+        */
+       slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
+       CheckPointReplicationSlots();
+
        /*
         * Some slots have been invalidated; recalculate the old-segment
         * horizon, starting again from RedoRecPtr.
         */
        XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
-       KeepLogSeg(endptr, &_logSegNo);
+       KeepLogSeg(endptr, slotsMinReqLSN, &_logSegNo);
    }
    _logSegNo--;
 
    XLogSegNo   oldestSegMaxWalSize;    /* oldest segid kept by max_wal_size */
    XLogSegNo   oldestSlotSeg;  /* oldest segid kept by slot */
    uint64      keepSegs;
+   XLogRecPtr  slotsMinReqLSN;
 
    /*
     * slot does not reserve WAL. Either deactivated, or has never been active
     * oldestSlotSeg to the current segment.
     */
    currpos = GetXLogWriteRecPtr();
+   slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN();
    XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
-   KeepLogSeg(currpos, &oldestSlotSeg);
+   KeepLogSeg(currpos, slotsMinReqLSN, &oldestSlotSeg);
 
    /*
     * Find the oldest extant segment file. We get 1 until checkpoint removes
  * invalidation is optionally done here, instead.
  */
 static void
-KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
+KeepLogSeg(XLogRecPtr recptr, XLogRecPtr slotsMinReqLSN, XLogSegNo *logSegNo)
 {
    XLogSegNo   currSegNo;
    XLogSegNo   segno;
     * Calculate how many segments are kept by slots first, adjusting for
     * max_slot_wal_keep_size.
     */
-   keep = XLogGetReplicationSlotMinimumLSN();
+   keep = slotsMinReqLSN;
    if (keep != InvalidXLogRecPtr && keep < recptr)
    {
        XLByteToSeg(keep, segno, wal_segment_size);