diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 6a6fc3b..e9a9a8f 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -336,7 +336,8 @@ end_heap_rewrite(RewriteState state)
 						MAIN_FORKNUM,
 						state->rs_blockno,
 						state->rs_buffer,
-						true);
+						true,
+						false);
 		RelationOpenSmgr(state->rs_new_rel);
 
 		PageSetChecksumInplace(state->rs_buffer, state->rs_blockno);
@@ -685,7 +686,8 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
 							MAIN_FORKNUM,
 							state->rs_blockno,
 							page,
-							true);
+							true,
+							false);
 
 			/*
 			 * Now write the page. We say isTemp = true even if it's not a
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index cf4a6dc..d211a98 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -206,7 +206,7 @@ btbuildempty(PG_FUNCTION_ARGS)
 			  (char *) metapage, true);
 	if (XLogIsNeeded())
 		log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-					BTREE_METAPAGE, metapage, false);
+					BTREE_METAPAGE, metapage, false, true);
 
 	/*
 	 * An immediate sync is required even if we xlog'd the page, because the
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index f95f67a..faf611c 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -277,7 +277,8 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
 	if (wstate->btws_use_wal)
 	{
 		/* We use the heap NEWPAGE record type for this */
-		log_newpage(&wstate->index->rd_node, MAIN_FORKNUM, blkno, page, true);
+		log_newpage(&wstate->index->rd_node, MAIN_FORKNUM, blkno, page,
+					true, false);
 	}
 
 	/*
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 83cc9e8..5f6fed5 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -77,7 +77,9 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 
 		appendStringInfoString(buf, xlrec->rp_name);
 	}
-	else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
+	else if (info == XLOG_FPI ||
+			 info == XLOG_FPI_FOR_HINT ||
+			 info == XLOG_FPI_FOR_SYNC)
 	{
 		/* no further information to print */
 	}
@@ -181,6 +183,9 @@ xlog_identify(uint8 info)
 		case XLOG_FPI_FOR_HINT:
 			id = "FPI_FOR_HINT";
 			break;
+		case XLOG_FPI_FOR_SYNC:
+			id = "FPI_FOR_SYNC";
+			break;
 	}
 
 	return id;
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index bceee8d..15d148c 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -173,7 +173,7 @@ spgbuildempty(PG_FUNCTION_ARGS)
 			  (char *) page, true);
 	if (XLogIsNeeded())
 		log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-					SPGIST_METAPAGE_BLKNO, page, false);
+					SPGIST_METAPAGE_BLKNO, page, false, false);
 
 	/* Likewise for the root page. */
 	SpGistInitPage(page, SPGIST_LEAF);
@@ -183,7 +183,7 @@ spgbuildempty(PG_FUNCTION_ARGS)
 			  (char *) page, true);
 	if (XLogIsNeeded())
 		log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-					SPGIST_ROOT_BLKNO, page, true);
+					SPGIST_ROOT_BLKNO, page, true, false);
 
 	/* Likewise for the null-tuples root page. */
 	SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS);
@@ -193,12 +193,15 @@ spgbuildempty(PG_FUNCTION_ARGS)
 			  (char *) page, true);
 	if (XLogIsNeeded())
 		log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-					SPGIST_NULL_BLKNO, page, true);
+					SPGIST_NULL_BLKNO, page, true, true);
 
 	/*
 	 * An immediate sync is required even if we xlog'd the pages, because the
 	 * writes did not go through shared buffers and therefore a concurrent
 	 * checkpoint may have moved the redo pointer past our xlog record.
+	 * When the pages are WAL-logged, record requesting the relation to be
+	 * sync'ed is requested only once for the last record emitted in this
+	 * sequence.
 	 */
 	smgrimmedsync(index->rd_smgr, INIT_FORKNUM);
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f17f834..003fe95 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -9184,7 +9184,9 @@ xlog_redo(XLogReaderState *record)
 	XLogRecPtr	lsn = record->EndRecPtr;
 
 	/* in XLOG rmgr, backup blocks are only used by XLOG_FPI records */
-	Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
+	Assert(info == XLOG_FPI ||
+		   info == XLOG_FPI_FOR_HINT ||
+		   info == XLOG_FPI_FOR_SYNC ||
 		   !XLogRecHasAnyBlockRefs(record));
 
 	if (info == XLOG_NEXTOID)
