*** a/doc/src/sgml/ref/pg_receivexlog.sgml
--- b/doc/src/sgml/ref/pg_receivexlog.sgml
***************
*** 204,209 **** PostgreSQL documentation
--- 204,219 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>-N</></term>
+       <term><option>--no-fsync</></term>
+       <listitem>
+        <para>
+         WAL file is flushed only it has changed.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option>-U <replaceable>username</replaceable></option></term>
        <term><option>--username=<replaceable class="parameter">username</replaceable></option></term>
        <listitem>
*** a/src/bin/pg_basebackup/pg_basebackup.c
--- b/src/bin/pg_basebackup/pg_basebackup.c
***************
*** 370,376 **** LogStreamerMain(logstreamer_param *param)
  	if (!ReceiveXlogStream(param->bgconn, param->startptr, param->timeline,
  						   param->sysidentifier, param->xlogdir,
  						   reached_end_position, standby_message_timeout,
! 						   NULL, 0))
  
  		/*
  		 * Any errors will already have been reported in the function process,
--- 370,376 ----
  	if (!ReceiveXlogStream(param->bgconn, param->startptr, param->timeline,
  						   param->sysidentifier, param->xlogdir,
  						   reached_end_position, standby_message_timeout,
! 						   NULL, true))
  
  		/*
  		 * Any errors will already have been reported in the function process,
*** a/src/bin/pg_basebackup/pg_receivexlog.c
--- b/src/bin/pg_basebackup/pg_receivexlog.c
***************
*** 36,46 **** static char *basedir = NULL;
  static int	verbose = 0;
  static int	noloop = 0;
  static int	standby_message_timeout = 10 * 1000;		/* 10 sec = default */
- static int	fsync_interval = 0; /* 0 = default */
  static volatile bool time_to_abort = false;
  static bool do_create_slot = false;
  static bool do_drop_slot = false;
! 
  
  static void usage(void);
  static DIR* get_destination_dir(char *dest_folder);
--- 36,45 ----
  static int	verbose = 0;
  static int	noloop = 0;
  static int	standby_message_timeout = 10 * 1000;		/* 10 sec = default */
  static volatile bool time_to_abort = false;
  static bool do_create_slot = false;
  static bool do_drop_slot = false;
! static bool	no_fsync = false;
  
  static void usage(void);
  static DIR* get_destination_dir(char *dest_folder);
***************
*** 66,76 **** usage(void)
  	printf(_("  %s [OPTION]...\n"), progname);
  	printf(_("\nOptions:\n"));
  	printf(_("  -D, --directory=DIR    receive transaction log files into this directory\n"));
- 	printf(_("  -F  --fsync-interval=SECS\n"
- 			 "                         time between fsyncs to transaction log files (default: %d)\n"), (fsync_interval / 1000));
  	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
  	printf(_("  -s, --status-interval=SECS\n"
  			 "                         time between status packets sent to server (default: %d)\n"), (standby_message_timeout / 1000));
  	printf(_("  -S, --slot=SLOTNAME    replication slot to use\n"));
  	printf(_("  -v, --verbose          output verbose messages\n"));
  	printf(_("  -V, --version          output version information, then exit\n"));
--- 65,75 ----
  	printf(_("  %s [OPTION]...\n"), progname);
  	printf(_("\nOptions:\n"));
  	printf(_("  -D, --directory=DIR    receive transaction log files into this directory\n"));
  	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
  	printf(_("  -s, --status-interval=SECS\n"
  			 "                         time between status packets sent to server (default: %d)\n"), (standby_message_timeout / 1000));
+ 	printf(_("  -N, --no-fsync         fsync only wal has changed\n"
+  			 "                         If you want to report the flush position to the server, should use -S option.\n"));
  	printf(_("  -S, --slot=SLOTNAME    replication slot to use\n"));
  	printf(_("  -v, --verbose          output verbose messages\n"));
  	printf(_("  -V, --version          output version information, then exit\n"));
***************
*** 343,349 **** StreamLog(void)
  
  	ReceiveXlogStream(conn, startpos, starttli, NULL, basedir,
  					  stop_streaming, standby_message_timeout, ".partial",
! 					  fsync_interval);
  
  	PQfinish(conn);
  	conn = NULL;
--- 342,348 ----
  
  	ReceiveXlogStream(conn, startpos, starttli, NULL, basedir,
  					  stop_streaming, standby_message_timeout, ".partial",
! 					  no_fsync);
  
  	PQfinish(conn);
  	conn = NULL;
