# How MongoDB Data Balancing Works and How to Configure It Using Docker Compose

> Learn how MongoDB data balancing works to distribute data evenly across shards. Configure the balancer easily with Docker Compose for optimal performance and efficiency.

- Repository: [Jin/mongodb-cluster-docker-compose](https://github.com/minhhungit/mongodb-cluster-docker-compose)
- Tags: how-to-guide
- Published: 2026-03-07

---

**MongoDB's balancer is a background process that runs on the `mongos` router to automatically migrate chunks between shards, ensuring even data distribution, and you can configure it via the `config.settings` collection or helper methods like `sh.startBalancer()` and `sh.setChunkSize()`.**

MongoDB uses a sharded cluster architecture to distribute data across multiple replica sets, relying on an automated **data balancing mechanism** to maintain performance as datasets grow. This guide explains how the balancer manages chunk migrations and how to configure it using the **minhhungit/mongodb-cluster-docker-compose** repository, which provides a complete Docker Compose setup for running a sharded MongoDB cluster locally.

## What Is the MongoDB Balancer and How It Works

The balancer is responsible for maintaining equilibrium across a sharded cluster by moving **chunks**—contiguous ranges of shard key values—from shards with more data to those with less.

### Chunk-Based Data Distribution

MongoDB partitions data into chunks based on the **shard key**. When a chunk grows beyond the **chunkSize** threshold (default 64 MiB), the config server marks it for splitting. The balancer then evaluates the distribution across all shards and initiates migrations if it detects an imbalance.

### The Balancer Process on Mongos

According to the repository's README, the balancer runs as a background process on the `mongos` router. The sample `sh.status()` output shows:

```

balancer:
  Currently enabled:  yes
  Currently running:  no
  No recent migrations

```

This indicates the balancer is enabled by default but idle when the cluster is balanced. The status output is documented in the README around lines 171‑174 of [`readme.md`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/readme.md).

## Core Components of the Sharded Cluster

The data balancing mechanism relies on three architectural components defined in the repository's [`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml) and startup scripts.

### Config Servers Store Metadata

The **config servers** maintain the cluster's metadata, including chunk ranges and balancer settings. In [`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml), three config-server containers (e.g., `mongo-config-01`) are defined to provide redundancy for this critical metadata.

### Mongos Router Runs the Balancer

The **mongos** process acts as the query router and hosts the balancer logic. The [`scripts/entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-route.sh) script starts the `mongos` instance and waits for config servers and shards to become available before executing `sh.addShard()` commands to register shards with the cluster.

### Shard Replica Sets Hold Data

Data is stored in **shard replica sets**. Each shard is started by an **entrypoint-shardXX.sh** script (e.g., [`scripts/entrypoint-shard01.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-shard01.sh)) that initiates the replica set via the `init_shard()` function before joining the cluster.

## How to Check Balancer Status

To inspect the current balancing state in the Docker environment, execute `mongosh` on the router container:

```bash
docker exec -it router-01 mongosh --port 27017 <<'EOF'
sh.status()
EOF

```

Look for the `balancer:` section in the output. It reports whether the balancer is enabled, whether it is actively running, and statistics on recent chunk migrations.

## Configuring the Data Balancing Mechanism

MongoDB exposes balancer controls through the `config.settings` collection in the **admin** database. All configuration commands must run against the `mongos` router.

### Enable or Disable the Balancer

Use the helper methods to toggle the balancer state:

```javascript
// Disable automatic balancing
sh.stopBalancer();

// Re-enable automatic balancing
sh.startBalancer();

```

These commands update the `balancerEnabled` field in `config.settings`. Verify the change with:

```javascript
db.getSiblingDB("config").settings.find({_id: "balancer"}).pretty();

```

### Adjust Chunk Size

The default **chunkSize** is 64 MiB. Increase or decrease it to control the granularity of data distribution:

```javascript
// Set chunk size to 128 MiB
sh.setChunkSize(128);

```

Smaller chunks enable more even distribution but increase metadata overhead on config servers. Larger chunks reduce migration frequency but may create hot spots on individual shards.

### Set a Balancing Window

Restrict balancing operations to off-peak hours by defining an **activeWindow**:

```javascript
db.getSiblingDB("config").settings.update(
   { _id: "balancer" },
   { $set: { 
       activeWindow: { start: "03:00", stop: "05:00" }   // 3 am-5 am UTC
   } },
   { upsert: true }
);

```

During hours outside this window, the balancer will not initiate new chunk migrations.

### Force Manual Balancing

To trigger an immediate balancing round without waiting for the background process:

```javascript
sh.startBalancer();
sh.balance();   // Forces an immediate balancing round

```

