Singleton Pattern in Node.js
The Singleton earns its place in every real Node.js service I have worked on, usually without anyone calling it that: the shared database pool, the config object, the logger. It is also the pattern most often accidentally broken in Node, because module caching gives you singletons until it quietly doesn't.
This post is part of my Node.js Design Patterns series.
Let’s delve into both the Factory and Singleton patterns with specific examples to clarify how they can be implemented in Node.js.
Factory Pattern Example
The Factory pattern is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. This pattern is particularly useful when you have a set of related classes and you want to instantiate one of them based on some input.
Here’s a simple example demonstrating the Factory pattern for creating different types of notifications (e.g., email, SMS):
// NotificationFactory.js class Notification { send() { throw new Error("Method 'send()' must be implemented."); } } class EmailNotification extends Notification { send(message) { console.log(Sending email with message: ${message}); // Logic to send email } } class SMSNotification extends Notification { send(message) { console.log(Sending SMS with message: ${message}); // Logic to send SMS } } class NotificationFactory { static createNotification(type) { switch (type) { case "email": return new EmailNotification(); case "sms": return new SMSNotification(); default: throw new Error("Notification type not supported."); } } } // Usage const emailNotification = NotificationFactory.createNotification("email"); emailNotification.send("Hello, this is an email notification!"); const smsNotification = NotificationFactory.createNotification("sms"); smsNotification.send("Hello, this is an SMS notification!");
In this example, the NotificationFactory class decides which type of notification to instantiate based on the input. This encapsulates the instantiation logic and separates it from the client code.
Singleton Pattern Example
The Singleton pattern ensures a class has only one instance and provides a global point of access to that instance. It’s useful when exactly one object is needed to coordinate actions across the system.
Here’s how you might implement a Singleton for a database connection in Node.js:
// DatabaseConnection.js class DatabaseConnection { constructor(connectionDetails) { if (DatabaseConnection.instance) { return DatabaseConnection.instance; } this.connectionDetails = connectionDetails; DatabaseConnection.instance = this; } connect() { console.log(Connecting to database with details: ${this.connectionDetails}); // Logic to connect to the database } // Ensure the instance is not cloned clone() { return this; } } // Usage const dbConnection1 = new DatabaseConnection("User1:Password1@Host1"); dbConnection1.connect(); const dbConnection2 = new DatabaseConnection("User2:Password2@Host2"); dbConnection2.connect(); console.log(dbConnection1 === dbConnection2); // true
In this Singleton pattern example, the DatabaseConnection class controls instantiation of itself and ensures that only one instance can exist. If an instance already exists, the constructor returns the existing instance instead of creating a new one. This ensures that multiple requests for a database connection do not create multiple connections, preserving resources and ensuring consistent access to the database.

Nguyễn Hải Nam
Project Management Lead. 16+ years from code to delivery. PMP®. Writing here about project management and engineering.