Sitemap

How Can a Million Requests Call the Same Singleton Function in Node.js?

3 min readApr 22, 2025
Press enter or click to view image in full size

Great question. It might seem surprising at first, but Node.js can efficiently handle millions of concurrent requests — even when they all call the same method on a Singleton — thanks to its event-driven, non-blocking architecture.

Let’s break it down step by step.

1. Node.js and the Event Loop

Node.js uses a single-threaded event loop, but that doesn’t mean it handles only one request at a time.

Instead, it relies on asynchronous I/O operations and event callbacks to handle multiple concurrent requests without blocking the main thread.

Here’s what happens when a request comes in:

  • Node.js begins processing the request.
  • If the request involves asynchronous operations (like database queries or file reads), those tasks are delegated (to the system kernel or worker threads).
  • While waiting, Node.js moves on to handle the next request.
  • When the async operation completes, a callback is queued and executed.

This architecture allows Node.js to handle a massive number of simultaneous requests using minimal resources.

2. Shared Singleton Function Access

Now let’s say we have a simple Singleton object like this:

class Config {
constructor() {
this.settings = {
dbHost: 'localhost',
dbPort: 3306
};
}

get(key) {
return this.settings[key];
}
}

const config = new Config();
module.exports = config;
  • This config object is created once, at application startup.
  • Every request that imports this module receives the same instance.
  • The get() method simply reads from a static in-memory object — no mutation, no I/O, no blocking.

So what happens if a million requests all call config.get()?

They all succeed, with zero conflict.

That’s because:

  • There’s no shared state being mutated.
  • No blocking or waiting is involved.
  • Each call is lightweight and independent.

3. Node.js Concurrency in Action

Let’s put it into context with a simple Express server:

const express = require('express');
const app = express();
const config = require('./config');

app.get('/', (req, res) => {
const dbHost = config.get('dbHost');
res.send(`Database host is ${dbHost}`);
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

If 1 million requests hit this server:

  • Each one will call config.get('dbHost').
  • This is just a property lookup in a JavaScript object.
  • Node.js handles these in the event loop, efficiently queuing and responding to requests without waiting for previous ones to finish.

Because the method is:

  • Stateless
  • Read-only
  • Non-blocking

So, Node.js can process requests concurrently with minimal delay.

4. When a Singleton Becomes a Bottleneck

This efficiency only holds as long as the Singleton stays stateless and non-blocking.

Here’s what can go wrong:

Blocking Operation Example

class Logger {
constructor() {
this.logFile = fs.createWriteStream('./app.log');
}

log(message) {
this.logFile.write(`${new Date().toISOString()} ${message}\n`);
}
}

If every request writes a log entry:

  • All requests share the same Logger instance and the same file stream.
  • Writing to disk is I/O-bound and potentially blocking.
  • Under high load, log writes can slow down or block the event loop.

Shared Mutable State Example

class EmailSender {
constructor() {
this.recipients = [];
}

setRecipients(list) {
this.recipients = list;
}

send(message) {
this.recipients.forEach(email => {
console.log(`Sending "${message}" to ${email}`);
});
}
}

If multiple requests modify the recipients list at the same time, they’ll interfere with one another — a classic race condition.

5. Conclusion

Yes — a million requests can safely call the same function in a Singleton, as long as:

✅ The method is read-only
✅ There is no shared mutable state
✅ There is no blocking operation (like file or network I/O)
✅ The function operates in constant time and memory

Node.js can handle high concurrency not by creating threads, but by queuing and dispatching work through the event loop in a highly efficient, non-blocking manner.

Key Takeaway

A Singleton in Node.js is safe and scalable if it’s stateless and performs non-blocking operations. But once it introduces mutable data or blocking logic, it can quietly become a performance bottleneck — or worse, a source of bugs.

--

--

Aditya Yadav
Aditya Yadav

Written by Aditya Yadav

Software Engineer who talks about tech concepts in web development https://www.linkedin.com/in/aditya-yadav-01/