DEV Community

Cover image for Singleton Pattern Explained Simply With JavaScript Examples
Arun Teja
Arun Teja

Posted on

Singleton Pattern Explained Simply With JavaScript Examples

Design patterns often feel abstract until we clearly see the problem they solve.

The Singleton Pattern is one of the simplest & important design patterns, yet it is frequently misunderstood and misused.

In this article, we’ll break down the Singleton Pattern using clear explanations, a relatable real-world perspective, and a practical JavaScript example that shows why this pattern exists.


Core Values & Definition

Core Value

Control and consistency.

The Singleton Pattern exists to answer one important question:

How do we ensure that only one instance of an object exists across the entire application?

Some objects represent shared resources. Creating multiple instances of such objects can lead to:

  • Inconsistent state
  • Conflicting behavior
  • Difficult debugging
  • Unnecessary memory usage

Definition

The Singleton Pattern ensures that a class or object has only one instance and provides a global access point to that instance.

In simpler terms:

  • Object creation is controlled
  • Everyone works with the same instance
  • The application behaves consistently

Main Features

A typical Singleton has the following characteristics:

  • Single instance throughout the application lifecycle
  • Global access point to that instance
  • Controlled creation logic
  • Shared state across all consumers
  • Often lazy initialization (created only when needed)

A Real-World Perspective

Think about the music player on your phone.

You can control it from multiple places:

  • Lock screen
  • Notification panel
  • Music app itself

But no matter where you press play or pause, there is only one active music player running in the background.

If your phone created a new music player instance every time you interacted with a control:

  • Multiple songs would play at once
  • Volume controls would conflict
  • The entire experience would break

To avoid this, the system ensures that all controls talk to the same underlying player instance.

That is exactly how the Singleton Pattern works:
one shared instance, accessed from many places, behaving consistently.


Practical Exercise

Scenario: Centralized Application Logger

In real-world applications:

  • Logs are generated from many different files
  • Logs should be collected in one place
  • Log order and consistency are important for debugging

Creating multiple logger instances would:

  • Fragment logs
  • Break ordering
  • Make debugging harder

A logger is a perfect candidate for the Singleton Pattern.


JavaScript Implementation

class Logger {
  constructor() {
    if (Logger.instance) {
      return Logger.instance;
    }

    this.logs = [];
    Logger.instance = this;
  }

  log(message) {
    const entry = `[${new Date().toISOString()}] ${message}`;
    this.logs.push(entry);
    console.log(entry);
  }

  getLogs() {
    return this.logs;
  }
}

// Usage
const logger1 = new Logger();
const logger2 = new Logger();

logger1.log("Application started");
logger2.log("User logged in");

console.log(logger1 === logger2); // true
Enter fullscreen mode Exit fullscreen mode

What This Example Demonstrates

  • Only one logger instance exists across the application
  • Logs coming from different parts of the code end up in the same place
  • Shared state is intentional and meaningful
  • The need for Singleton is clear and practical, not theoretical

This example shows why Singleton is useful when multiple instances would actively cause problems, not just inconvenience.


Real-World Use Cases

The Singleton Pattern is commonly used for:

  • Logger services
  • Database connection managers
  • Cache managers
  • Message queue clients (Kafka, RabbitMQ)
  • Feature flag systems
  • Application-wide configuration loaders

These are shared infrastructure components that should remain consistent across the entire application.


How to Identify When to Use Singleton

Use the Singleton Pattern when:

  • You need exactly one instance of an object
  • The object represents a shared resource
  • Multiple instances would lead to conflicts or inconsistency
  • Consistency across the application is critical
  • Object creation is expensive or resource-heavy

A helpful question to ask yourself is:

Does it make sense for this object to exist more than once?

If the answer is no, Singleton is a strong candidate.


When NOT to Use Singleton

Avoid the Singleton Pattern when:

  • You need multiple independent instances
  • Behavior should vary per consumer
  • Test isolation is important
  • Global state would increase coupling between modules

Singleton should be used deliberately, not by default.


Disadvantages and Trade-offs

Like any design pattern, Singleton comes with trade-offs.

Common Issues

  • Behaves like global state
  • Makes unit testing harder
  • Introduces hidden dependencies
  • Can be easily overused or abused

These issues usually arise when Singleton is used outside of infrastructure-level concerns.


How to Mitigate These Issues

  • Keep Singleton logic minimal and focused
  • Avoid placing business logic inside Singleton classes
  • Prefer dependency injection where possible
  • Use Singleton mainly for shared infrastructure components

Used carefully, these practices reduce the downsides significantly.


Final Thoughts

The Singleton Pattern is neither good nor bad—it is a tool.

Used correctly, it provides:

  • Order
  • Consistency
  • Predictability

Used carelessly, it can introduce:

  • Tight coupling
  • Testing complexity
  • Hidden dependencies

The key is intentional usage.

When a system genuinely needs one and only one instance, the Singleton Pattern is the right choice.

Top comments (0)