What Makes MongoDB Unique to Monitor
MongoDB's document model and query architecture create monitoring challenges that don't exist in traditional SQL databases. Indexes in MongoDB are not enforced by schema — a missing index silently degrades from milliseconds to seconds as collections grow. Connection pooling semantics differ from SQL: MongoDB uses a per-host pool rather than per-database, and pool exhaustion manifests as application-level timeouts rather than connection errors.
Most generic observability tools capture MongoDB operation counts and latency averages, but miss the metrics that actually predict trouble: connection pool utilization, index hit ratio, oplog replication lag, and the distribution of wiredTiger cache reads vs. disk reads. These are the signals that distinguish a healthy MongoDB cluster from one that is 2 weeks away from a severe production incident.
The good news: the MongoDB driver emits rich CommandStartedEvent and CommandSucceededEvent events for every operation. Node.js's Mongoose and the native MongoDB driver both expose monitoring hooks that make comprehensive instrumentation possible with minimal application code changes.
The Five Metrics That Actually Matter
Connection pool utilization is the most critical MongoDB metric for Node.js applications. Every concurrent database operation consumes a connection from the pool. When the pool is exhausted, new requests queue up and eventually time out. The default Mongoose pool size is 5 — severely undersized for production applications handling concurrent requests.
- Connection pool utilization: currentConnections / maxConnections. Alert at > 80%. The post-mortem example in this blog series was caused by pool exhaustion.
- Wait queue length: requests waiting for an available connection. Any non-zero value under normal load is a red flag.
- Slow query rate: queries taking > 100ms. Track as a rolling percentage of total queries.
- Index miss rate: collection scans (COLLSCAN in explain output) as a percentage of total queries. Should be < 0.1% in production.
- Replication lag: seconds behind primary for replica set members. Alert at > 10 seconds.
Instrumenting the MongoDB Driver in Node.js
The MongoDB Node.js driver exposes a monitoring event system that emits command events for every database operation. By subscribing to these events, you can track operation duration, detect slow queries, and measure pool utilization — all without modifying your business logic.
import { MongoClient, MongoClientOptions } from 'mongodb';
function createMongoClientWithMonitoring(uri: string): MongoClient {
const options: MongoClientOptions = {
maxPoolSize: 50, // Production-appropriate pool size
minPoolSize: 5, // Keep connections warm
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
// Enable all monitoring events
monitorCommands: true,
};
const client = new MongoClient(uri, options);
const slowQueryThresholdMs = 100;
// Track command durations for slow query detection
client.on('commandStarted', (event) => {
(event as any)._startTime = Date.now();
});
client.on('commandSucceeded', (event) => {
const durationMs = Date.now() - ((event as any)._startTime ?? Date.now());
// Emit to your observability platform
metrics.histogram('mongodb.command.duration_ms', durationMs, {
command: event.commandName,
database: event.databaseName,
});
if (durationMs > slowQueryThresholdMs) {
logger.warn({
event: 'mongodb.slow_query',
command: event.commandName,
database: event.databaseName,
durationMs,
query: JSON.stringify(event.reply).slice(0, 500),
}, 'Slow MongoDB query detected');
}
});
client.on('commandFailed', (event) => {
metrics.increment('mongodb.command.errors', {
command: event.commandName,
error: event.failure.message,
});
});
// Monitor connection pool
client.on('connectionPoolCreated', (event) => {
logger.info({ event: 'mongodb.pool.created', address: event.address }, 'MongoDB connection pool created');
});
client.on('connectionCheckOutFailed', (event) => {
// This fires when pool is exhausted — critical signal
metrics.increment('mongodb.pool.checkout_failed', { reason: event.reason });
logger.error({ event: 'mongodb.pool.exhausted', reason: event.reason }, 'MongoDB connection pool exhausted');
});
return client;
}Detecting N+1 Queries and Missing Indexes
N+1 queries are the most common performance anti-pattern in MongoDB + Node.js applications: a loop that executes one database query per item in a result set. A page that loads 50 users and then queries each user's profile generates 51 queries instead of 2. At low traffic, this is imperceptible. At production scale, it collapses your connection pool and degrades every concurrent user's experience.
MongoDB's explain() plan reveals whether a query uses an index (IXSCAN) or performs a collection scan (COLLSCAN). A COLLSCAN on a collection with 1 million documents is a query that reads every document — latency scales linearly with collection size. In production, automatically detecting and logging COLLSCAN patterns allows you to identify missing indexes before they cause incidents.
// Automated slow query analysis with explain() plan logging
async function analyzeSlowQuery(
collection: Collection,
filter: object,
durationMs: number
): Promise<void> {
if (durationMs < 100) return; // Only analyze slow queries
const plan = await collection.find(filter).explain('executionStats');
const stage = plan.queryPlanner?.winningPlan?.stage;
if (stage === 'COLLSCAN') {
logger.error({
event: 'mongodb.missing_index',
collection: collection.collectionName,
filter: JSON.stringify(filter),
durationMs,
docsExamined: plan.executionStats?.totalDocsExamined,
docsReturned: plan.executionStats?.totalKeysExamined,
}, 'Collection scan detected — index missing');
// Auto-create an alert in ObservabilityOS
await observability.createAlert({
title: `Missing index on ${collection.collectionName}`,
severity: 'high',
metadata: { filter, durationMs },
});
}
}Setting Up MongoDB Monitoring with ObservabilityOS
ObservabilityOS's Node.js SDK includes built-in MongoDB monitoring that wraps the driver event system automatically. Install the SDK and add the MongoDB monitor plugin — all the slow query detection, pool monitoring, and index analysis from this guide is handled automatically.
import { init, mongoMonitor } from '@observability-os/sdk';
// Initialize with MongoDB monitoring plugin
init({
apiKey: process.env.OBSERVABILITY_API_KEY,
service: 'my-api',
plugins: [
mongoMonitor({
slowQueryThresholdMs: 100,
logExplainOnSlowQuery: true,
alertOnPoolExhaustion: true,
}),
],
});
// Your existing Mongoose connection — no other changes needed
await mongoose.connect(process.env.MONGODB_URI);Stop debugging production in the dark
ObservabilityOS gives every engineer AI-powered incident intelligence. Zero config. Connects in 5 minutes.
About the Author
ObservabilityOS Team
Core Engineering & DevRel
The core engineering, site reliability, and developer relations team behind ObservabilityOS. We build AI-native observability infrastructure to eliminate 3 AM firefighting.