Examness

Web & Design

Node.js इंटरव्यू प्रश्न

Event loop, streams, modules, Express and deployment.

175 प्रश्न

  1. 1.

    What are Promises in Node.js?

    शुरुआती

    It allows to associate handlers to an asynchronous action\'s eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise for the value at some point in the future.

    Promises in node.js promised to do some work and then had separate callbacks that would be executed for success and failure as well as handling timeouts. Another way to think of promises in node.js was that they were emitters that could emit only two events: success and error.The cool thing about promises is you can combine them into dependency chains (do Promise C only when Promise A and Promise B complete).

    The core idea behind promises is that a promise represents the result of an asynchronous operation. A promise is in one of three different states:

    • pending - The initial state of a promise.
    • fulfilled - The state of a promise representing a successful operation.
    • rejected - The state of a promise representing a failed operation.

    Once a promise is fulfilled or rejected, it is immutable (i.e. it can never change again).

    Example:

    /**
     * Promise
     */
    function getSum(num1, num2) {
      const myPromise = new Promise((resolve, reject) => {
        if (!isNaN(num1) && !isNaN(num2)) {
          resolve(num1 + num2);
        } else {
          reject(new Error("Not a valid number"));
        }
      });
    
      return myPromise;
    }
    
    console.log(getSum(10, 20)); // Promise { 30 }

    ↥ back to top

  2. 2.

    What is EventEmitter in Node.js?

    शुरुआती

    EventEmitter is a class from Node.js\'s built-in events module that implements the Observer (Pub/Sub) pattern — objects can emit named events, and listeners registered for those events are called when they fire.

    EventEmitter is at the core of Node asynchronous event-driven architecture. Many of Node\'s built-in modules inherit from EventEmitter including prominent frameworks like Express.js. An emitter object basically has two main features:

    • Emitting name events.
    • Registering and unregistering listener functions.

    Example:

    /**
     * Callback Events with Parameters
     */
    const events = require('events');
    const eventEmitter = new events.EventEmitter();
    
    function listener(code, msg) {
       console.log(`status ${code} and ${msg}`);
    }
    
    eventEmitter.on('status', listener); // Register listener
    eventEmitter.emit('status', 200, 'ok');
    
    // Output
    status 200 and ok

    Key Methods

    MethodDescription
    .on(event, listener)Register a listener (fires every time)
    .once(event, listener)Register a listener that fires only once
    .emit(event, ...args)Trigger all listeners for an event
    .off(event, listener)Remove a specific listener
    .removeAllListeners(event)Remove all listeners for an event
    .listeners(event)Returns array of listeners for an event
    .listenerCount(event)Returns number of listeners
    .setMaxListeners(n)Change the limit (default: 10)

    > Node.js prints a warning when more than 10 listeners are registered for a single event — use emitter.setMaxListeners(0) to disable the limit, or increase it as needed.

    ↥ back to top

  3. 3.

    What are Worker Threads in Node.js?

    शुरुआती

    Worker Threads (the worker_threads module, stable since Node.js v12 LTS) run JavaScript in parallel on separate threads. Unlike child_process.fork(), workers share memory via SharedArrayBuffer and are best suited for CPU-intensive JavaScript tasks (e.g., image processing, cryptography, data parsing) without blocking the main event loop.

    Key APIs:

    APIDescription
    WorkerRepresents a worker thread
    isMainThreadtrue if running in the main thread
    parentPortMessagePort for communicating with the parent
    workerDataData passed to the worker on creation
    SharedArrayBufferShared memory between threads

    Example:

    // worker-example.js (works as both main and worker)
    const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
    
    if (isMainThread) {
      // Main thread: spawn a worker
      const worker = new Worker(__filename, { workerData: { n: 40 } });
    
      worker.on('message', (result) => {
        console.log(`fibonacci(40) = ${result}`);
      });
      worker.on('error', (err) => console.error(err));
      worker.on('exit', (code) => console.log(`Worker exited with code ${code}`));
    } else {
      // Worker thread: perform the CPU-intensive task
      function fibonacci(n) {
        if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
      }
      parentPort.postMessage(fibonacci(workerData.n));
    }

    Worker Threads vs Child Processes:

    Worker ThreadsChild Process
    MemoryShared (via SharedArrayBuffer)Separate
    CommunicationpostMessage / SharedArrayBufferIPC / stdin/stdout
    Best forCPU-intensive JS tasksExternal programs, separate Node processes
    OverheadLowHigher

    ↥ back to top

    # 10. NODE.JS WEB MODULE

  4. 4.

    What is the preferred method of resolving unhandled exceptions in Node.js?

    शुरुआती

    Unhandled exceptions in Node.js can be caught at the Process level by attaching a handler for uncaughtException event.

    process.on('uncaughtException', function(err) {
        console.log('Caught exception: ' + err);
    });

    Process is a global object that provides information about the current Node.js process. Process is a listener function that is always listening to events.

    Few events are :

    1. Exit
    2. disconnect
    3. unhandledException
    4. rejectionHandled

    ↥ back to top

  5. 5.

    What is a stub?

    शुरुआती

    Stubbing and verification for node.js tests. Enables you to validate and override behaviour of nested pieces of code such as methods, require() and npm modules or even instances of classes. This library is inspired on node-gently, MockJS and mock-require.

    Features of Stub:

    • Produces simple, lightweight Objects capable of extending down their tree
    • Compatible with Nodejs
    • Easily extendable directly or through an ExtensionManager
    • Comes with predefined, usable extensions

    Stubs are functions/programs that simulate the behaviours of components/modules. Stubs provide canned answers to function calls made during test cases. Also, you can assert on with what these stubs were called.

    A use-case can be a file read, when you do not want to read an actual file:

    const fs = require('fs');
    
    const readFileStub = sinon.stub(fs, 'readFile', function (path, cb) {  
      return cb(null, 'filecontent');
    });
    
    expect(readFileStub).to.be.called;  
    readFileStub.restore();

    ↥ back to top

  6. 6.

    What are the types of applications you can build with Node.js?

    शुरुआती

    Node.js is a JavaScript runtime environment built upon event-driven programming that enables non-blocking I/O (Input/Output) capable of serving multiple concurrent events in a single thread. Non-blocking I/O makes Node.js very fast, lightweight, scalable, and efficient in handling data-heavy and I/O-heavy workloads characteristic of several types of web applications.

    Types of applications you can build with Node.js

    • IoT (Internet of Things)
    • Real-Time Chat Application
    • Single-Page Application
    • Social Media Platform
    • Streaming App
    • Online Payment Processor
    • Remote Collaboration Tool
    • CRM Tool
    • Advanced Fintech App
    • Content Management System
    • E-Learning Platform
    • E-Commerce Platform
    • Ridesharing App
    • Project Management Tools
    • Location-Based App
    • Online Publishing Platforms
    • ERP Tool
    • Websites With Server-Side Rendering
    • FastCGI Servers
    • Command Line Tools
    • API Servers
    • Desktop Apps
    • Backend for Mobile Apps
    • Server Management Services
    • Notification Centre
    • Custom DNS Server
    • Static Site Generator
    • Game Servers, Game Clients

    ↥ back to top

  7. 7.

    What is the path module in Node.js?

    शुरुआती

    The path module provides utilities for working with file and directory paths. It handles cross-platform differences between Unix (/) and Windows (\) path separators automatically.

    Example:

    const path = require('path');
    
    // Join path segments (cross-platform)
    console.log(path.join('/users', 'alice', 'docs', 'file.txt'));
    // /users/alice/docs/file.txt
    
    // Resolve an absolute path from the current working directory
    console.log(path.resolve('src', 'index.js'));
    // /current/working/dir/src/index.js
    
    // Directory name
    console.log(path.dirname('/users/alice/file.txt')); // /users/alice
    
    // File name with and without extension
    console.log(path.basename('/users/alice/file.txt'));         // file.txt
    console.log(path.basename('/users/alice/file.txt', '.txt')); // file
    
    // File extension
    console.log(path.extname('index.html')); // .html
    
    // Parse a path into its components
    console.log(path.parse('/users/alice/file.txt'));
    // { root: '/', dir: '/users/alice', base: 'file.txt', ext: '.txt', name: 'file' }
    
    // Normalize a path (resolves . and ..)
    console.log(path.normalize('/users/alice/../bob/./file.txt'));
    // /users/bob/file.txt

    `__dirname` and `__filename` (CommonJS):

    console.log(__dirname);  // absolute path of the directory containing the file
    console.log(__filename); // absolute path of the current file
    
    // Building safe paths relative to the current file
    const configPath = path.join(__dirname, 'config', 'settings.json');

    ↥ back to top

  8. 8.

    What is the difference between npm and npx?

    शुरुआती

    npm (Node Package Manager) is used to install, share, and manage JavaScript packages. It is bundled with Node.js.

    npx (Node Package Execute) is an npm package runner (available since npm v5.2) that lets you execute CLI packages without installing them globally.

    Featurenpmnpx
    PurposeInstall and manage packagesExecute packages directly
    Global install requiredYes, to use a CLI tool globallyNo, runs temporarily
    Version pinningVia npm installSpecify inline: npx pkg@version
    Use casenpm install -g eslintnpx eslint index.js

    Example:

    // Install globally with npm, then use
    npm install -g create-react-app
    create-react-app my-app
    
    // Use once without installing globally with npx (recommended)
    npx create-react-app my-app

    ↥ back to top

  9. 9.

    What is callback function in Node.js?

    शुरुआती

    A callback is a function which is called when a task is completed, thus helps in preventing any kind of blocking and a callback function allows other code to run in the meantime.

    Callback is called when task get completed and is asynchronous equivalent for a function. Using Callback concept, Node.js can process a large number of requests without waiting for any function to return the result which makes Node.js highly scalable.

    Example:

    /**
     * Callback Function
     */
    function message(name, callback) {
      console.log("Hi" + " " + name);
      callback();
    }
    
    // Callback function
    function callMe() {
      console.log("I am callback function");
    }
    
    // Passing function as an argument
    message("Node.JS", callMe);

    Output:

    Hi Node.JS
    I am callback function

    ↥ back to top

  10. 10.

    What are the core modules of Node.js?

    शुरुआती

    Node.js has a set of core modules that are part of the platform and come with the Node.js installation. These modules can be loaded into the program by using the require function.

    The following table lists some of the important core modules in Node.js.

    NameDescription
    assertIt is used by Node.js for testing itself.
    bufferHandle raw binary data outside the V8 heap
    child_processSpawn child processes (exec, spawn, fork)
    clusterThis module is used by Node.js to take advantage of multi-core systems, so that it can handle more load.
    consoleIt is used to write data to console. Node.js has a Console object which contains functions to write data to console.
    cryptoCryptographic functions — hashing, encryption, HMAC
    http/httpsCreate HTTP/HTTPS servers and make requests
    urlIt includes methods for URL resolution and parsing.
    querystringIt includes methods to deal with query string.
    pathUtilities for working with file and directory paths
    fsFile system — read, write, update, delete, rename files.
    streamReadable, Writable, Duplex, and Transform streams
    worker_threadsRun CPU-intensive JS in background threads
    utilIt includes utility functions useful for programmers.
    zlibIt is used to compress and decompress data.

    Example:

    const http   = require('http');
    const fs     = require('fs');
    const path   = require('path');
    const crypto = require('crypto');
    
    // HTTP server
    http.createServer((req, res) => {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('Hello World');
    }).listen(3000);
    
    // File path
    const filePath = path.join(__dirname, 'data', 'file.txt');
    
    // Read file
    fs.readFile(filePath, 'utf8', (err, data) => {
      if (err) throw err;
      console.log(data);
    });
    
    // Hash a string
    const hash = crypto.createHash('sha256').update('secret').digest('hex');
    console.log(hash);

    ↥ back to top

  11. 11.

    What is chrome v8 engine?

    शुरुआती

    V8 is an open-source, high-performance JavaScript and WebAssembly engine written in C++, developed by Google. It was originally designed for Google Chrome and Chromium-based browsers ( such as Brave ) in 2008, but it was later utilized to create Node.js for server-side coding.

    V8 is the JavaScript engine i.e. it parses and executes JavaScript code. The DOM, and the other Web Platform APIs ( they all makeup runtime environment ) are provided by the browser.

    V8 is known to be a JavaScript engine because it takes JavaScript code and executes it while browsing in Chrome. It provides a runtime environment for the execution of JavaScript code. The best part is that the JavaScript engine is completely independent of the browser in which it runs.

    Just-In-Time (JIT) compilation:

    V8 uses two compilers working together:

    • Ignition — baseline interpreter that converts JS to bytecode quickly, collects profiling data
    • TurboFan — optimizing compiler that re-compiles "hot" (frequently run) code into highly optimized machine code

    V8 Key Optimizations

    • Hidden classes — optimizes property access on objects
    • Inline caching — caches results of repeated operations
    • Garbage collection — generational GC (Scavenger + Mark-Compact) with minimal pause times

    ↥ back to top

  12. 12.

    What is Node.js?

    शुरुआती

    Node.js is an open-source server side runtime environment built on Chrome\'s V8 JavaScript engine. It provides an event driven, non-blocking (asynchronous) I/O and cross-platform runtime environment for building highly scalable server-side applications using JavaScript.

    ↥ back to top

  13. 13.

    What is the use of DNS module in Node.js?

    शुरुआती

    DNS is a node module used to do name resolution facility which is provided by the operating system as well as used to do an actual DNS lookup. No need for memorising IP addresses – DNS servers provide a nifty solution of converting domain or subdomain names to IP addresses. This module provides an asynchronous network wrapper and can be imported using the following syntax.

    const dns = require('dns');

    Example: dns.lookup() function

    const dns = require('dns');  
    dns.lookup('www.google.com', (err, addresses, family) => {  
      console.log('addresses:', addresses);  
      console.log('family:',family);  
    });  

    Example: resolve4() and reverse() functions

    const dns = require('dns');  
    dns.resolve4('www.google.com', (err, addresses) => {  
      if (err) throw err;  
      console.log(`addresses: ${JSON.stringify(addresses)}`);  
      addresses.forEach((a) => {  
        dns.reverse(a, (err, hostnames) => {  
          if (err) {  
            throw err;  
          }  
          console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`);  
        });  
      });  
    });

    Example: Print the localhost name using lookupService() function

    const dns = require('dns');  
    dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {  
      console.log(hostname, service);  
        // Prints: localhost  
    });

    ↥ back to top

  14. 14.

    What are the global objects of Node.js?

    शुरुआती

    Node.js Global Objects are the objects that are available in all modules. Global Objects are built-in objects that are part of the JavaScript and can be used directly in the application without importing any particular module.

    Global Objects

    ObjectDescription
    globalThe global namespace object (equivalent to window in browsers)
    processInfo and control over the current Node.js process
    consoleWrite to stdout/stderr
    BufferHandle raw binary data
    __dirnameAbsolute path of the current module's directory
    __filenameAbsolute path of the current module's file
    setTimeout / clearTimeoutSchedule a one-time callback
    setInterval / clearIntervalSchedule a repeating callback
    setImmediate / clearImmediateExecute after current event loop iteration
    queueMicrotaskQueue a microtask
    URL / URLSearchParamsWeb-compatible URL API
    fetchHTTP client (available since Node.js v18)
    cryptoWeb Crypto API (available since Node.js v19)

    Examples:

    // __dirname and __filename
    console.log(__dirname);   // D:\projects\myapp
    console.log(__filename);  // D:\projects\myapp\index.js
    
    // process — runtime info
    console.log(process.version);       // v20.x.x
    console.log(process.platform);      // 'win32' / 'linux'
    console.log(process.env.NODE_ENV);  // 'development'
    console.log(process.pid);           // process ID
    process.exit(0);                    // exit with code 0
    
    // global — set a truly global variable (avoid in practice)
    global.appName = 'MyApp';
    console.log(appName); // 'MyApp' — accessible anywhere
    
    // Buffer
    const buf = Buffer.from('hello');
    console.log(buf.toString('hex')); // 68656c6c6f
    
    // Timers
    const timer = setTimeout(() => console.log('done'), 1000);
    clearTimeout(timer); // cancel it

    > __dirname and __filename are not available in ES Modules — use import.meta.url with fileURLToPath() instead. The global object in Node.js v21+ is also aliased as globalThis (the standard cross-environment global).

    ↥ back to top

  15. 15.

    What is Node.js and why is it used?

    शुरुआती

    Node.js is an open-source, cross-platform JavaScript runtime environment that executes code outside of a web browser. It is built on V8, the same JavaScript engine within Chrome, and optimized for high performance. This environment, coupled with an event-driven, non-blocking I/O framework, is tailored for server-side web development and more.

    Key Features

    • Asynchronous & Non-Blocking: Ideal for handling a myriad of concurrent connections with efficiency.
    • V8 Engine: Powered by Google's V8, Node.js boasts top-tier JavaScript execution.
    • Libuv Library: Ensures consistent performance across platforms and assists in managing I/O operations.
    • NPM: A vast package ecosystem simplifies module management and deployment.
    • Full-Stack JavaScript: Allows for unified server and client-side code in JavaScript.

    Use Cases

    • Data Streaming: Suited for real-time streaming of audio, video, and lightweight data.
    • API Servers: Ideal for building fast, scalable, and data-intensive applications.
    • Microservices: Its module-oriented design facilitates the development of decoupled, independently scalable services.
    • Single Page Applications: Often used with frameworks like Angular, React, or Vue to craft robust, server-side backends.
    • Chat Applications: Its real-time capabilities are advantageous in building instant messaging systems.
    • Internet of Things (IoT): Provides a lightweight environment for running applications on constrained devices like Raspberry Pi.

    Why Node.js?

    • Unified Language: Utilizing JavaScript both on the frontend and backend brings coherence to development efforts, potentially reducing debugging time and enabling shared libraries.
    • NPM Ecosystem: The NPM repository offers myriad open-source packages, empowering rapid development and feature expansion.
    • Rapid Prototyping: Express, a minimalist web framework for Node.js, and NPM's wealth of modules expedite early application development and testing.
    • Scalability: Cluster modules, load balancers, and Microservice Architecture aid in linear, on-demand scaling for both simple and intricate applications.
    • Real-Time Power: With built-in WebSockets and event-based architecture, Node.js excels in constructing real-time applications such as multiplayer games, stock trading platforms, and chat applications.
    • Open Source: Being an open-source technology, Node.js continuously benefits from community contributions, updates, and enhanced packages.
  16. 16.

    What is the event loop in Node.js?

    शुरुआती

    The event loop is a fundamental concept in Node.js for managing asynchronous operations. Its efficiency is a key reason behind Node.js's high performance.

    How Does the Event Loop Work?

    1. Initialization: When Node.js starts, it initializes the event loop to watch for I/O operations and other asynchronous tasks.
    1. Queueing: Any task or I/O operation is added to a queue, which can be either the microtask queue or the macrotask/Callback queue.
    1. Polling: The event loop iteratively checks for tasks in the queue while also waiting for I/O and timers.
    1. Execution Phases: When the event loop detects tasks in the queue, it executes them in specific phases, ensuring order efficiency.

    Task Scheduler Zones: microtask and Callback Queue

    • Microtask Queue: This is a highly prioritized queue, usually acting over tasks in the Callback Queue. Useful for tasks that require immediate attention.
    • Callback Queue (Macrotask Queue): Also known as the 'Task Queue,' it manages events and I/O operations.

    Event Loop Phases

    • Timers: Manages timer events for scheduled tasks.
    • Pending callbacks: Handles system events such as I/O, which are typically queued by the kernel.
    • Idle / prepare: Ensures internal actions are managed before I/O events handling.
    • Poll: Retrieves New I/O events.
    • Check: Executes 'setImmediate' functions.
    • Close: Handles close events, such as 'socket.close'.

    Task Scheduling: microtasks and macrotasks

    • Microtasks (process.nextTick and Promises): Executed after each task.
    • Macrotasks: Executed after the poll phase when the event loop is not behind any file I/O or scheduled time. This includes timers, setImmediate, and I/O events.

    Code Example: Timers and Task Queues

    Here is the JavaScript code:

    Node.js

    // Code Example
    console.log('Start');
    
    setTimeout(() => {  
      console.log('Set Timeout - 1');
      
      Promise.resolve().then(() => {
        console.log('Promise - 1');
      }).then(() => {
        console.log('Promise - 2');
      });
    
    }, 0);
    
    setImmediate(() => {
      console.log('Set Immediate');
    });
    
    process.nextTick(() => {
      console.log('Next Tick');
      // It's like an infinite loop point for microtask queue
      process.nextTick(() => console.log('Next Tick - nested'));
    });
    
    fs.readFile(file, 'utf-8', (err, data) => {
      if (err) throw err;
      console.log('File Read');
    });
    
    console.log('End');
  17. 17.

    What is daemon process?

    शुरुआती

    A daemon is a program that runs in background and has no controlling terminal. They are often used to provide background services. For example, a web-server or a database server can run as a daemon.

    When a daemon process is initialized:

    • It creates a child of itself and proceeds to shut down all standard descriptors (error, input, and output) from this particular copy.
    • It closes the parent process when the user closes the session/terminal window.
    • Leaves the child process running as a daemon.

    Daemonize Node.js process:

    • Forever
    • PM2
    • Nodemon
    • Supervisor
    • Docker

    Example: Using an instance of Forever from Node.js

    const forever = require("forever");
    
    const child = new forever.Forever("your-filename.js", {
      max: 3,
      silent: true,
      args: [],
    });
    
    child.on("exit", this.callback);
    child.start();

    ↥ back to top

  18. 18.

    What is Error Handling in Node.js?

    शुरुआती

    An error is any problem given out by the program due to a number of factors such as logic, syntax, timeout, etc. An error in Node.js is any instance of the Error object. Common examples include built-in error classes, such as ReferenceError, RangeError, TypeError, URIError, EvalError, and SyntaxError.

    User-defined errors can also be created by extending the base Error object, a built-in error class, or another custom error. In general, Node.js errors are divided into two distinct categories: operational errors and programmer errors.

    1. Operational Errors:

    Operational errors represent runtime problems. These errors are expected in the Node.js runtime and should be dealt with in a proper way. Here\'s a list of common operational errors:

    • failed to connect to server
    • failed to resolve hostname
    • invalid user input
    • request timeout
    • server returned a 500 response
    • socket hang-up
    • system is out of memory

    2. Programmer Errors:

    Programmer errors are what we call bugs. They represent issues in the code itself. Here\'s a common one for Node.js, when you try reading a property of an undefined object. It\'s a classic case of programmer error. Here are a few more:

    • called an asynchronous function without a callback
    • did not resolve a promise
    • did not catch a rejected promise
    • passed a string where an object was expected
    • passed an object where a string was expected
    • passed incorrect parameters in a function

    ↥ back to top

  19. 19.

    What are the key features of Node.js?

    शुरुआती
    • Asynchronous and Event driven – All APIs of Node.js are asynchronous. This feature means that if a Node receives a request for some Input/Output operation, it will execute that operation in the background and continue with the processing of other requests. Thus it will not wait for the response from the previous requests.
    • Fast in Code execution – Node.js uses the V8 JavaScript Runtime engine, the one which is used by Google Chrome. Node has a wrapper over the JavaScript engine which makes the runtime engine much faster and hence processing of requests within Node.js also become faster.
    • Single Threaded but Highly Scalable – Node.js uses a single thread model for event looping. The response from these events may or may not reach the server immediately. However, this does not block other operations. Thus making Node.js highly scalable. Traditional servers create limited threads to handle requests while Node.js creates a single thread that provides service to much larger numbers of such requests.
    • Node.js library uses JavaScript – This is another important aspect of Node.js from the developer\'s point of view. The majority of developers are already well-versed in JavaScript. Hence, development in Node.js becomes easier for a developer who knows JavaScript.
    • There is an Active and vibrant community for the Node.js framework – The active community always keeps the framework updated with the latest trends in the web development.
    • No Buffering – Node.js applications never buffer any data. They simply output the data in chunks.

    ↥ back to top

  20. 20.

    What is the purpose of NODEENV in Node.js?

    शुरुआती

    NODE_ENV is a convention used by Node.js frameworks and libraries to alter their behaviour based on the runtime environment. It is not set automatically — you must define it explicitly.

    Common values:

    ValueUsage
    developmentVerbose errors, hot reload, debug logging
    testIsolated databases, mocked services
    productionMinified output, cached templates, suppressed stack traces

    Example — toggling behaviour:

    require('dotenv').config();
    
    const express = require('express');
    const app = express();
    
    // Express automatically disables view cache and enables verbose errors
    // when NODE_ENV !== 'production'
    console.log(`NODE_ENV: ${process.env.NODE_ENV}`);
    
    // Custom behaviour based on environment
    if (process.env.NODE_ENV === 'production') {
      // Use a real database connection
      app.use(require('./middleware/errorHandler'));   // hides stack traces
    } else {
      // Use an in-memory SQLite database for development
      app.use((err, req, res, next) => {
        console.error(err.stack);   // show full stack in dev
        res.status(500).json({ error: err.message, stack: err.stack });
      });
    }

    Setting NODE_ENV:

    # Linux / macOS
    NODE_ENV=production node app.js
    
    # Windows PowerShell
    $env:NODE_ENV="production"; node app.js
    
    # Cross-platform via npm script (cross-env package)
    npm install --save-dev cross-env
    # package.json
    "scripts": {
      "start": "cross-env NODE_ENV=production node app.js",
      "dev":   "cross-env NODE_ENV=development nodemon app.js"
    }

    ↥ back to top