Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Node.js Tutorial

Node HOME Node Intro Node Get Started Node JS Requirements Node.js vs Browser Node Cmd Line Node V8 Engine Node Architecture Node Event Loop

Asynchronous

Node Async Node Promises Node Async/Await Node Errors Handling

Module Basics

Node Modules Node ES Modules Node NPM Node package.json Node NPM Scripts Node Manage Dep Node Publish Packages

Core Modules

HTTP Module HTTPS Module File System (fs) Path Module OS Module URL Module Events Module Stream Module Buffer Module Crypto Module Timers Module DNS Module Assert Module Util Module Readline Module

JS & TS Features

Node ES6+ Node Process Node TypeScript Node Adv. TypeScript Node Lint & Formatting

Building Applications

Node Frameworks Express.js Middleware Concept REST API Design API Authentication Node.js with Frontend

Database Integration

MySQL Get Started MySQL Create Database MySQL Create Table MySQL Insert Into MySQL Select From MySQL Where MySQL Order By MySQL Delete MySQL Drop Table MySQL Update MySQL Limit MySQL Join
MongoDB Get Started MongoDB Create DB MongoDB Collection MongoDB Insert MongoDB Find MongoDB Query MongoDB Sort MongoDB Delete MongoDB Drop Collection MongoDB Update MongoDB Limit MongoDB Join

Advanced Communication

GraphQL Socket.IO WebSockets

Testing & Debugging

Node Adv. Debugging Node Testing Apps Node Test Frameworks Node Test Runner

Node.js Deployment

Node Env Variables Node Dev vs Prod Node CI/CD Node Security Node Deployment

Perfomance & Scaling

Node Logging Node Monitoring Node Performance Child Process Module Cluster Module Worker Threads

Node.js Advanced

Microservices Node WebAssembly HTTP2 Module Perf_hooks Module VM Module TLS/SSL Module Net Module Zlib Module Real-World Examples

Hardware & IoT

RasPi Get Started RasPi GPIO Introduction RasPi Blinking LED RasPi LED & Pushbutton RasPi Flowing LEDs RasPi WebSocket RasPi RGB LED WebSocket RasPi Components

Node.js Reference

Built-in Modules EventEmitter (events) Worker (cluster) Cipher (crypto) Decipher (crypto) DiffieHellman (crypto) ECDH (crypto) Hash (crypto) Hmac (crypto) Sign (crypto) Verify (crypto) Socket (dgram, net, tls) ReadStream (fs, stream) WriteStream (fs, stream) Server (http, https, net, tls) Agent (http, https) Request (http) Response (http) Message (http) Interface (readline)

Resources & Tools

Node.js Compiler Node.js Server Node.js Quiz Node.js Exercises Node.js Syllabus Node.js Study Plan Node.js Certificate

Node.js: Development vs Production


Differences between Development and Production

This page covers the key differences between development and production environments in Node.js applications and best practices for managing both effectively.

Key Differences at a Glance

Development

  • Verbose logging
  • Detailed error messages
  • Hot-reloading enabled
  • Unminified code
  • Mock data/stubs

Production

  • Minimal logging
  • Generic error messages
  • Optimized performance
  • Minified and bundled code
  • Real data/services

The NODE_ENV Environment Variable

In Node.js, the NODE_ENV environment variable is a convention used to determine the environment in which an application is running.

It's commonly set to either 'development' or 'production', though other values like 'test' or 'staging' are also used.

Note: Many Node.js frameworks and libraries (like Express, React, Vue, etc.) use NODE_ENV to enable or disable certain features and optimizations.

Setting NODE_ENV

Command Line

# Windows Command Prompt
set NODE_ENV=production
node app.js

# Windows PowerShell
$env:NODE_ENV="production"
node app.js

# Linux/macOS
export NODE_ENV=production
node app.js

package.json Scripts

{
  "scripts": {
    "start": "NODE_ENV=production node app.js",
    "dev": "NODE_ENV=development nodemon app.js",
    "test": "NODE_ENV=test jest"
  }
}

Using cross-env (cross-platform)

npm install --save-dev cross-env
{
  "scripts": {
    "start": "cross-env NODE_ENV=production node app.js"
  }
}

Using NODE_ENV in Your Application

// Simple environment check
const isProduction = process.env.NODE_ENV === 'production';
const isDevelopment = !isProduction;

// Environment-specific configuration
const config = {
  port: process.env.PORT || 3000,
  db: {
   host: isProduction ? 'prod-db.example.com' : 'localhost',
   name: isProduction ? 'myapp_prod' : 'myapp_dev'
 },
  logging: {
   level: isProduction ? 'warn' : 'debug',
   prettyPrint: !isProduction
  }
};

// Express.js example
const express = require('express');
const app = express();

Note: Setting NODE_ENV=production can improve application performance by up to 35%, as some packages apply optimizations based on this setting.


