Most people advise against using global variables. If you want the same logger class in different modules you can do this

logger.js

  module.exports = new logger(customConfig);

foobar.js

  var logger = require('./logger');
  logger('barfoo');

If you do want a global variable you can do:

global.logger = new logger(customConfig);
Answer from Pickels on Stack Overflow
🌐
Node.js
nodejs.org › api › globals.html
Global objects | Node.js v25.8.2 Documentation
Any modification of this data outside ... user or per request when used in the context of a server, it is shared across all users and requests. ... The MessageChannel class. See MessageChannel for more details. ... A browser-compatible implementation of <MessageEvent>. ... The MessagePort class. See MessagePort for more details. This variable may appear to be global but is ...
Top answer
1 of 5
7

Yes, with some caveats. You're looking for a module called continuation-local-storage.
This allows you to keep arbitrary data for the remainder of callbacks for the current request, and access it in a global fashion.
I wrote a blog post about it here. But the gist is this:

  1. Install cls: npm install --save continuation-local-storage
  2. Create a namespace for your app (at the top of the main file for your app)

    var createNamespace = require('continuation-local-storage').createNamespace, 
        namespace = createNamespace('myAppNamespace');
    
  3. Create a middleware that runs downstream functions in the cls (continuation-local-storage) namespace

    var getNamespace = require('continuation-local-storage').getNamespace,
        namespace = getNamespace('myAppNamespace'),
    
    app.use(function(req, res, next) {    
      // wrap the events from request and response
      namespace.bindEmitter(req);
      namespace.bindEmitter(res);
    
      // run following middleware in the scope of the namespace we created
      namespace.run(function() {
        namespace.set(‘foo’, 'a string data');
        next();
      });
    });
    
  4. Since you ran next within namespace.run, any downstream function can access data in the namespace

    var getNamespace = require('continuation-local-storage').getNamespace,
        namespace = getNamespace('myAppNamespace');
    
    // Some downstream function that doesn't have access to req...
    function doSomething() {
      var myData = namespace.get('foo');
      // myData will be 'a string data'
    }
    
  5. There is the caveat that certain modules can "lose" the context created by cls. This means that when you go to lookup 'foo' on the namespace, it won't have it. There are a few ways to deal with this, namely using another module like cls-redis, cls-q, or binding to the namespace.

2 of 5
1

Per request, I think what you're after could be done with ordinary closures. For example, you'd define your custom functions in module that takes a req argument:

util_funcs.js:

module.exports = function( req ){
  return {
    customFunctionThatRequiresReq: function(){ console.info( req ) },
    otherFunctionThatRequiresReq:  function(){ console.log( req ) }
  };
};

Then wherever you depend on those functions (presumably some middleware elsewhere in the application), you can just require them in context:

var someMiddleWare = function( req, res, next ){

  var utils = require( 'util_funcs.js' )( req );

  utils.customFunctionThatRequiresReq();
  utils.otherFunctionThatRequiresReq();

}; 

This allows you to avoid littering your function args with req, and no dubious globals.

🌐
Stack Abuse
stackabuse.com › using-global-variables-in-node-js
Using Global Variables in Node.js
July 8, 2024 - Now that we have a better understanding of what a global variable in Node is, let's talk about how we actually set up and use a global variable. To set up a global variable, we need to create it on the global object. The global object is what gives us the scope of the entire project, rather ...
Top answer
1 of 4
14

Here is my suggestion avoid global state like fire.

  • It's the number one maintenance problem in Node servers from my experience.
  • It makes your code not composable and harder to reuse.
  • It creates implicit dependencies in your code - you're never sure which piece depends on which and it's not easy to verify.

You want the parts of code that each piece of an application uses to be as explicit as possible. It's a huge issue.

The issue

We want to synchronize state across multiple requests and act accordingly. This is a very big problem in writing software - some say even the biggest. The importance of the way objects in the application communicate can not be overestimated.

Some solutions

There are several ways to accomplish sharing state across requests or server wide in a Node server. It depends on what you want to do. Here are the two most common imo.

  1. I want to observe what the requests do.
  2. I want one request to do things based on what another request did.

