diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index fc8638c1b61..f6ca9e8632c 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -213,6 +213,12 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 	/* Set defaults, to be overridden by explicit options below */
 	InitializeGUCOptions();
 
+	/* Override ignore_system_indexes: we have no indexes during bootstrap */
+	IgnoreSystemIndexes = true;
+
+	/* Set bootstrap mode; note that this locks down values of some GUCs */
+	SetProcessingMode(BootstrapProcessing);
+
 	/* an initial --boot or --check should be present */
 	Assert(argc > 1
 		   && (strcmp(argv[1], "--boot") == 0
@@ -321,9 +327,6 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 
 	CreateDataDirLockFile(false);
 
-	SetProcessingMode(BootstrapProcessing);
-	IgnoreSystemIndexes = true;
-
 	InitializeMaxBackends();
 
 	/*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 667df448732..215a20a1f06 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3464,6 +3464,15 @@ set_config_with_handle(const char *name, config_handle *handle,
 		return 0;
 	}
 
+	/*
+	 * Certain GUCs aren't safe to enable during bootstrap mode.  Silently
+	 * ignore attempts to set them to non-default values.
+	 */
+	if (unlikely(IsBootstrapProcessingMode()) &&
+		(record->flags & GUC_NOT_IN_BOOTSTRAP) &&
+		source > PGC_S_DYNAMIC_DEFAULT)
+		changeVal = false;
+
 	/*
 	 * Check if the option can be set at this time. See guc.h for the precise
 	 * rules.
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 511dc32d519..064c6ba09e2 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -1089,7 +1089,8 @@ struct config_bool ConfigureNamesBool[] =
 	{
 		{"track_commit_timestamp", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Collects transaction commit time."),
-			NULL
+			NULL,
+			GUC_NOT_IN_BOOTSTRAP
 		},
 		&track_commit_timestamp,
 		false,
@@ -1929,7 +1930,7 @@ struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Disables reading from system indexes."),
 			gettext_noop("It does not prevent updating the indexes, so it is safe "
 						 "to use.  The worst consequence is slowness."),
-			GUC_NOT_IN_SAMPLE
+			GUC_NOT_IN_SAMPLE | GUC_NOT_IN_BOOTSTRAP
 		},
 		&IgnoreSystemIndexes,
 		false,
@@ -2763,7 +2764,7 @@ struct config_int ConfigureNamesInt[] =
 		{"transaction_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)."),
 			gettext_noop("0 disables the timeout."),
-			GUC_UNIT_MS
+			GUC_UNIT_MS | GUC_NOT_IN_BOOTSTRAP
 		},
 		&TransactionTimeout,
 		0, 0, INT_MAX,
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f619100467d..0e7e97dabf0 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -228,6 +228,7 @@ typedef enum
 							   0x002000 /* can't set in PG_AUTOCONF_FILENAME */
 #define GUC_RUNTIME_COMPUTED   0x004000 /* delay processing in 'postgres -C' */
 #define GUC_ALLOW_IN_PARALLEL  0x008000 /* allow setting in parallel mode */
+#define GUC_NOT_IN_BOOTSTRAP   0x010000 /* can't set in bootstrap mode */
 
 #define GUC_UNIT_KB			 0x01000000 /* value is in kilobytes */
 #define GUC_UNIT_BLOCKS		 0x02000000 /* value is in blocks */
