MongoDB Error
Topology Destroyed
Database Connection
MongoError
Error Handling

mongoError Topology was destroyed

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The error MongoError: Topology was destroyed usually means your code tried to use MongoDB after the driver had already torn down its connection state. In practice, that almost always comes back to client lifecycle mistakes: closing too early, reusing stale handles, or shutting down while async work is still in flight.

What the Driver Is Telling You

In the Node.js MongoDB driver, the topology is the driver's internal view of the MongoDB deployment it is connected to. That deployment may be a standalone server, a replica set, or a sharded cluster.

Once that topology is destroyed, the driver no longer considers the connection usable. Any collection or database handle derived from that client becomes unsafe to use because the thing underneath it is gone.

The Classic Mistake: Connect and Close Per Operation

A common anti-pattern is creating a new client inside every helper and closing it immediately after the query.

javascript
1const { MongoClient } = require("mongodb");
2
3async function findUser(email) {
4  const client = new MongoClient(process.env.MONGODB_URI);
5
6  try {
7    await client.connect();
8    return await client.db("app").collection("users").findOne({ email });
9  } finally {
10    await client.close();
11  }
12}

This looks neat, but it becomes fragile fast when the rest of the application starts caching collection handles or overlapping async work. The driver lifecycle ends before the wider code path is really done with it.

A Better Pattern: One Client, Long Lifetime

Most applications should create one MongoClient, connect once during startup, and close it only during process shutdown.

javascript
1const { MongoClient } = require("mongodb");
2
3const client = new MongoClient(process.env.MONGODB_URI);
4let db;
5
6async function connectDb() {
7  if (!db) {
8    await client.connect();
9    db = client.db("app");
10  }
11
12  return db;
13}
14
15async function listOrders() {
16  const database = await connectDb();
17  return database.collection("orders").find({}).toArray();
18}

This structure makes ownership clear. One place owns the client, and the rest of the code asks for a database handle instead of improvising connection setup and teardown repeatedly.

Other Situations That Trigger It

Premature close() is the most common cause, but not the only one. You can also see this error when:

  • test teardown closes MongoDB before pending async assertions finish
  • your app starts shutdown while requests are still using the database
  • code caches a collection globally but swaps or closes the underlying client elsewhere
  • connection-failure recovery logic leaves stale references behind

The common thread is always the same: your application is still acting as if the client is alive after the driver has already abandoned that topology.

Structure Shutdown Carefully

Shutdown logic should stop accepting new work before it closes MongoDB. Otherwise, one part of the app can still be processing a request while another part closes the client.

javascript
1process.on("SIGTERM", async () => {
2  try {
3    await client.close();
4  } finally {
5    process.exit(0);
6  }
7});

In a real server, you would usually stop the HTTP listener first, wait for in-flight requests to finish, and then close the database connection last.

Common Pitfalls

The biggest mistake is reusing collection or database objects after the parent client has been closed. Those handles are not magical standalone connections.

Another common issue is mixing two patterns in one codebase, such as cached globals in one module and one-client-per-request helpers in another. That kind of lifecycle mismatch produces exactly the sort of stale-state bug this error is warning about.

Be especially careful in tests. If the failure appears only in CI or only after afterAll, teardown timing is a strong suspect.

Finally, avoid papering over the problem with blind reconnect loops. Reconnection logic belongs in a deliberate connection-management layer, not scattered across every query helper.

Summary

  • 'Topology was destroyed usually means your MongoDB client was closed or invalidated before an operation finished.'
  • Prefer one long-lived MongoClient per process instead of connect-close cycles around every query.
  • Do not reuse database or collection handles after the underlying client is gone.
  • Shut down request handling before closing MongoDB during process termination.
  • If the error appears in tests, inspect teardown timing and stale shared state first.

Course illustration
Course illustration

All Rights Reserved.