***************
*** 374,383 **** main(int argc, char **argv)
  		{"port", required_argument, NULL, 'p'},
  		{"username", required_argument, NULL, 'U'},
  		{"no-loop", no_argument, NULL, 'n'},
- 		{"fsync-interval", required_argument, NULL, 'F'},
  		{"no-password", no_argument, NULL, 'w'},
  		{"password", no_argument, NULL, 'W'},
  		{"status-interval", required_argument, NULL, 's'},
  		{"slot", required_argument, NULL, 'S'},
  		{"verbose", no_argument, NULL, 'v'},
  /* action */
--- 373,382 ----
  		{"port", required_argument, NULL, 'p'},
  		{"username", required_argument, NULL, 'U'},
  		{"no-loop", no_argument, NULL, 'n'},
  		{"no-password", no_argument, NULL, 'w'},
  		{"password", no_argument, NULL, 'W'},
  		{"status-interval", required_argument, NULL, 's'},
+ 		{"no-fsync", no_argument, NULL, 'N'},
  		{"slot", required_argument, NULL, 'S'},
  		{"verbose", no_argument, NULL, 'v'},
  /* action */
***************
*** 408,414 **** main(int argc, char **argv)
  		}
  	}
  
! 	while ((c = getopt_long(argc, argv, "D:d:h:p:U:s:S:nF:wWv",
  							long_options, &option_index)) != -1)
  	{
  		switch (c)
--- 407,413 ----
  		}
  	}
  
! 	while ((c = getopt_long(argc, argv, "D:d:h:p:U:s:NS:nwWv",
  							long_options, &option_index)) != -1)
  	{
  		switch (c)
***************
*** 449,469 **** main(int argc, char **argv)
  					exit(1);
  				}
  				break;
  			case 'S':
  				replication_slot = pg_strdup(optarg);
  				break;
  			case 'n':
  				noloop = 1;
  				break;
- 		case 'F':
- 			fsync_interval = atoi(optarg) * 1000;
- 			if (fsync_interval < -1000)
- 			{
- 				fprintf(stderr, _("%s: invalid fsync interval \"%s\"\n"),
- 						progname, optarg);
- 				exit(1);
- 			}
- 			break;
  			case 'v':
  				verbose++;
  				break;
--- 448,462 ----
  					exit(1);
  				}
  				break;
+ 			case 'N':
+ 				no_fsync = true;
+ 				break;
  			case 'S':
  				replication_slot = pg_strdup(optarg);
  				break;
  			case 'n':
  				noloop = 1;
  				break;
  			case 'v':
  				verbose++;
  				break;
*** a/src/bin/pg_basebackup/receivelog.c
--- b/src/bin/pg_basebackup/receivelog.c
***************
*** 31,44 **** static char current_walfile_name[MAXPGPATH] = "";
  static bool reportFlushPosition = false;
  static XLogRecPtr lastFlushPosition = InvalidXLogRecPtr;
  
- static int64 last_fsync = -1;		/* timestamp of last WAL file flush */
  static bool still_sending = true;		/* feedback still needs to be sent? */
  
  static PGresult *HandleCopyStream(PGconn *conn, XLogRecPtr startpos,
  				 uint32 timeline, char *basedir,
  			   stream_stop_callback stream_stop, int standby_message_timeout,
  				  char *partial_suffix, XLogRecPtr *stoppos,
! 				  int fsync_interval);
  static int CopyStreamPoll(PGconn *conn, long timeout_ms);
  static int CopyStreamReceive(PGconn *conn, long timeout, char **buffer);
  static bool ProcessKeepaliveMsg(PGconn *conn, char *copybuf, int len,
--- 31,43 ----
  static bool reportFlushPosition = false;
  static XLogRecPtr lastFlushPosition = InvalidXLogRecPtr;
  
  static bool still_sending = true;		/* feedback still needs to be sent? */
  
  static PGresult *HandleCopyStream(PGconn *conn, XLogRecPtr startpos,
  				 uint32 timeline, char *basedir,
  			   stream_stop_callback stream_stop, int standby_message_timeout,
  				  char *partial_suffix, XLogRecPtr *stoppos,
! 				  bool no_fsync);
  static int CopyStreamPoll(PGconn *conn, long timeout_ms);
  static int CopyStreamReceive(PGconn *conn, long timeout, char **buffer);
  static bool ProcessKeepaliveMsg(PGconn *conn, char *copybuf, int len,
***************
*** 55,62 **** static bool CheckCopyStreamStop(PGconn *conn, XLogRecPtr blockpos,
  								stream_stop_callback stream_stop,
  								char *partial_suffix, XLogRecPtr *stoppos);
  static long CalculateCopyStreamSleeptime(int64 now, int standby_message_timeout,
! 										 int64 last_status, int fsync_interval,
! 										 XLogRecPtr blockpos);
  
  static bool ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos,
  						 uint32 *timeline);
--- 54,60 ----
  								stream_stop_callback stream_stop,
  								char *partial_suffix, XLogRecPtr *stoppos);
  static long CalculateCopyStreamSleeptime(int64 now, int standby_message_timeout,
! 										 int64 last_status, XLogRecPtr blockpos);
  
  static bool ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos,
  						 uint32 *timeline);
