diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c7c928f50b..72868779e9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -12989,3 +12989,46 @@ XLogRequestWalReceiverReply(void)
 {
 	doRequestWalReceiverReply = true;
 }
+
+/*
+ * Read the data from WAL buffer
+ * If the page we want is already recycled, return false
+ */
+bool
+XLogReadBuffer(char *buf, XLogRecPtr startptr, Size count, TimeLineID tli)
+{
+	int			idx;
+	uint32		offset;
+	XLogPageHeader	TargetPage;
+
+	/*
+	 * First, we should prevent AdvanceXLInsertBuffer
+	 */
+	LWLockAcquire(WALBufMappingLock, LW_SHARED);
+
+	/*
+	 * Check wheter the page we want is still on WAL buffer
+	 */
+	idx = XLogRecPtrToBufIdx(startptr);
+	TargetPage = (XLogPageHeader) (XLogCtl->pages + idx * (Size) XLOG_BLCKSZ);
+
+	if (TargetPage->xlp_tli != tli || TargetPage->xlp_pageaddr > startptr
+			|| TargetPage->xlp_pageaddr + (Size) XLOG_BLCKSZ < startptr + count)
+	{
+		LWLockRelease(WALBufMappingLock);
+		return false;
+	}
+
+	offset = startptr % XLOG_BLCKSZ;
+
+	/*
+	 * Acquire lock to prevent the other process from write WAL buffer anymore,
+	 * then read
+	 */
+	WALInsertLockAcquireExclusive();
+	memcpy(buf, TargetPage + offset, count);
+	WALInsertLockRelease();
+
+	LWLockRelease(WALBufMappingLock);
+	return true;
+}
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 5cf74e181a..6b55fbc880 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -33,6 +33,7 @@
 #ifndef FRONTEND
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "access/xlog.h"
 #include "utils/memutils.h"
 #endif
 
@@ -1054,9 +1055,6 @@ err:
  *
  * Returns true if succeeded, false if an error occurs, in which case
  * 'errinfo' receives error details.
- *
- * XXX probably this should be improved to suck data directly from the
- * WAL buffers when possible.
  */
 bool
 WALRead(XLogReaderState *state,
@@ -1067,6 +1065,14 @@ WALRead(XLogReaderState *state,
 	XLogRecPtr	recptr;
 	Size		nbytes;
 
+#ifndef FRONTEND
+	/*
+	 * If the data we want seems to be in one page, we first try to read from WAL buffer
+	 */
+	if (count < (Size) XLOG_BLCKSZ && XLogReadBuffer(buf, startptr, count, tli))
+			return true;
+#endif
+
 	p = buf;
 	recptr = startptr;
 	nbytes = count;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index ccfcf43d62..328c380d71 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -369,6 +369,8 @@ extern void XLogRequestWalReceiverReply(void);
 extern void assign_max_wal_size(int newval, void *extra);
 extern void assign_checkpoint_completion_target(double newval, void *extra);
 
+extern bool XLogReadBuffer(char *buf, XLogRecPtr startptr, Size count, TimeLineID tli);
+
 /*
  * Routines to start, stop, and get status of a base backup.
  */
