diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1e5c328d80402b7da4be575b408c1ecc86d12da6..74110f077226a0546ef84aca7c0f245f0ea7975e 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -4672,6 +4672,22 @@ FROM pg_stat_activity;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-log-replication-commands" xreflabel="log_replication_commands">
+      <term><varname>log_replication_commands</varname> (<type>boolean</type>)
+      <indexterm>
+       <primary><varname>log_replication_commands</> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Causes each replication command to be logged in the server log.
+        See <xref linkend="protocol-replication"> for more information about
+        replication command. The default value is <literal>off</>.
+        Only superusers can change this setting.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-log-temp-files" xreflabel="log_temp_files">
       <term><varname>log_temp_files</varname> (<type>integer</type>)
       <indexterm>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index a8a09e4f0ec63f5fe586ccfc1f4caaa996e54baa..5f6ad6b5fb4bc0befa56d38e6806bbf40e213253 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1306,6 +1306,8 @@ To initiate streaming replication, the frontend sends the
 of <literal>true</> tells the backend to go into walsender mode, wherein a
 small set of replication commands can be issued instead of SQL statements. Only
 the simple query protocol can be used in walsender mode.
+Replication commands are logged in the server log when
+<xref linkend="guc-log-replication-commands"> is enabled.
 Passing <literal>database</> as the value instructs walsender to connect to
 the database specified in the <literal>dbname</> parameter, which will allow
 the connection to be used for logical replication from that database.
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 844a5dea1def123b6a9c8a75e2bd311c775bd92b..384c9b61ce1bfc13f4e60d417600ee343d8254e1 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -108,6 +108,7 @@ bool		am_db_walsender = false;	/* Connected to a database? */
 int			max_wal_senders = 0;	/* the maximum number of concurrent walsenders */
 int			wal_sender_timeout = 60 * 1000;		/* maximum time to send one
 												 * WAL data message */
+bool		log_replication_commands = false;
 
 /*
  * State for WalSndWakeupRequest
@@ -1267,14 +1268,20 @@ exec_replication_command(const char *cmd_string)
 	MemoryContext cmd_context;
 	MemoryContext old_context;
 
+	/*
+	 * Log replication command if log_replication_commands is enabled.
+	 * Even when it's disabled, log the command with DEBUG1 level for
+	 * backward compatibility.
+	 */
+	ereport(log_replication_commands ? LOG : DEBUG1,
+			(errmsg("received replication command: %s", cmd_string)));
+
 	/*
 	 * CREATE_REPLICATION_SLOT ... LOGICAL exports a snapshot until the next
 	 * command arrives. Clean up the old stuff if there's anything.
 	 */
 	SnapBuildClearExportedSnapshot();
 
-	elog(DEBUG1, "received replication command: %s", cmd_string);
-
 	CHECK_FOR_INTERRUPTS();
 
 	cmd_context = AllocSetContextCreate(CurrentMemoryContext,
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index af667f54ada520db97d45b8929458dba0c6c96d2..0192def17a5b202ec49510a7f5b5b7e1b6d3d57a 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -924,6 +924,15 @@ static struct config_bool ConfigureNamesBool[] =
 		false,
 		NULL, NULL, NULL
 	},
+	{
+		{"log_replication_commands", PGC_SUSET, LOGGING_WHAT,
+			gettext_noop("Logs each replication command."),
+			NULL
+		},
+		&log_replication_commands,
+		false,
+		NULL, NULL, NULL
+	},
 	{
 		{"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows whether the running server has assertion checks enabled."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index df98b02d788b6e70d5b71010bd8d0d25223f129c..1b5f39fa6c1f94a127e5ea09fdfb97be8e622cb9 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -431,6 +431,7 @@
 					# e.g. '<%u%%%d> '
 #log_lock_waits = off			# log lock waits >= deadlock_timeout
 #log_statement = 'none'			# none, ddl, mod, all
+#log_replication_commands = off
 #log_temp_files = -1			# log temporary files equal or larger
 					# than the specified size in kilobytes;
 					# -1 disables, 0 logs all temp files
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index cff2be6d8f6eec0b857d025c5c7c7332c4d72d33..d091e0f6d081a8e9d721c31a08581baa85a49ba3 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -25,6 +25,7 @@ extern bool wake_wal_senders;
 /* user-settable parameters */
 extern int	max_wal_senders;
 extern int	wal_sender_timeout;
+extern bool	log_replication_commands;
 
 extern void InitWalSender(void);
 extern void exec_replication_command(const char *query_string);