Configuration Management

Different environments typically require different configurations for databases, APIs, logging, and other services.

Environment-Specific Configuration

Configuration with dotenv

// Install dotenv: npm install dotenv
require('dotenv').config(); // Loads .env file contents into process.env

// config.js
module.exports = {
  development: {
    port: 8080,
    database: 'mongodb://localhost:27017/myapp_dev',
    logLevel: 'debug',
    apiKeys: {
      thirdPartyService: process.env.DEV_API_KEY
    }
  },
  test: {
    port: 3001,
    database: 'mongodb://localhost:27017/myapp_test',
    logLevel: 'info',
    apiKeys: {
      thirdPartyService: process.env.TEST_API_KEY
    }
  },
  production: {
    port: process.env.PORT || 8080,
    database: process.env.DATABASE_URL,
    logLevel: 'error',
    apiKeys: {
      thirdPartyService: process.env.PROD_API_KEY
    }
  }
};

const env = process.env.NODE_ENV || 'development';
module.exports.current = module.exports[env];

Configuration Files

Common approaches to configuration management include:

  • Environment files: Using .env files with the dotenv package
  • Configuration objects: Creating environment-specific configuration objects
  • Configuration services: Using external services like AWS Parameter Store, Vault, or Consul

Security Warning: Never commit sensitive information like API keys, database credentials, or secrets to version control. Always use environment variables or secure configuration services for sensitive data.


Error Handling

Error handling strategies should differ between development and production environments:

Development Environment

  • Display detailed error messages and stack traces
  • Use verbose logging to aid debugging
  • Crash early on errors to identify issues quickly
  • Enable source maps for better debugging
  • Provide interactive debugging tools

Production Environment

  • Hide implementation details from error responses
  • Log errors for internal use but return generic error messages
  • Implement proper error recovery mechanisms
  • Use structured logging for better analysis
  • Implement circuit breakers for external services

Environment-Specific Error Handling

const express = require('express');
const app = express();

app.get('/api/data', (req, res) => {
  try {
    // Some operation that might fail
    throw new Error('Something went wrong');
  } catch (error) {
    // Log the error internally (always do this)
    console.error('Error occurred:', error);

    // Provide different responses based on environment
    if (process.env.NODE_ENV === 'production') {
     // In production: generic error message
     return res.status(500).json({
      error: 'An unexpected error occurred'
     });
    } else {
     // In development: detailed error information
     return res.status(500).json({
      error: error.message,
      stack: error.stack,
      details: 'This detailed error is only shown in development'
     });
    }
  }
});

app.listen(8080);

Logging Strategies

Logging requirements differ significantly between development and production:

Development Logging

  • Verbose logging with detailed information
  • Human-readable format with colors
  • Console output for immediate feedback
  • Debug and trace level logging enabled
  • No log rotation needed

Production Logging

  • Structured logging (JSON format)
  • Appropriate log levels (warn/error)
  • Log rotation and retention policies
  • Centralized log aggregation
  • Performance monitoring integration

Environment-Specific Logging with Winston

const winston = require('winston');

// Define different logging configurations per environment
const logger = winston.createLogger({
  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
  format: process.env.NODE_ENV === 'production'
    ? winston.format.json()
    : winston.format.combine(
     winston.format.colorize(),
     winston.format.simple()
    ),
  defaultMeta: { service: 'user-service' },
  transports: [
    // Always log errors to a file
    new winston.transports.File({
     filename: 'error.log',
     level: 'error'
    }),

    // In production, save all logs to a file
    ...(process.env.NODE_ENV === 'production'
     ? [new winston.transports.File({ filename: 'combined.log' })]
     : []),

    // In development, log to the console
    ...(process.env.NODE_ENV !== 'production'
     ? [new winston.transports.Console()]
     : [])
  ],
});

logger.info('Application started');
logger.debug('This debug message appears only in development');

For more details on logging, see the Node.js Logging tutorial.


Performance Optimizations

Production environments should be optimized for performance and reliability:

Development Focus

  • Fast refresh and hot module replacement
  • Source maps for debugging
  • Detailed error overlays
  • Unminified code
  • Development tools integration

Production Optimizations

  • Code minification and tree-shaking
  • Asset optimization and compression
  • Content Delivery Network (CDN) usage
  • Browser caching headers
  • Performance monitoring

Performance Considerations

  • Optimized code bundling and minification
  • Caching strategies
  • Cluster mode to utilize multiple CPU cores
  • Memory and CPU optimizations
  • Content compression