1. I want to observe what the requests do

Again, there are many ways to do this. Here are the two I see most.

Using an event emitter

This way requests emit events. The application reads events the requests fire and learns about them accordingly. The application itself could be an event emitter you can observe from the outside.

You can do something like:

request.emit("Client did something silly", theSillyThing);

And then listen to it from the outside if you choose to.

Using an observer pattern

This is like an event emitter but reversed. You keep a list of dependencies on the request and call a handler method on them yourself when something interesting happens on the request.

Personally, I usually prefer an event emitter because I think they usually solve the case better.

2. I want one request to do things based on what another request did.

This is a lot tricker than just listening. again, there are several approaches here. What they have in common is that we put the sharing in a service

Instead of having global state - each request gets access to a service - for example when you read a file you notify the service and when you want a list of read files - you ask the service. Everything is explicit in the dependency.

The service is not global, only dependencies of it. For example, it can coordinate resources and the data, being some form of Repository).

Nice theory! Now what about my use case?

Here are two options for what I would do in your case. It's far from the only solution.

First option:

  • Each of the modules are an event emitter, whenever they read a file they emit an event.
  • A service listens to all their events and keeps count.
  • Requests have access to that service explicitly and can query it for a list of files.
  • Requests perform writes through the modules themselves and not the added service.

Second option:

  • Create a service that owns a copy of module1, module2 and module3. (composition)
  • The service delegates actions to the modules based on what is required from it.
  • The service keeps the list of files accessed since the requests were made through it.
  • The request stops using the modules directly - uses the service instead.

Both these approaches have advantages and disadvantages. A more complicated solution might be required (those two are in practice pretty simple to do) where the services are abstracted further but I think this is a good start.

2 of 4
0

One simple way is storing data on the request object.

Here is an example (using Express):

app.get('/hello.txt', function(req, res){
    req.transaction = req.transaction || [];

    if (req.transaction.length) {
        // something else has already written to this array
    }
});

However, I don't really see how you can need this. When you call moduleA or moduleB, you just have to pass an object as argument, and it solves your issue. Maybe you're looking for dependency injection?

Top answer
1 of 7
242

You can use global like so:

global._ = require('underscore')
2 of 7
221

In Node.js, you can set global variables via the "global" or "GLOBAL" object:

GLOBAL._ = require('underscore'); // But you "shouldn't" do this! (see note below)

or more usefully...

GLOBAL.window = GLOBAL;  // Like in the browser

From the Node.js source, you can see that these are aliased to each other:

node-v0.6.6/src/node.js:
28:     global = this;
128:    global.GLOBAL = global;

In the code above, "this" is the global context. With the CommonJS module system (which Node.js uses), the "this" object inside of a module (i.e., "your code") is not the global context. For proof of this, see below where I spew the "this" object and then the giant "GLOBAL" object.

console.log("\nTHIS:");
console.log(this);
console.log("\nGLOBAL:");
console.log(global);

