diff --git a/jstests/sharding/balancer_configuration_refresh.js b/jstests/sharding/balancer_configuration_refresh.js
new file mode 100644
index 00000000000..a92f51fc08b
--- /dev/null
+++ b/jstests/sharding/balancer_configuration_refresh.js
@@ -0,0 +1,70 @@
+/**
+ * Test shell balancer commands.
+ *  sh.setBalancerState
+ *  sh.getBalancerState
+ */
+import {configureFailPoint} from "jstests/libs/fail_point_util.js";
+import {funWithArgs} from "jstests/libs/parallel_shell_helpers.js";
+
+var db;
+
+var shardingTest =
+    new ShardingTest({name: "shell_commands", shards: 1, mongos: 1, other: {enableBalancer: true}});
+db = shardingTest.getDB("test");
+
+function balancerState() {
+    const res = assert.commandWorked(shardingTest.s.adminCommand({balancerStatus: 1}));
+    return res.mode !== "off";
+}
+assert(balancerState(), "Balancer should have been enabled during cluster setup");
+
+// Test that the balancer can be disabled
+assert.commandWorked(shardingTest.s.adminCommand({balancerStop: 1}));
+assert(!balancerState(), "Failed to disable balancer");
+
+const csrsPrimary = shardingTest.configRS.getPrimary();
+let balancerRefreshFp =
+    configureFailPoint(csrsPrimary, "hangBalancerSettingsRefreshOnBalancerThread");
+balancerRefreshFp.wait();
+
+// Activate hangBalancerReportAfterConfigurationRefresh outside of parallel shell.
+const fpCount =
+    assert
+        .commandWorked(csrsPrimary.adminCommand(
+            {configureFailPoint: "hangBalancerReportAfterConfigurationRefresh", mode: "alwaysOn"}))
+        .count;
+
+const failpointCoordinationShell = startParallelShell(
+    funWithArgs(function(count) {
+        // Wait for hangBalancerReportAfterConfigurationRefresh to be hit.
+        assert.commandWorked(db.adminCommand({
+            waitForFailPoint: "hangBalancerReportAfterConfigurationRefresh",
+            timesEntered: count + 1,
+            maxTimeMS: 60000
+        }));
+
+        // At this point the _configsvrBalancerStatus has refreshed the BalancerConfiguration with
+        // the latest state.
+
+        // Unblock the balancer thread refresh of BalancerConfiguration, which had already read from
+        // config.settings, but not yet swapped the configuration. This overrides the BalancerConfig
+        // with an older state.
+        assert.commandWorked(db.adminCommand(
+            {configureFailPoint: "hangBalancerSettingsRefreshOnBalancerThread", mode: "off"}))
+
+        // Allow _configsvrBalancerStatus to continue.
+        assert.commandWorked(db.adminCommand(
+            {configureFailPoint: "hangBalancerReportAfterConfigurationRefresh", mode: "off"}))
+
+        jsTestLog("Finished parallel shell");
+    }, fpCount), csrsPrimary.port);
+
+// Test that the balancer can be re-enabled
+assert.commandWorked(shardingTest.s.adminCommand({balancerStart: 1}));
+assert(!balancerState(), "Expected to return incorrect result due to above failpoint coordination");
+assert(balancerState(),
+       "Expected to succeed because faipoints have been disabled and a new refresh is triggered");
+
+failpointCoordinationShell();
+
+shardingTest.stop();
diff --git a/src/mongo/db/s/balancer/balancer.cpp b/src/mongo/db/s/balancer/balancer.cpp
index 17615c0e23a..7826560b708 100644
--- a/src/mongo/db/s/balancer/balancer.cpp
+++ b/src/mongo/db/s/balancer/balancer.cpp
@@ -129,6 +129,7 @@ using MigrationsAndResponses = std::vector<std::pair<const MigrateInfo&, SemiFut
 namespace {
 
 MONGO_FAIL_POINT_DEFINE(forceBalancerWarningChecks);
+MONGO_FAIL_POINT_DEFINE(hangBalancerReportAfterConfigurationRefresh);
 
 const Milliseconds kBalanceRoundDefaultInterval(10 * 1000);
 
@@ -806,6 +807,8 @@ void Balancer::report(OperationContext* opCtx, BSONObjBuilder* builder) {
     auto balancerConfig = Grid::get(opCtx)->getBalancerConfiguration();
     balancerConfig->refreshAndCheck(opCtx).ignore();
 
+    hangBalancerReportAfterConfigurationRefresh.pauseWhileSet();
+
     const auto mode = balancerConfig->getBalancerMode();
 
     stdx::lock_guard<Latch> scopedLock(_mutex);
diff --git a/src/mongo/s/balancer_configuration.cpp b/src/mongo/s/balancer_configuration.cpp
index 9e86c6f53e8..4321f6189eb 100644
--- a/src/mongo/s/balancer_configuration.cpp
+++ b/src/mongo/s/balancer_configuration.cpp
@@ -77,6 +77,8 @@
 namespace mongo {
 namespace {
 
+MONGO_FAIL_POINT_DEFINE(hangBalancerSettingsRefreshOnBalancerThread);
+
 // parses time of day in "hh:mm" format assuming 'hh' is 00-23
 bool toPointInTime(const std::string& str, boost::posix_time::ptime* timeOfDay) {
     int hh = 0;
@@ -273,6 +275,13 @@ Status BalancerConfiguration::_refreshBalancerSettings(OperationContext* opCtx)
         return settingsObjStatus.getStatus();
     }
 
+    hangBalancerSettingsRefreshOnBalancerThread.executeIf(
+        [&](const BSONObj&) {
+            LOGV2(9999900, "Hanging due to hangBalancerSettingsRefreshOnBalancerThread failpoint");
+            hangBalancerSettingsRefreshOnBalancerThread.pauseWhileSet();
+        },
+        [&](const BSONObj&) { return opCtx->getClient()->desc() == "Balancer"; });
+
     stdx::lock_guard<Latch> lk(_balancerSettingsMutex);
     _balancerSettings = std::move(settings);
 