### Disable Auto-Splitting

For testing or specific maintenance scenarios, prevent automatic chunk splitting:

```javascript
db.getSiblingDB("config").settings.update(
   { _id: "autosplit" },
   { $set: { enabled: false } },
   { upsert: true }
);

```

## Complete Configuration Example

Below is a self-contained script you can execute inside the `router-01` container to tune the balancer for a production-like environment. Save this as [`scripts/balance-config.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/balance-config.sh) in your repository:

```bash
#!/bin/bash

# router-balancer-config.sh – run inside router-01

mongosh --port 27017 <<'EOS'
print("Current balancer status:");
sh.status().balancer

// Enable the balancer (if it was disabled)
sh.startBalancer();

// Set chunk size to 128 MiB (default is 64 MiB)
sh.setChunkSize(128);

// Restrict balancing to a nightly window (02:00-04:00 UTC)
db.getSiblingDB("config").settings.update(
  { _id: "balancer" },
  { $set: { activeWindow: { start: "02:00", stop: "04:00" } } },
  { upsert: true }
);

print("Updated balancer configuration:");
db.getSiblingDB("config").settings.find({_id:"balancer"}).pretty();
EOS

```

Invoke the script after the cluster has started:

```bash
docker exec -it router-01 bash /scripts/balance-config.sh

```

## Where to Find the Relevant Code in the Repository

The **minhhungit/mongodb-cluster-docker-compose** repository implements the sharded cluster architecture that supports the data balancing mechanism described above.

| File | Purpose |
|------|---------|
| [`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml) | Declares the router, config servers, and shard containers that make up the cluster. |
| [`scripts/entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-route.sh) | Starts `mongos`, waits for config servers and shards, then executes `sh.addShard()` commands. |
| [`scripts/entrypoint-shard01.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-shard01.sh) | Boots the first shard's `mongod` instance and initiates the replica set via the `init_shard()` function. |
| [`readme.md`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/readme.md) | Contains sample `sh.status()` output showing the balancer block and cluster verification steps. |
| [`scripts/init-router.js`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/init-router.js) | Holds the JavaScript commands that register shards with the cluster metadata. |

Browse these files directly on GitHub:
- **Router entrypoint**: https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/scripts/entrypoint-route.sh
- **Shard entrypoint**: https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/scripts/entrypoint-shard01.sh
- **Full README**: https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/readme.md

## Summary

- The **MongoDB balancer** is a background process running on the `mongos` router that migrates **chunks** (ranges of shard key values) between shards to maintain even data distribution.
- **Configuration** is managed through the `config.settings` collection using helpers like `sh.startBalancer()`, `sh.stopBalancer()`, and `sh.setChunkSize()`, or by setting an `activeWindow` for time-based restrictions.
- The **minhhungit/mongodb-cluster-docker-compose** repository provides the Docker infrastructure—defined in [`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml) and managed by [`entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/entrypoint-route.sh)—that implements the config servers, mongos router, and shard replica sets required for automatic balancing.
- You can inspect balancer status with `sh.status()`, force immediate balancing with `sh.balance()`, and tune performance by adjusting the **chunkSize** default of 64 MiB.

## Frequently Asked Questions

### How do I know if the MongoDB balancer is actually running?

Connect to the `mongos` router and run `sh.status()`. The output includes a `balancer:` section that reports `Currently enabled` and `Currently running` status. In the **minhhungit/mongodb-cluster-docker-compose** repository, the README shows sample output indicating the balancer is enabled by default but may display `Currently running: no` when the cluster is already balanced or when no migrations are needed.

### What is the default chunk size, and when should I change it?

The default **chunkSize** is 64 MiB. You should increase it (using `sh.setChunkSize()`) if you have a very large dataset and want to reduce the overhead of frequent migrations and metadata tracking. Decrease it if you need finer-grained distribution to avoid hot spots on individual shards, though this increases the storage and processing load on the config servers.

### Can I schedule MongoDB balancing to run only during off-peak hours?

Yes. You can define an **activeWindow** in the `config.settings` collection to restrict the balancer to specific UTC times. For example, setting `activeWindow: { start: "02:00", stop: "04:00" }` ensures the balancer only migrates chunks between 2 am and 4 am UTC, preventing balancing operations from impacting peak-hour workloads.

### Where is the balancer process located in the Docker Compose architecture?

In the **minhhungit/mongodb-cluster-docker-compose** setup, the balancer runs as part of the **mongos** router process defined in [`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml) and started by [`scripts/entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-route.sh). You must connect to the router container (e.g., `router-01`) to inspect or configure balancer settings, as the shard containers only run `mongod` instances and do not execute balancing logic.