Singletons ensure “only one instance” of something. Here are 5 real-world cases in JavaScript where that’s exactly what you need.

Introduction: Why Do We Need Singletons?
Sometimes, you don’t want multiple copies of the same thing floating around in your app.
- One database connection
- One config object
- One API client
- One global store
That’s where the Singleton Pattern comes in:
👉 It ensures only one instance of a class/object exists, and provides a global access point to it.
In JavaScript, singletons are easy to create but powerful when used carefully.
Let’s walk through 5 practical examples that you’ll actually use in real-world apps.
1. Configuration Manager
Every app has configs: API keys, feature flags, and environment variables. You don’t want multiple versions floating around.
class Config {
constructor(settings) {
if (Config.instance) {
return Config.instance;
}
this.settings = settings;
Config.instance = this;
}
get(key) {
return this.settings[key];
}
}
// Usage
const config1 = new Config({ env: "dev", debug: true });
const config2 = new Config({ env: "prod" });
console.log(config1.get("env")); // dev
console.log(config1 === config2); // true
✅ Even though we tried to createconfig2
It points to the same instance.
2. Logger Utility
Logging should be consistent across your whole app, not multiple disconnected loggers.
class Logger {
constructor() {
if (Logger.instance) {
return Logger.instance;
}
Logger.instance = this;
}
log(message) {
console.log(`[LOG] ${new Date().toISOString()}: ${message}`);
}
}
// Usage
const logger1 = new Logger();
const logger2 = new Logger();
logger1.log("App started");
logger2.log("User logged in");
console.log(logger1 === logger2); // true
✅ Both loggers share the same instance, making logs consistent.
3. Database Connection Manager
Databases don’t like 50 different connections from one app; that’s wasteful. A singleton ensures one connection pool per app.
class Database {
constructor(connectionString) {
if (Database.instance) {
return Database.instance;
}
this.connectionString = connectionString;
this.connected = false;
Database.instance = this;
}
connect() {
if (!this.connected) {
console.log("Connecting to", this.connectionString);
this.connected = true;
}
return this;
}
}
// Usage
const db1 = new Database("mongodb://localhost:27017/app");
db1.connect();
const db2 = new Database("mongodb://localhost:27017/other");
db2.connect();
console.log(db1 === db2); // true
✅ No matter how many times you “create” it, there’s only one DB connection.
4. Global Event Bus
A central place where components can publish/subscribe to events. If each module had its own bus, nothing would sync.
class EventBus {
constructor() {
if (EventBus.instance) {
return EventBus.instance;
}
this.events = {};
EventBus.instance = this;
}
on(event, fn) {
(this.events[event] || (this.events[event] = [])).push(fn);
}
emit(event, data) {
(this.events[event] || []).forEach(fn => fn(data));
}
}
// Usage
const bus1 = new EventBus();
const bus2 = new EventBus();
bus1.on("login", user => console.log("User logged in:", user));
bus2.emit("login", { name: "Ali" });
console.log(bus1 === bus2); // true
✅ A single bus ensures all components share the same event system.
5. Application State (Mini Store)
React, Vue, Angular… all use a form of global state. A singleton makes sure everyone references the same state object.
class Store {
constructor(initialState = {}) {
if (Store.instance) {
return Store.instance;
}
this.state = initialState;
Store.instance = this;
}
getState() {
return this.state;
}
setState(newState) {
this.state = { ...this.state, ...newState };
}
}
// Usage
const store1 = new Store({ count: 0 });
store1.setState({ count: 1 });
const store2 = new Store();
console.log(store2.getState()); // { count: 1 }
✅ Both references point to the same store. That’s the core idea of Redux/Vuex/MobX, simplified.
Bonus: Module Pattern in JS = Singleton
In ES modules, any exported object is effectively a singleton; it’s cached and reused everywhere.
// store.js
export const store = { count: 0 };
// file1.js
import { store } from "./store.js";
store.count++;
// file2.js
import { store } from "./store.js";
console.log(store.count); // updated value
✅ The module system itself enforces a singleton instance.
Wrapping It All Up
Here are 5 practical Singleton Pattern uses in JavaScript:
- Config Manager → one source of truth for settings
- Logger → consistent logs across the app
- Database Connection → single pool, fewer resources
- Event Bus → decoupled communication across modules
- Global Store → single state, shared everywhere
👉 Key takeaway: The Singleton Pattern isn’t just academic; it solves real-world problems whenever you want exactly one instance across your app.
Call to Action
👉 Which singleton example have you used before? Drop it in the comments 👇.
📤 Share this with a teammate who keeps spinning up “just another logger.”
🔖 Bookmark this for your design-pattern toolkit.
Leave a Reply