Thousands of MongoDB databases have been breached for one embarrassing reason: they were left open to the internet with no authentication. Running MongoDB well is not only about clever schemas and fast queries; it is about locking the door and operating the database responsibly. This final CodeYourCraft lesson is a production checklist covering security, reliability, and performance habits.
A fresh self-managed MongoDB install does not require a password, which is safe only because it binds to localhost. The moment a server is reachable from elsewhere, it must require credentials. Create an administrative user and turn authorization on:
use admin
db.createUser({
user: 'siteAdmin',
pwd: passwordPrompt(),
roles: [ { role: 'userAdminAnyDatabase', db: 'admin' } ]
})# /etc/mongod.conf
security:
authorization: enabled
net:
bindIp: 127.0.0.1 # never 0.0.0.0 without a firewallAtlas enforces authentication and IP allowlists by default, one more reason beginners should start there.
Applications should never connect as an admin. Give each service its own user with the narrowest built-in role that works, usually readWrite on a single database:
use shop
db.createUser({
user: 'shopApp',
pwd: passwordPrompt(),
roles: [ { role: 'readWrite', db: 'shop' } ]
})Analytics dashboards get read-only users. Backup jobs get the backup role. If credentials leak, the blast radius stays small.
Enable TLS so data cannot be sniffed in transit (Atlas requires it). Use disk or cloud encryption at rest. Keep connection strings in environment variables or a secrets manager, never in git, and rotate any credential that has ever been committed. Client-Side Field Level Encryption can additionally encrypt sensitive fields, such as national ID numbers, before they leave your application.
Passing raw request objects into queries lets attackers smuggle operators. If req.body.username is { $ne: null }, a naive login filter matches any user:
// DANGEROUS
const user = await User.findOne({ username: req.body.username })
// SAFE: force the expected type
const user = await User.findOne({ username: String(req.body.username) })Validate and sanitize all input, and prefer schema-driven casting through Mongoose or a validation library.
Production MongoDB runs as a replica set of at least three nodes, giving automatic failover and safe write acknowledgment with w: 'majority'. Back up on a schedule using Atlas backups or mongodump, and periodically restore a backup to a test environment; an untested backup is a hope, not a plan.
Authentication enabled and admin user created; per-service least-privilege users; network access restricted by firewall, VPC peering, or IP allowlist; TLS on; secrets in environment variables; input validated against injection; replica set with majority writes for critical data; scheduled and tested backups; slow query monitoring switched on. If you can tick every box, your MongoDB deployment is in better shape than most.
Congratulations, you have completed the CodeYourCraft MongoDB series! From here, practice by building a small API with Node.js and Mongoose, and explore advanced topics like sharding, change streams, and Atlas Search.