/* Outputs ...

THIS:
{}

GLOBAL:
{ ArrayBuffer: [Function: ArrayBuffer],
  Int8Array: { [Function] BYTES_PER_ELEMENT: 1 },
  Uint8Array: { [Function] BYTES_PER_ELEMENT: 1 },
  Int16Array: { [Function] BYTES_PER_ELEMENT: 2 },
  Uint16Array: { [Function] BYTES_PER_ELEMENT: 2 },
  Int32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Uint32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Float32Array: { [Function] BYTES_PER_ELEMENT: 4 },
  Float64Array: { [Function] BYTES_PER_ELEMENT: 8 },
  DataView: [Function: DataView],
  global: [Circular],
  process:
   { EventEmitter: [Function: EventEmitter],
     title: 'node',
     assert: [Function],
     version: 'v0.6.5',
     _tickCallback: [Function],
     moduleLoadList:
      [ 'Binding evals',
        'Binding natives',
        'NativeModule events',
        'NativeModule buffer',
        'Binding buffer',
        'NativeModule assert',
        'NativeModule util',
        'NativeModule path',
        'NativeModule module',
        'NativeModule fs',
        'Binding fs',
        'Binding constants',
        'NativeModule stream',
        'NativeModule console',
        'Binding tty_wrap',
        'NativeModule tty',
        'NativeModule net',
        'NativeModule timers',
        'Binding timer_wrap',
        'NativeModule _linklist' ],
     versions:
      { node: '0.6.5',
        v8: '3.6.6.11',
        ares: '1.7.5-DEV',
        uv: '0.6',
        openssl: '0.9.8n' },
     nextTick: [Function],
     stdout: [Getter],
     arch: 'x64',
     stderr: [Getter],
     platform: 'darwin',
     argv: [ 'node', '/workspace/zd/zgap/darwin-js/index.js' ],
     stdin: [Getter],
     env:
      { TERM_PROGRAM: 'iTerm.app',
        'COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET': '/tmp/launch-nNl1vo/ServiceProcessSocket',
        TERM: 'xterm',
        SHELL: '/bin/bash',
        TMPDIR: '/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/',
        Apple_PubSub_Socket_Render: '/tmp/launch-9Ga0PT/Render',
        USER: 'ddopson',
        COMMAND_MODE: 'unix2003',
        SSH_AUTH_SOCK: '/tmp/launch-sD905b/Listeners',
        __CF_USER_TEXT_ENCODING: '0x12D732E7:0:0',
        PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/X11/bin',
        PWD: '/workspace/zd/zgap/darwin-js',
        LANG: 'en_US.UTF-8',
        ITERM_PROFILE: 'Default',
        SHLVL: '1',
        COLORFGBG: '7;0',
        HOME: '/Users/ddopson',
        ITERM_SESSION_ID: 'w0t0p0',
        LOGNAME: 'ddopson',
        DISPLAY: '/tmp/launch-l9RQXI/org.x:0',
        OLDPWD: '/workspace/zd/zgap/darwin-js/external',
        _: './index.js' },
     openStdin: [Function],
     exit: [Function],
     pid: 10321,
     features:
      { debug: false,
        uv: true,
        ipv6: true,
        tls_npn: false,
        tls_sni: true,
        tls: true },
     kill: [Function],
     execPath: '/usr/local/bin/node',
     addListener: [Function],
     _needTickCallback: [Function],
     on: [Function],
     removeListener: [Function],
     reallyExit: [Function],
     chdir: [Function],
     debug: [Function],
     error: [Function],
     cwd: [Function],
     watchFile: [Function],
     umask: [Function],
     getuid: [Function],
     unwatchFile: [Function],
     mixin: [Function],
     setuid: [Function],
     setgid: [Function],
     createChildProcess: [Function],
     getgid: [Function],
     inherits: [Function],
     _kill: [Function],
     _byteLength: [Function],
     mainModule:
      { id: '.',
        exports: {},
        parent: null,
        filename: '/workspace/zd/zgap/darwin-js/index.js',
        loaded: false,
        exited: false,
        children: [],
        paths: [Object] },
     _debugProcess: [Function],
     dlopen: [Function],
     uptime: [Function],
     memoryUsage: [Function],
     uvCounters: [Function],
     binding: [Function] },
  GLOBAL: [Circular],
  root: [Circular],
  Buffer:
   { [Function: Buffer]
     poolSize: 8192,
     isBuffer: [Function: isBuffer],
     byteLength: [Function],
     _charsWritten: 8 },
  setTimeout: [Function],
  setInterval: [Function],
  clearTimeout: [Function],
  clearInterval: [Function],
  console: [Getter],
  window: [Circular],
  navigator: {} }
*/

** Note: regarding setting "GLOBAL._", in general you should just do var _ = require('underscore');. Yes, you do that in every single file that uses Underscore.js, just like how in Java you do import com.foo.bar;. This makes it easier to figure out what your code is doing because the linkages between files are 'explicit'. It is mildly annoying, but a good thing. .... That's the preaching.

