BackendNode.jsMongoDBProductionBackendExpress

Node.js + MongoDB Best Practices for Production

Production-ready patterns for Node.js and MongoDB applications — error handling, logging, health checks, graceful shutdown, and deployment strategies.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

April 24, 2024 9 min read

Why Production Requires Different Thinking

A Node.js app that works on localhost can still fail spectacularly in production. Production brings real load, network failures, memory pressure, and the need for observability when things go wrong at 3am. Building for production from the start — even on small projects — saves you painful incidents later.

Centralized Error Handling

Create a single error handling middleware in Express that catches all errors, formats them consistently, and returns appropriate HTTP status codes. Distinguish between operational errors (user input validation failures, not-found errors) and programming errors (null pointer exceptions, unhandled promise rejections). Log programming errors and send alerts — they indicate bugs that need fixing. Operational errors are expected and should return clear messages to the client without logging stack traces.

Structured Logging with Winston or Pino

console.log is not logging. Use a proper logging library like Pino (fastest) or Winston (most flexible). Log in JSON format so log aggregators (Datadog, CloudWatch, Logtail) can parse and search your logs. Include request ID, user ID, and timestamp in every log entry. Log at the right levels: debug for development, info for significant events, warn for recoverable issues, error for failures.

Health Check Endpoints

Add a GET /health endpoint that returns your application's status including database connectivity. Deployment platforms (Render, Railway, AWS ECS) use health checks to detect unhealthy instances and restart them. A proper health check verifies not just that the server is running, but that it can actually serve requests — including database connection status.

Graceful Shutdown

Listen for SIGTERM and SIGINT signals and shut down gracefully: stop accepting new requests, wait for in-flight requests to complete, close database connections, then exit. Without graceful shutdown, in-flight requests are dropped when your container restarts during deployments. Mongoose's connection.close() and server.close() in your shutdown handler prevent this.

Environment Configuration and Secrets

Never commit secrets to Git — ever. Use environment variables for all configuration: database URLs, JWT secrets, API keys, and CORS origins. Use dotenv for local development and your hosting platform's environment variable management for production. Validate required environment variables at startup using a schema — fail fast if a required variable is missing rather than discovering it at runtime when a feature is first used.

Share this article

All posts
#Node.js#MongoDB#Production#Backend#Express
Abdur Razzak — Full Stack Web Developer

Free Consultation

Got a Project Idea? Let's Talk.