Only One of Its Kind: Rethinking the Singleton Pattern in JavaScript
The singleton pattern ensures that only one instance of an object exists and is shared across an application, providing a single source of truth while introducing trade-offs around global state and tight coupling.
At first, creating objects in JavaScript feels effortless.
You call a function.
You get a new instance.
You move on.
const a = createConfig()
const b = createConfig()Each call produces something fresh.
Independent.
Isolated.
And most of the time, thatâs exactly what you want.
But not always.
When Multiplicity Becomes a Problem
There are moments when creating multiple instances doesnât just feel unnecessaryâ
it feels wrong.
Imagine:
- a global configuration
- a logging system
- a central store
If each part of your application creates its own version, something subtle breaks.
The system loses its sense of unity.
State diverges.
Behavior becomes inconsistent.
And suddenly, the question arises:
âWhich one is the real one?â
The Desire for a Single Source
This is where the singleton pattern emerges.
Not as a restrictionâ
but as a response.
It enforces a simple rule:
There should only ever be one instance of this.
And more importantly:
Everyone should share it.
Controlling Creation
Instead of allowing objects to be created freely, you introduce control.
let instance = null
function getInstance() {
if (!instance) {
instance = { count: 0 }
}
return instance
}Now, no matter how many times you call it:
const a = getInstance()
const b = getInstance()You always receive the same object.
Not copies.
Not variations.
The same instance.
Not About LimitationâBut Consistency
The goal is not to prevent creation for the sake of it.
Itâs to maintain consistency.
A single place where:
- state is stored
- behavior is defined
- truth is maintained
Without it, each part of your system begins to drift.
With it, everything aligns around a shared core.
The Quiet Presence of Singleton
Interestingly, youâve already been using this pattern.
In modern JavaScript modules:
// config.js
export const config = { theme: "dark" }Every import receives the same object.
No duplication.
No re-creation.
The module itself becomes a singleton.
Not by conventionâ
but by design.
The Trade-Off Beneath the Surface
But this convenience comes with a cost.
When everything shares the same instance:
- changes in one place affect everything
- dependencies become implicit
- debugging becomes more complex
The system becomes tightly connected.
Not visibly.
But structurally.
A Subtle Danger
Singletons often feel like a solution.
But over time, they can become a hidden global state.
And global state has a tendency to spread influence quietly.
What starts as convenience can turn into dependency.
And dependency can turn into fragility.
A Different Way to See It
The singleton pattern is not about creating less.
Itâs about deciding ownership.
Who owns this data?
How many versions should exist?
How widely should it be shared?
These are design questions.
Not implementation details.
A Final Thought
Thereâs a certain elegance in having a single source of truth.
One place to look.
One place to update.
One place to trust.
But with that elegance comes responsibility.
Because once everything depends on that one instanceâ
every change matters.
And once you understand that,
you stop using singletons as a convenienceâ
and start treating them as a commitment.