@@ -9374,7 +9376,9 @@ xlog_redo(XLogReaderState *record)
 	{
 		/* nothing to do here */
 	}
-	else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
+	else if (info == XLOG_FPI ||
+			 info == XLOG_FPI_FOR_HINT ||
+			 info == XLOG_FPI_FOR_SYNC)
 	{
 		Buffer		buffer;
 
@@ -9392,10 +9396,27 @@ xlog_redo(XLogReaderState *record)
 		 * when checksums are enabled. There is no difference in handling
 		 * XLOG_FPI and XLOG_FPI_FOR_HINT records, they use a different info
 		 * code just to distinguish them for statistics purposes.
+		 *
+		 * XLOG_FPI_FOR_SYNC records are generated when a relation needs to
+		 * be sync'ed just after replaying a full page. This is important
+		 * to match the master behavior in the case where a page is written
+		 * directly to disk without going through shared buffers.
 		 */
 		if (XLogReadBufferForRedo(record, 0, &buffer) != BLK_RESTORED)
 			elog(ERROR, "unexpected XLogReadBufferForRedo result when restoring backup block");
 		UnlockReleaseBuffer(buffer);
+
+		if (info == XLOG_FPI_FOR_SYNC)
+		{
+			RelFileNode	rnode;
+			ForkNumber	forknum;
+			BlockNumber	blkno;
+			SMgrRelation srel;
+
+			(void) XLogRecGetBlockTag(record, 0, &rnode, &forknum, &blkno);
+			srel = smgropen(rnode, InvalidBackendId);
+			smgrimmedsync(srel, forknum);
+		}
 	}
 	else if (info == XLOG_BACKUP_END)
 	{
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 925255f..647d653 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -932,10 +932,13 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
  * If the page follows the standard page layout, with a PageHeader and unused
  * space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
  * the unused space to be left out from the WAL record, making it smaller.
+ *
+ * If 'is_sync' is set to TRUE, relation will be requested to sync immediately
+ * its data at replay after replaying this page full image.
  */
 XLogRecPtr
 log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
-			Page page, bool page_std)
+			Page page, bool page_std, bool is_sync)
 {
 	int			flags;
 	XLogRecPtr	recptr;
@@ -946,7 +949,7 @@ log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
 
 	XLogBeginInsert();
 	XLogRegisterBlock(0, rnode, forkNum, blkno, page, flags);
-	recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
+	recptr = XLogInsert(RM_XLOG_ID, is_sync ? XLOG_FPI_FOR_SYNC : XLOG_FPI);
 
 	/*
 	 * The page may be uninitialized. If so, we can't set the LSN because that
@@ -983,7 +986,7 @@ log_newpage_buffer(Buffer buffer, bool page_std)
 
 	BufferGetTag(buffer, &rnode, &forkNum, &blkno);
 
-	return log_newpage(&rnode, forkNum, blkno, page, page_std);
+	return log_newpage(&rnode, forkNum, blkno, page, page_std, false);
 }
 
 /*
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0ddde72..eb22a51 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9920,7 +9920,8 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
 		 * space.
 		 */
 		if (use_wal)
-			log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
+			log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page,
+						false, false);
 
 		PageSetChecksumInplace(page, blkno);
 
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 9f60687..fff0c7a 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -174,6 +174,7 @@ DecodeXLogOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 		case XLOG_FPW_CHANGE:
 		case XLOG_FPI_FOR_HINT:
 		case XLOG_FPI:
+		case XLOG_FPI_FOR_SYNC:
 			break;
 		default:
 			elog(ERROR, "unexpected RM_XLOG_ID record type: %u", info);
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
index 31b45ba..a682fba 100644
--- a/src/include/access/xloginsert.h
+++ b/src/include/access/xloginsert.h
@@ -53,7 +53,8 @@ extern void XLogResetInsertion(void);
 extern bool XLogCheckBufferNeedsBackup(Buffer buffer);
 
 extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
-			BlockNumber blk, char *page, bool page_std);
+				  BlockNumber blk, char *page, bool page_std,
+				  bool is_sync);
 extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std);
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index ad1eb4b..91445f1 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -73,6 +73,7 @@ typedef struct CheckPoint
 #define XLOG_END_OF_RECOVERY			0x90
 #define XLOG_FPI_FOR_HINT				0xA0
 #define XLOG_FPI						0xB0
+#define XLOG_FPI_FOR_SYNC				0xC0
 
 
 /*