There is an exception to every rule. I have had precisely exactly one instance where I needed to set "GLOBAL._". I was creating a system for defining "configuration" files which were basically JSON, but were "written in JavaScript" to allow a bit more flexibility. Such configuration files had no 'require' statements, but I wanted them to have access to Underscore.js (the entire system was predicated on Underscore.js and Underscore.js templates), so before evaluating the "configuration", I would set "GLOBAL._". So yeah, for every rule, there's an exception somewhere. But you had better have a darn good reason and not just "I get tired of typing 'require', so I want to break with the convention".

Find elsewhere
🌐
Mastering JS
masteringjs.io › tutorials › fundamentals › global-variable
Global Variables in JavaScript - Mastering JS
February 2, 2021 - If you assign to an variable that you didn't define using let, const, or var outside of strict mode, that automatically becomes a global variable. function() { answer = 42; // `answer` becomes global scoped in the browser, or file scoped in Node.js }
🌐
Reactgo
reactgo.com › home › how to declare a global variable in node.js
How to declare a global variable in Node.js | Reactgo
February 15, 2023 - In this tutorial, we are going to learn about how to declare and use global variables in Node. In Node.js, each module has its own scope the variables we declared inside one module can’t be accessed inside other modules.
🌐
Quora
quora.com › How-do-I-declare-a-global-variable-in-Node
How to declare a global variable in Node - Quora
Answer (1 of 2): Generally you don't want to. If you think you want to, then rethink your plan and don't do it. For instance, if you need a value shared between modules, your can export it from one and import it where it's needed. But the way to actually add something to the global namespace i...
🌐
Node.js
nodejs.org › download › release › v14.16.1 › docs › api › globals.html
Global objects | Node.js v14.16.1 Documentation
In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different.
🌐
Node.js
nodejs.org › download › release › v12.13.0 › docs › api › globals.html
Global Objects | Node.js v12.13.0 Documentation
In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different.
🌐
EDUCBA
educba.com › home › software development › software development tutorials › javascript technology tutorial › node.js global variable
Node.js Global Variable | How Global Variable Work in Node.js?
March 29, 2023 - So in node js, we have one object called global. So whatever function we are using in nodejs without creating them is coming from this global object. One thing to note here, if we are declaring any variable in nodejs, then it is not added to its global scope.
Address   Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
npm
npmjs.com › package › globals
globals - npm
March 1, 2026 - globals.nodeBuiltin: Globals available to all code running in Node.js. These will usually be available as properties on the globalThis object and include process, Buffer, but not CommonJS arguments like require. See: https://nodejs.org/api/globals.html · globals.node: A combination of the globals from nodeBuiltin plus all CommonJS arguments ("CommonJS module scope"). See: https://nodejs.org/api/modules.html#modules_the_module_scope
      » npm install globals
    
Published   Mar 01, 2026
Version   17.4.0
Author   Sindre Sorhus
🌐
GitHub
gist.github.com › arsho › edcd784c6228d0635a5b8e3907c5c95b
This little script saves a global variable in express js. It count how many times an user visit the root of the website which is in this case http://localhost:3000/ · GitHub
January 13, 2017 - This little script saves a global variable in express js. It count how many times an user visit the root of the website which is in this case http://localhost:3000/ - global_variable_express.js
🌐
Medium
medium.com › @a.kago1988 › global-objects-variables-and-methods-in-javascript-and-node-js-f6bffc74e792
Objects, Variables, and Methods Provided by Node.js | by Andreas 🎧 Kagoshima | Medium
2 days ago - In Node.js, the global object itself is global, similar to how browsers use window. However, in Node.js, the global object is less frequently used directly because Node.js encourages modularity (using local scope) rather than relying on global variables.
🌐
GeeksforGeeks
geeksforgeeks.org › node.js › how-to-create-global-variables-accessible-in-all-views-using-express-nodejs
How to Create Global Variables Accessible in all Views using Express/NodeJS ? - GeeksforGeeks
April 9, 2024 - Custom middleware functions in Express.js allow developers to manipulate the request or response objects before passing them to subsequent middleware functions or routes. By setting variables in res.locals within a custom middleware, developers can ensure the availability of those variables in all views rendered during that request.