diff --git a/src/test/modules/commit_ts/t/005_switchover.pl b/src/test/modules/commit_ts/t/005_switchover.pl
new file mode 100644
index 0000000000..e6db21f656
--- /dev/null
+++ b/src/test/modules/commit_ts/t/005_switchover.pl
@@ -0,0 +1,95 @@
+# Test master/standby switchover scenario where the track_commit_timestamp
+# GUC is originally off, then enabled on the new primary after a switchover.
+use strict;
+use warnings;
+
+use TestLib;
+use Test::More tests => 3;
+use PostgresNode;
+
+my $bkplabel = 'backup';
+my $master   = get_new_node('master');
+$master->init(allows_streaming => 1);
+$master->append_conf(
+	'postgresql.conf', qq{
+	track_commit_timestamp = on
+	max_wal_senders = 5
+	max_worker_processes = 8
+	});
+$master->start;
+$master->backup($bkplabel);
+
+my $standby = get_new_node('standby');
+$standby->init_from_backup($master, $bkplabel, has_streaming => 1);
+$standby->start;
+
+for my $i (1 .. 10)
+{
+	$master->safe_psql('postgres', "create table t$i()");
+}
+my $master_lsn =
+  $master->safe_psql('postgres', 'select pg_current_wal_lsn()');
+$standby->poll_query_until('postgres',
+	qq{SELECT '$master_lsn'::pg_lsn <= pg_last_wal_replay_lsn()})
+  or die "standby never caught up";
+
+$standby->safe_psql('postgres', 'checkpoint');
+$standby->restart;
+
+# Begin the switchover, and first stop cleanly the primary.
+$master->stop;
+
+# Promote the standby with larger max_worker_processes, and enable
+# track_commit_timestamp while on it. Generate a XLOG_PARAMETER_CHANGE
+# record with those values.
+$standby->promote;
+$standby->append_conf('postgresql.conf', 'track_commit_timestamp = off');
+$standby->append_conf('postgresql.conf', 'max_worker_processes = 10');
+$standby->restart;
+
+# Enable streaming on the previous primary, and start it. The node will
+# shut down once it finds the record XLOG_PARAMETER_CHANGE generated
+# previously.
+$master->enable_streaming($standby);
+command_fails(
+    [ 'pg_ctl', '-D', $master->data_dir, '-l', $master->logfile, 'start' ],
+    'start fails because of max_worker_processes lower on standby at recovery');
+
+# Consume some transactions on the standby without the primary knowing
+# about it yet, generating some commit timestamps.
+for my $i (11 .. 20)
+{
+	$standby->safe_psql('postgres', "create table t$i()");
+}
+
+# Toggle the configuration back on, and do more transactions.
+$standby->append_conf('postgresql.conf', 'track_commit_timestamp = on');
+$standby->restart;
+for my $i (21 .. 30)
+{
+	$standby->safe_psql('postgres', "create table t$i()");
+}
+
+# Reconfigure the new standby and start it so as recovery is able to
+# go through with a setting of max_worker_processes much larger than
+# the primary.
+$master->append_conf('postgresql.conf', 'max_worker_processes = 50');
+$master->start;
+my $standby_lsn =
+  $standby->safe_psql('postgres', 'select pg_current_wal_lsn()');
+$master->poll_query_until('postgres',
+    qq{SELECT '$standby_lsn'::pg_lsn <= pg_last_wal_replay_lsn()});
+
+# And finally check that commit timestamps are generated on the
+# new primary.
+my $standby_ts = $standby->safe_psql('postgres',
+	qq{SELECT ts.* FROM pg_class, pg_xact_commit_timestamp(xmin) AS ts WHERE relname = 't30'}
+);
+isnt($standby_ts, '',
+	"standby gives valid non-empty value after promotion");
+
+$standby_ts = $standby->safe_psql('postgres',
+	qq{SELECT ts.* FROM pg_class, pg_xact_commit_timestamp(xmin) AS ts WHERE relname = 't11'}
+);
+is($standby_ts, '',
+	"standby gives valid empty value after promotion");
