NoSQL Databases

How to Downgrade MongoDB from 7.0 to 6.0: A Step-by-Step Guide

Downgrading MongoDB requires careful planning — setting the Feature Compatibility Version before replacing binaries, handling replica set members in sequence, and verifying data integrity throughout.

JusDB Team
November 23, 2023
8 min read
181 views

A team running MongoDB 7.0 in production flagged critical issues three days after upgrading — a third-party analytics connector began throwing wire protocol errors, and a legacy internal service that hadn't been touched in years stopped writing documents entirely. The incompatibilities weren't caught in staging because the affected workflows only ran on a weekly schedule. With the next batch window approaching and no patch available from the vendor, the engineering team had one option: roll back to MongoDB 6.0. This guide documents the exact procedure for doing that safely, without data loss, and with minimal downtime.

TL;DR: To downgrade MongoDB from 7.0 to 6.0, you must first set the Feature Compatibility Version (FCV) to "6.0" while still running 7.0 binaries — this is the irreversible gate. Then stop each mongod in sequence (secondaries first, then primary), replace binaries with 6.0 versions, restart, and verify replica set health between each step. For sharded clusters, downgrade mongos and config servers last. Back up everything before you start.

When Downgrading MongoDB Makes Sense (and When It Doesn't)

Downgrading is a legitimate operational move in specific circumstances. Knowing when it's appropriate — and when it's not — saves time arguing about the right path forward.

Valid Reasons to Downgrade

  • Driver incompatibility — A client library, BI connector, or ORM does not yet support MongoDB 7.0 wire protocol changes and has no available patch.
  • Application behavior regression — A query planner change in 7.0 causes a critical query to perform significantly worse and there is no immediate index or query fix.
  • Third-party dependency — An ETL tool, CDC pipeline (e.g., Debezium), or monitoring agent has a hard version ceiling below 7.0.
  • Time pressure — The upgrade was done prematurely before full compatibility validation, and a rollback buys time to do it right.

When Downgrading Is the Wrong Move

  • The FCV has already been used at 7.0 to create new collections or indexes that use 7.0-only features (these cannot be migrated backward automatically).
  • You have been running on 7.0 for weeks or months with active write workloads — the risk of data format incompatibility increases with time at the higher FCV.
  • The root cause is a misconfiguration or application bug that can be fixed without a version change.

If any 7.0-specific features have been enabled — such as time series collection improvements introduced post-6.0, or new index types — those must be removed or migrated before the FCV can be lowered.

Pre-Downgrade Checklist

Backup first, no exceptions. Before touching FCV or any binary, take a full consistent backup of every replica set member. If you use mongodump, run it against the primary. If you use filesystem snapshots, quiesce writes first. A downgrade that goes wrong without a backup is unrecoverable.

1. Verify Current FCV

Connect to the primary and confirm what FCV is currently set:

javascript
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })

Expected output if you upgraded fully to 7.0:

javascript
{ featureCompatibilityVersion: { version: '7.0' }, ok: 1 }

If the version shows "6.0", the FCV was never upgraded and you can proceed directly to binary replacement. If it shows "7.0", the FCV must be lowered first.

2. Audit for 7.0-Only Features

Check whether any collections use features introduced in 7.0 that are not backward-compatible. The most common are:

  • Compound wildcard indexes (new in 7.0)
  • Any collection created with options only available at FCV 7.0

Drop or convert those before lowering the FCV. Attempting to lower FCV with incompatible objects in place will result in an error.

3. Verify Driver and Application Compatibility with 6.0

Confirm that all application drivers support MongoDB 6.0. MongoDB 6.0 requires driver versions that support MongoDB Server API version 1. Check your driver release notes against the MongoDB Driver Compatibility Matrix.

4. Check Replica Set Health

javascript
rs.status()

All members must be in PRIMARY or SECONDARY state. Do not proceed with any member in RECOVERING, STARTUP, or UNKNOWN state.

Step 1 — Set Feature Compatibility Version to 6.0

