The "socket hang up" error in MongoDB occurs when a network connection between the MongoDB client and server is abruptly terminated. This typically happens due to network timeouts, firewall issues, or server-side connection limits. The error indicates that the TCP socket was closed before the request could complete, often during long-running queries or bulk operations.
The "socket hang up" error in MongoDB is a network-level error that occurs when the TCP connection between a MongoDB client (application, driver, or tool) and the MongoDB server is unexpectedly closed before a request completes. This is not a MongoDB-specific error but rather a Node.js/network error that surfaces when using MongoDB drivers. When a MongoDB client establishes a connection to the server, it opens a TCP socket for communication. If this socket is closed prematurely—either by the client, server, or an intermediate network device—any ongoing operations will fail with "socket hang up." Common scenarios where this error appears: - **Long-running queries**: Queries that take longer than the configured socket timeout - **Bulk operations**: Large insert/update operations that exceed network timeouts - **Network instability**: Intermittent network connectivity or packet loss - **Firewall/proxy interference**: Middleware that terminates idle connections - **Server-side limits**: MongoDB server closing connections due to max connection limits or idle timeout - **Load balancer timeouts**: When MongoDB is behind a load balancer with aggressive timeout settings The error is particularly common in Node.js applications using the MongoDB Node.js driver, as Node.js uses non-blocking I/O and can have many concurrent connections. When a socket times out or is closed, the driver emits this error to indicate the connection was terminated before the operation completed.
The most common fix is to increase the socket timeout in your MongoDB connection string. The default is often too low for production workloads.
Node.js MongoDB driver example:
const { MongoClient } = require('mongodb');
// Increase socketTimeoutMS to 30000ms (30 seconds)
const uri = 'mongodb://localhost:27017/mydb?socketTimeoutMS=30000&connectTimeoutMS=30000';
const client = new MongoClient(uri);
// Or with connection options
const client = new MongoClient(uri, {
socketTimeoutMS: 30000,
connectTimeoutMS: 30000,
serverSelectionTimeoutMS: 30000,
});Mongoose example:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mydb', {
socketTimeoutMS: 30000,
connectTimeoutMS: 30000,
serverSelectionTimeoutMS: 30000,
});Recommended timeout values:
- socketTimeoutMS: 30000 (30 seconds) for most applications
- For long-running aggregation queries: 60000-120000 (1-2 minutes)
- For bulk operations: Adjust based on data volume
MongoDB servers have connection limits that can cause sockets to be closed. Check your server configuration:
Check current connections:
# In mongosh or mongo shell
db.serverStatus().connectionsCheck max connections setting:
# In mongosh
db.adminCommand({getParameter: 1, maxIncomingConnections: 1})Adjust max connections in mongod.conf:
# /etc/mongod.conf
net:
port: 27017
maxIncomingConnections: 1000 # Increase from default 65536 if neededFor MongoDB Atlas:
Connection limits are based on your cluster tier. Check your Atlas dashboard:
1. Go to your cluster → Settings → Additional Settings
2. Check "Connection Limits"
3. Upgrade tier if hitting limits
Monitor connection usage:
# Continuous monitoring
watch -n 5 "echo 'db.serverStatus().connections' | mongosh --quiet"Connection pool exhaustion can lead to socket hang ups. Configure appropriate pool sizes:
Node.js MongoDB driver:
const client = new MongoClient(uri, {
maxPoolSize: 50, // Maximum connections in pool
minPoolSize: 10, // Minimum connections to maintain
maxIdleTimeMS: 60000, // Close idle connections after 60s
waitQueueTimeoutMS: 10000, // Wait 10s for connection from pool
});Mongoose connection pooling:
mongoose.connect(uri, {
maxPoolSize: 50,
minPoolSize: 10,
socketTimeoutMS: 30000,
});Calculate optimal pool size:
- Web servers: maxPoolSize = (max concurrent requests) × (average queries per request)
- Background jobs: Smaller pool (5-10 connections)
- Microservices: 10-50 connections depending on load
Monitor pool usage:
// Log pool metrics periodically
setInterval(() => {
const poolStats = client.topology?.s?.pool?.poolStats;
if (poolStats) {
console.log('Pool stats:', {
total: poolStats.totalConnectionCount,
available: poolStats.availableConnectionCount,
waitQueue: poolStats.waitQueueSize,
});
}
}, 30000);Network devices between client and MongoDB can terminate connections:
Test network connectivity:
# Test basic connectivity
ping mongodb-host
# Test MongoDB port
nc -zv mongodb-host 27017
# Test with timeout
timeout 30 nc -zv mongodb-host 27017Check firewall rules:
# Linux iptables
sudo iptables -L -n | grep 27017
# Linux firewalld
sudo firewall-cmd --list-all | grep 27017
# Windows firewall
netsh advfirewall firewall show rule name=all | findstr 27017Adjust firewall/idle timeout settings:
- AWS Security Groups: Default idle timeout is 350 seconds
- Azure NSG: Default is 4 minutes
- GCP Firewall: Default varies by rule type
- Corporate firewalls: Often 5-30 minute idle timeouts
For load balancers (AWS ELB/ALB, Nginx, HAProxy):
# Nginx example - increase proxy timeout
location / {
proxy_pass http://mongodb-backend;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}AWS ELB/ALB idle timeout: Default 60 seconds, increase if needed:
aws elb modify-load-balancer-attributes \
--load-balancer-name my-lb \
--load-balancer-attributes "{\"ConnectionSettings\":{\"IdleTimeout\":300}}"Transient network issues can cause socket hang ups. Implement retry logic:
Node.js with MongoDB driver:
async function queryWithRetry(collection, query, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await collection.find(query).toArray();
} catch (error) {
lastError = error;
// Only retry on socket hang up or network errors
if (error.message.includes('socket hang up') ||
error.name === 'MongoNetworkError') {
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
console.log('Attempt ' + attempt + ' failed, retrying in ' + delay + 'ms');
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
// Non-retryable error
throw error;
}
}
throw lastError;
}
// Usage
const results = await queryWithRetry(db.collection('users'), { active: true });Using a library like p-retry:
npm install p-retryconst retry = require('p-retry');
async function runQuery() {
return await db.collection('users').find({ active: true }).toArray();
}
const result = await retry(runQuery, {
retries: 3,
factor: 2, // exponential backoff factor
minTimeout: 1000,
maxTimeout: 10000,
onFailedAttempt: error => {
console.log('Attempt ' + error.attemptNumber + ' failed. ' + error.retriesLeft + ' retries left');
},
});Configure MongoDB driver retry options:
const client = new MongoClient(uri, {
retryWrites: true,
retryReads: true,
// Driver will automatically retry certain operations
});Long-running queries are a common cause of socket timeouts. Optimize your queries:
Identify slow queries:
# Enable profiling
db.setProfilingLevel(1, { slowms: 100 })
# Check profiled queries
db.system.profile.find().sort({ ts: -1 }).limit(10).pretty()Use explain() to analyze queries:
// In your application
const explain = await collection.find({ userId: '123' })
.explain('executionStats');
console.log('Query stats:', explain.executionStats);Add appropriate indexes:
// Create index on frequently queried fields
await collection.createIndex({ userId: 1 });
await collection.createIndex({ createdAt: -1 });
await collection.createIndex({ status: 1, priority: -1 });Limit result sets:
// Bad: Fetching all documents
const allUsers = await collection.find({}).toArray();
// Good: Use pagination
const users = await collection.find({})
.limit(100)
.skip(0)
.toArray();
// Good: Use projection to fetch only needed fields
const users = await collection.find({}, {
projection: { name: 1, email: 1, _id: 0 }
}).toArray();Batch large operations:
// Bad: Single large insert
await collection.insertMany(millionDocuments);
// Good: Batch in chunks
const batchSize = 1000;
for (let i = 0; i < millionDocuments.length; i += batchSize) {
const batch = millionDocuments.slice(i, i + batchSize);
await collection.insertMany(batch);
console.log('Inserted ' + (i + batchSize) + ' documents');
}Understanding TCP Keepalive:
TCP keepalive is a mechanism to detect dead connections. When enabled, the OS sends periodic packets to verify the connection is still alive. If no response is received after several retries, the connection is closed.
Adjust TCP keepalive settings:
# Linux: Check current settings
sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_intvl
sysctl net.ipv4.tcp_keepalive_probes
# Linux: Increase keepalive time (default 7200 seconds = 2 hours)
sudo sysctl -w net.ipv4.tcp_keepalive_time=300 # 5 minutes
sudo sysctl -w net.ipv4.tcp_keepalive_intvl=75 # 75 seconds between probes
sudo sysctl -w net.ipv4.tcp_keepalive_probes=9 # 9 probes before closing
# Make permanent
echo "net.ipv4.tcp_keepalive_time = 300" >> /etc/sysctl.conf
echo "net.ipv4.tcp_keepalive_intvl = 75" >> /etc/sysctl.conf
echo "net.ipv4.tcp_keepalive_probes = 9" >> /etc/sysctl.conf
sysctl -pMongoDB Atlas Specific Considerations:
1. Connection Limits: Each cluster tier has specific connection limits
2. Idle Timeout: Atlas closes idle connections after 30 minutes
3. Load Balancer: Atlas uses a load balancer with its own timeout settings
4. IP Whitelisting: Ensure your IP is whitelisted in Atlas Network Access
Diagnostic Queries:
// Check current operations
db.currentOp()
// Check connection statistics
db.serverStatus().connections
db.serverStatus().network
// Check replica set status
rs.status()
// Check oplog window
use local
db.oplog.rs.find().sort({$natural: -1}).limit(1).pretty()When to Consider Alternative Solutions:
1. Change Streams instead of polling: For real-time data, use change streams rather than frequent queries
2. Aggregation Pipeline Optimization: Use $match early, $project to limit fields, $limit when possible
3. Read Preference: For read-heavy applications, use secondary nodes with readPreference: 'secondary'
4. Connection String Options: Explore other connection string parameters like maxStalenessSeconds, localThresholdMS
Monitoring and Alerting:
Set up monitoring for:
- Connection count trends
- Query duration percentiles
- Network error rates
- Retry attempt counts
- Pool exhaustion events
Use tools like:
- MongoDB Atlas Monitoring
- Datadog MongoDB integration
- New Relic MongoDB monitoring
- Custom metrics with Prometheus + mongodb_exporter
MongoOperationTimeoutError: Operation timed out
How to fix "MongoOperationTimeoutError: Operation timed out" in MongoDB
MongoServerError: PlanExecutor error during aggregation :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation.
How to fix "QueryExceededMemoryLimitNoDiskUseAllowed" in MongoDB
MissingSchemaError: Schema hasn't been registered for model
How to fix "MissingSchemaError: Schema hasn't been registered for model" in MongoDB/Mongoose
CastError: Cast to ObjectId failed for value "abc123" at path "_id"
How to fix "CastError: Cast to ObjectId failed" in MongoDB
OverwriteModelError: Cannot overwrite model once compiled
How to fix "OverwriteModelError: Cannot overwrite model once compiled" in MongoDB