Running in Cluster Mode in Production

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (process.env.NODE_ENV === 'production' && cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
    // Replace the dead worker
    cluster.fork();
  });
} else {
  // Workers can share a TCP connection
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

Security Considerations

Security practices should be more stringent in production environments:

Production Security Measures

  • Helmet: Set security-related HTTP headers
  • Rate limiting: Protect against brute force and DoS attacks
  • CSRF protection: Prevent cross-site request forgery
  • Input validation: Sanitize all user inputs
  • HTTPS: Encrypt all communications
  • Dependency scanning: Check for vulnerabilities in dependencies

Security Middleware for Production

const express = require('express');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const app = express();

// Apply security middleware in production
if (process.env.NODE_ENV === 'production') {
  // Set security headers
  app.use(helmet());

  // Enable rate limiting
  const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // limit each IP to 100 requests per windowMs
    message: 'Too many requests from this IP, please try again later'
  });
  app.use('/api/', limiter);

  // Force HTTPS
  app.use((req, res, next) => {
    if (req.header('x-forwarded-proto') !== 'https') {
     res.redirect(`https://${req.header('host')}${req.url}`);
    } else {
     next();
    }
  });
}

app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(8080);

Build Process

For applications using TypeScript, Babel, or other build tools, the build process differs between environments:

Development Build

  • Source maps for debugging
  • Incremental compilation
  • Hot module replacement
  • Less aggressive optimizations

Production Build

  • Minification and tree shaking
  • Bundling and code splitting
  • Ahead-of-time compilation
  • No source maps (or external source maps)

webpack.config.js for Different Environments

const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    entry: './src/index.js',
    output: {
     path: path.resolve(__dirname, 'dist'),
     filename: isProduction
        ? 'bundle.[contenthash].js'
        : 'bundle.js'
    },
    mode: isProduction ? 'production' : 'development',
    // Generate source maps in development but not production
    devtool: isProduction ? false : 'eval-source-map',
    optimization: {
     minimize: isProduction,
     minimizer: isProduction ? [
        new TerserPlugin({
          terserOptions: {
           compress: true,
           mangle: true
          }
        })
      ] : [],
    },
    // Add development server configuration for non-production
    ...(isProduction ? {} : {
     devServer: {
      contentBase: './dist',
      hot: true
     }
    })
  };
};

Package.json Scripts

{
  "scripts": {
    "start": "node dist/server.js",
    "dev": "nodemon src/server.ts",
    "build": "tsc",
    "build:prod": "tsc && webpack --mode=production",
    "lint": "eslint src/**/*.ts",
    "test": "jest"
  }
}

Deployment Considerations

Development

  • Local development server
  • Docker containers for dependencies
  • Integrated development environment (IDE) tools

Production

  • Process managers (PM2, Forever)
  • Container orchestration (Kubernetes, Docker Swarm)
  • Load balancing
  • Health checks and monitoring
  • Automated deployment pipelines
  • Rollback strategies

PM2 Ecosystem File for Production

// ecosystem.config.js
module.exports = {
  apps: [{
    name: "my-app",
    script: "./dist/server.js",
    instances: "max",
    exec_mode: "cluster",
    env_development: {
      NODE_ENV: "development",
      PORT: 8080
    },
    env_production: {
      NODE_ENV: "production",
      PORT: 8080
    }
  }]
};

For more details on deployment, see the Node.js Deployment tutorial.


Testing Environments

Different environments have different testing requirements:

Development Testing

  • Unit tests during development
  • Integration tests
  • Fast feedback loops
  • Mocking external dependencies

Staging/QA Environment

  • End-to-end tests
  • Performance testing
  • Configuration similar to production
  • Mock data or sanitized production data

Production Testing

  • Smoke tests
  • Canary deployments
  • Real user monitoring
  • Load testing (during off-peak hours)

Best Practices

1. Use Environment Variables

Store environment-specific configuration in environment variables, not in code.

2. Automate Environment Setup

Use tools like Docker, Vagrant, or cloud templates to create consistent environments.

3. Implement Feature Flags

Use feature flags to enable features selectively in different environments.

const featureFlags = {
  development: {
    newUserInterface: true,
    experimentalFeature: true,
    betaAnalytics: true
  },
  production: {
    newUserInterface: false,
    experimentalFeature: false,
    betaAnalytics: true
  }
};

const env = process.env.NODE_ENV || 'development';
const features = featureFlags[env];

if (features.newUserInterface) {
  // Enable the new UI
}

4. Implement Continuous Integration/Continuous Deployment (CI/CD)

Automate testing and deployment across environments to ensure consistency.

5. Monitor and Alert

Set up comprehensive monitoring and alerting in production environments.

6. Document Environment Differences

Maintain clear documentation of environment-specific configurations and requirements.


Summary

  • Use the NODE_ENV environment variable to distinguish between development and production environments
  • Implement environment-specific configuration management
  • Handle errors differently in development (verbose) and production (secure)
  • Adjust logging strategies based on the environment
  • Apply performance optimizations and security measures in production
  • Use different build and deployment processes for each environment
  • Follow best practices for environment management, including automation and documentation


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.