Critical — this step is the point of no easy return. Once you set FCV to "6.0", MongoDB will begin restricting which 7.0-only behaviors are available. You can set FCV back to "7.0" only if you have not yet replaced binaries. After binary replacement, the path back to 7.0 requires a full reinstall and restore from backup.

Connect to the primary of your replica set and run:

javascript
db.adminCommand({ setFeatureCompatibilityVersion: "6.0" })

MongoDB will replicate this change to all secondaries automatically. Wait for replication to complete before proceeding. You can verify the FCV across all members by running the following on each node:

javascript
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })

All members must return "6.0" before you touch any binary. If any member is lagging behind on replication, wait for it to catch up:

javascript
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()

If the FCV Command Fails

If setFeatureCompatibilityVersion returns an error, it is most likely because a 7.0-specific feature is in use. The error message will indicate which feature is blocking the downgrade. Common resolution: drop the offending index or collection, then retry.

javascript
// Example: drop a compound wildcard index before lowering FCV
db.myCollection.dropIndex("fieldA_1_$**_1")

Step 2 — Downgrade Replica Set Members (Rolling Procedure)

The rolling downgrade procedure replaces one member at a time, always starting with secondaries. This keeps the replica set available throughout the process.

2a. Downgrade Each Secondary

For each secondary node (repeat for all secondaries before touching the primary):

Stop the mongod process on the secondary:

javascript
// From the mongo shell connected to the secondary
db.adminCommand({ shutdown: 1 })

Or from the OS shell on that host:

javascript
sudo systemctl stop mongod

Replace the MongoDB 7.0 binary with the 6.0 binary. On Ubuntu/Debian:

javascript
sudo apt-get install -y mongodb-org=6.0.14 mongodb-org-database=6.0.14 \
  mongodb-org-server=6.0.14 mongodb-org-shell=6.0.14 \
  mongodb-org-mongos=6.0.14 mongodb-org-tools=6.0.14

On RHEL/CentOS:

javascript
sudo yum downgrade mongodb-org-6.0.14 mongodb-org-server-6.0.14 \
  mongodb-org-shell-6.0.14 mongodb-org-mongos-6.0.14 \
  mongodb-org-tools-6.0.14

Start mongod and verify it rejoins the replica set as a secondary:

javascript
sudo systemctl start mongod

Then from the primary's mongo shell, verify the member is back in SECONDARY state:

javascript
rs.status()
// Confirm the downgraded node shows stateStr: "SECONDARY"

Wait for the secondary to fully catch up on oplog before proceeding to the next member:

javascript
rs.printSecondaryReplicationInfo()
// Confirm "behind the primary by" is near 0 seconds

2b. Step Down and Downgrade the Primary

Step down the primary before stopping it. Forcing a shutdown without a stepdown can cause a brief write outage while elections complete. A controlled stepdown triggers an immediate election among the already-downgraded secondaries.

From the primary's mongo shell:

javascript
rs.stepDown()

This forces an election. One of the 6.0 secondaries becomes the new primary. Confirm with rs.status() from another member. Then stop the former primary (now a secondary):

javascript
sudo systemctl stop mongod

Replace binaries using the same commands as the secondary step above. Start mongod:

javascript
sudo systemctl start mongod

The former primary rejoins the replica set as a secondary running MongoDB 6.0. Verify all members are healthy:

javascript
rs.status()
// All members should show PRIMARY or SECONDARY
// No member should show version: 7.x in health check

Step 3 — Downgrade Mongos and Config Servers (for Sharded Clusters)

If your deployment is a sharded cluster, downgrade in this order: data-bearing shards first (each shard treated as a replica set per Step 2), then config servers, then mongos routers.

3a. Downgrade Config Server Replica Set

The config server replica set (CSRS) follows the same rolling procedure as a data replica set. Connect to the CSRS primary and verify FCV is already at "6.0" (set in Step 1 applies cluster-wide), then repeat the secondary-then-primary binary replacement pattern.

3b. Downgrade Mongos Instances

Mongos does not hold data and can be downgraded without a rolling procedure. Stop each mongos instance, replace the binary, and restart:

javascript
sudo systemctl stop mongos
# Replace binary via package manager (same apt/yum commands as above)
sudo systemctl start mongos
Mongos version must not exceed the config server or shard version. Never run a mongos binary that is a higher major version than your mongod instances. During the transition, briefly running a 7.0 mongos against 6.0 shards can cause routing errors. Downgrade mongos only after all mongod instances are on 6.0.

Step 4 — Verify and Test After Downgrade

Check MongoDB Version on All Nodes

javascript
db.adminCommand({ buildInfo: 1 })
// Confirm "version" field shows "6.0.x" on every member

Confirm FCV

javascript
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })
// Should return: { featureCompatibilityVersion: { version: '6.0' }, ok: 1 }

Run Replica Set Status Check

javascript
rs.status()
// All members: PRIMARY or SECONDARY
// No members in RECOVERING or UNKNOWN

Validate Application Connectivity

Run your application's connection health check against the new primary. Confirm that the specific workflows that failed on 7.0 now operate correctly. If you have integration tests, this is the time to run them against the live cluster.

Check Oplog Window

After the downgrade, the oplog window may have contracted during the rolling restart. Verify it is within acceptable bounds for your recovery objectives:

javascript
rs.printReplicationInfo()
// Review "log length start to end" and "oplog first event time"

Common Issues During MongoDB Downgrade

FCV Refuses to Lower

Symptom: setFeatureCompatibilityVersion: "6.0" returns an error mentioning a specific feature or collection.

Fix: Identify and drop or modify the incompatible object. For compound wildcard indexes, use db.collection.getIndexes() to locate them and db.collection.dropIndex() to remove them. Re-run the FCV command after each removal until it succeeds.

Secondary Fails to Start After Binary Replacement

Symptom: mongod refuses to start after downgrade, logs show a fatal error about incompatible data files.

Fix: This usually means the FCV was not successfully set to "6.0" before binary replacement, or there is a WiredTiger storage format incompatibility. Restore from backup — there is no safe path forward from this state without a fresh sync.

If you need to resync a secondary from scratch after restoring the primary:

javascript
// On the affected secondary, from mongo shell:
db.adminCommand({ resync: 1 })
// Or delete the data directory contents and restart to trigger initial sync

Election Loops After Primary Stepdown

Symptom: After stepping down the primary, the replica set cannot elect a new primary. rs.status() shows all members in SECONDARY state.

Fix: This can happen if the remaining members do not have enough votes for a majority. Check that at least two voting members are healthy and reachable. If a secondary is in RECOVERING state, wait for it to finish before triggering stepdown. You can force an election if needed:

javascript
rs.freeze(0) // On a specific secondary — releases the freeze and allows it to call an election

Application Still Reporting 7.0 Errors After Downgrade

Symptom: Application drivers or connectors continue throwing errors even though MongoDB is now on 6.0.

Fix: Confirm the driver is connecting to the new primary (the connection string may be using a specific host rather than the replica set name). Clear any client-side connection pools and verify with db.hello() that the node being connected to reports version 6.0.

javascript
db.hello()
// Check "me" field and "hosts" — confirm primary is a 6.0 node
Key Takeaways
  • Set FCV to "6.0" while still running 7.0 binaries — this must happen before any binary is replaced, and it replicates automatically to all secondaries.
  • Drop any 7.0-specific features (compound wildcard indexes, etc.) before lowering FCV, or the command will fail.
  • Always downgrade secondaries first, then step down and downgrade the primary — never touch the primary first.
  • For sharded clusters: downgrade shards, then config servers, then mongos — in that order.
  • Verify replica set health and oplog window after every member replacement, not just at the end.
  • If a secondary cannot start after binary replacement, restore from backup — there is no partial recovery path from binary/data format mismatch.
  • Test application connectivity and run integration checks immediately after the full downgrade is complete.

Working with JusDB on MongoDB Version Management

JusDB manages MongoDB upgrades and downgrades for engineering teams — planning compatibility windows, coordinating rolling restarts, and verifying replica set health throughout the process. Our DBAs have executed dozens of MongoDB version migrations without downtime.

Explore JusDB MongoDB Management →  |  Talk to a DBA

Related reading:

Share this article