***************
*** 209,215 **** close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
  				progname, current_walfile_name, partial_suffix);
  
  	lastFlushPosition = pos;
- 	last_fsync = feGetCurrentTimestamp();
  	return true;
  }
  
--- 207,212 ----
***************
*** 440,447 **** CheckServerVersionForStreaming(PGconn *conn)
   * allows you to tell the difference between partial and completed files,
   * so that you can continue later where you left.
   *
!  * fsync_interval controls how often we flush to the received WAL file,
!  * in milliseconds.
   *
   * Note: The log position *must* be at a log segment start!
   */
--- 437,443 ----
   * allows you to tell the difference between partial and completed files,
   * so that you can continue later where you left.
   *
!  * If 'no_fsync' is true, fsync is only wal change.
   *
   * Note: The log position *must* be at a log segment start!
   */
***************
*** 450,456 **** ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  				  char *sysidentifier, char *basedir,
  				  stream_stop_callback stream_stop,
  				  int standby_message_timeout, char *partial_suffix,
! 				  int fsync_interval)
  {
  	char		query[128];
  	char		slotcmd[128];
--- 446,452 ----
  				  char *sysidentifier, char *basedir,
  				  stream_stop_callback stream_stop,
  				  int standby_message_timeout, char *partial_suffix,
! 				  bool no_fsync)
  {
  	char		query[128];
  	char		slotcmd[128];
***************
*** 595,601 **** ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  		/* Stream the WAL */
  		res = HandleCopyStream(conn, startpos, timeline, basedir, stream_stop,
  							   standby_message_timeout, partial_suffix,
! 							   &stoppos, fsync_interval);
  		if (res == NULL)
  			goto error;
  
--- 591,597 ----
  		/* Stream the WAL */
  		res = HandleCopyStream(conn, startpos, timeline, basedir, stream_stop,
  							   standby_message_timeout, partial_suffix,
! 							   &stoppos, no_fsync);
  		if (res == NULL)
  			goto error;
  
***************
*** 760,770 **** static PGresult *
  HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  				 char *basedir, stream_stop_callback stream_stop,
  				 int standby_message_timeout, char *partial_suffix,
! 				 XLogRecPtr *stoppos, int fsync_interval)
  {
  	char	   *copybuf = NULL;
  	int64		last_status = -1;
  	XLogRecPtr	blockpos = startpos;
  
  	still_sending = true;
  
--- 756,767 ----
  HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  				 char *basedir, stream_stop_callback stream_stop,
  				 int standby_message_timeout, char *partial_suffix,
! 				 XLogRecPtr *stoppos, bool no_fsync)
  {
  	char	   *copybuf = NULL;
  	int64		last_status = -1;
  	XLogRecPtr	blockpos = startpos;
+ 	XLogRecPtr	lastFeedbackFlushPosition = startpos;
  
  	still_sending = true;
  
***************
*** 789,797 **** HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  		 */
  		if (lastFlushPosition < blockpos &&
  			walfile != -1 &&
! 			((fsync_interval > 0 &&
! 			  feTimestampDifferenceExceeds(last_fsync, now, fsync_interval)) ||
! 			 fsync_interval < 0))
  		{
  			if (fsync(walfile) != 0)
  			{
--- 786,792 ----
  		 */
  		if (lastFlushPosition < blockpos &&
  			walfile != -1 &&
! 			! no_fsync)
  		{
  			if (fsync(walfile) != 0)
  			{
***************
*** 801,827 **** HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
  			}
  
  			lastFlushPosition = blockpos;
- 			last_fsync = now;
  		}
  
  		/*
  		 * Potentially send a status message to the master
  		 */
! 		if (still_sending && standby_message_timeout > 0 &&
! 			feTimestampDifferenceExceeds(last_status, now,
! 										 standby_message_timeout))
  		{
  			/* Time to send feedback! */
  			if (!sendFeedback(conn, blockpos, now, false))
  				goto error;
  			last_status = now;
  		}
  
  		/*
  		 * Calculate how long send/receive loops should sleep
  		 */
  		sleeptime = CalculateCopyStreamSleeptime(now, standby_message_timeout,
! 												 last_status, fsync_interval, blockpos);
  
  		r = CopyStreamReceive(conn, sleeptime, &copybuf);
  		while (r != 0)
--- 796,823 ----
  			}
  
  			lastFlushPosition = blockpos;
  		}
  
  		/*
  		 * Potentially send a status message to the master
  		 */
! 		if ((still_sending && standby_message_timeout > 0 &&
! 			feTimestampDifferenceExceeds(last_status, now, standby_message_timeout)) ||
! 			(! no_fsync && lastFeedbackFlushPosition != lastFlushPosition))
  		{
  			/* Time to send feedback! */
  			if (!sendFeedback(conn, blockpos, now, false))
  				goto error;
  			last_status = now;
+ 			if (! no_fsync)
+ 				lastFeedbackFlushPosition = lastFlushPosition;
  		}
  
  		/*
  		 * Calculate how long send/receive loops should sleep
  		 */
  		sleeptime = CalculateCopyStreamSleeptime(now, standby_message_timeout,
! 												 last_status, blockpos);
  
  		r = CopyStreamReceive(conn, sleeptime, &copybuf);
  		while (r != 0)
***************
*** 1244,1277 **** CheckCopyStreamStop(PGconn *conn, XLogRecPtr blockpos, uint32 timeline,
   */
  static long
  CalculateCopyStreamSleeptime(int64 now, int standby_message_timeout,
! 							 int64 last_status, int fsync_interval, XLogRecPtr blockpos)
  {
- 	int64		targettime = 0;
  	int64		status_targettime = 0;
- 	int64		fsync_targettime = 0;
  	long		sleeptime;
  
  	if (standby_message_timeout && still_sending)
  		status_targettime = last_status +
  			(standby_message_timeout - 1) * ((int64) 1000);
  
! 	if (fsync_interval > 0 && lastFlushPosition < blockpos)
! 		fsync_targettime = last_fsync +
! 			(fsync_interval - 1) * ((int64) 1000);
! 
! 	if ((status_targettime < fsync_targettime && status_targettime > 0) ||
! 		fsync_targettime == 0)
! 		targettime = status_targettime;
! 	else
! 		targettime = fsync_targettime;
! 
! 	if (targettime > 0)
  	{
  		long		secs;
  		int			usecs;
  
  		feTimestampDifference(now,
! 							  targettime,
  							  &secs,
  							  &usecs);
  		/* Always sleep at least 1 sec */
--- 1240,1261 ----
   */
  static long
  CalculateCopyStreamSleeptime(int64 now, int standby_message_timeout,
! 							 int64 last_status, XLogRecPtr blockpos)
  {
  	int64		status_targettime = 0;
  	long		sleeptime;
  
  	if (standby_message_timeout && still_sending)
  		status_targettime = last_status +
  			(standby_message_timeout - 1) * ((int64) 1000);
  
! 	if (status_targettime > 0)
  	{
  		long		secs;
  		int			usecs;
  
  		feTimestampDifference(now,
! 							  status_targettime,
  							  &secs,
  							  &usecs);
  		/* Always sleep at least 1 sec */
*** a/src/bin/pg_basebackup/receivelog.h
--- b/src/bin/pg_basebackup/receivelog.h
***************
*** 31,36 **** extern bool ReceiveXlogStream(PGconn *conn,
  				  stream_stop_callback stream_stop,
  				  int standby_message_timeout,
  				  char *partial_suffix,
! 				  int fsync_interval);
  
  #endif	/* RECEIVELOG_H */
--- 31,36 ----
  				  stream_stop_callback stream_stop,
  				  int standby_message_timeout,
  				  char *partial_suffix,
! 				  bool no_fsync);
  
  #endif	/* RECEIVELOG_H */
