Freeze the instance with Object.freeze(instance) if it should be immutable after creation.
Avoid singletons for anything that varies per request in server-side code.
Details
The Singleton pattern is one of the most debated patterns in JavaScript. The classic implementation uses a class with a static instance, but ES modules provide a simpler alternative: any module-level variable is effectively a singleton because Node.js and browsers cache module exports after the first import.
Trade-offs:
Singletons introduce global state, making code harder to test (you cannot easily create a fresh instance per test)
Hidden dependencies — callers cannot know from the function signature that they depend on a singleton
Mutable singletons are a source of subtle bugs in concurrent environments (avoid in server-side code handling multiple requests)
When NOT to use:
When you need multiple instances with different configurations
In unit tests — inject dependencies instead and pass a fresh instance per test
When the "singleton" is stateless — a plain object literal or a set of pure functions is simpler
Related patterns:
Module Pattern — a module-scoped variable achieves singleton semantics without a class
Proxy Pattern — a Proxy can intercept access to a singleton to add logging or validation
Read the instructions and examples in this document.
Apply the patterns to your implementation, adapting to your specific context.
Verify your implementation against the details and edge cases listed above.
Harness Integration
Type: knowledge — this skill is a reference document, not a procedural workflow.
No tools or state — consumed as context by other skills and agents.
Success Criteria
The patterns described in this document are applied correctly in the implementation.
Edge cases and anti-patterns listed in this document are avoided.
1---2name: js-singleton-pattern3description: JS Singleton Pattern4---5# JS Singleton Pattern67> Ensure a class has only one instance and provide a global access point89## When to Use1011- You need exactly one shared instance across the entire application (e.g., a database connection, logger, or config object)12- Multiple parts of the codebase should access the same object without prop-drilling or passing references13- The instance is expensive to create and should be reused1415## Instructions16171. Create a class with a private constructor and a static instance variable.182. Add a static `getInstance()` method that returns the existing instance or creates one on first call.193. Export only `getInstance()`, not the class itself.204. In ESM modules, prefer a module-level variable over a class — a module is already a singleton by the loader.2122```javascript23// Preferred ESM approach — module-level singleton24let instance;2526class DatabaseConnection {27 constructor(url) {28 if (instance) return instance;29 this.url = url;30 this.connected = false;31 instance = this;32 }3334 connect() {35 this.connected = true;36 }37}3839export const getInstance = (url) => new DatabaseConnection(url);40```41425. Freeze the instance with `Object.freeze(instance)` if it should be immutable after creation.436. Avoid singletons for anything that varies per request in server-side code.4445## Details4647The Singleton pattern is one of the most debated patterns in JavaScript. The classic implementation uses a class with a static instance, but ES modules provide a simpler alternative: any module-level variable is effectively a singleton because Node.js and browsers cache module exports after the first `import`.4849**Trade-offs:**5051- Singletons introduce global state, making code harder to test (you cannot easily create a fresh instance per test)52- Hidden dependencies — callers cannot know from the function signature that they depend on a singleton53- Mutable singletons are a source of subtle bugs in concurrent environments (avoid in server-side code handling multiple requests)5455**When NOT to use:**5657- When you need multiple instances with different configurations58- In unit tests — inject dependencies instead and pass a fresh instance per test59- When the "singleton" is stateless — a plain object literal or a set of pure functions is simpler6061**Related patterns:**6263- Module Pattern — a module-scoped variable achieves singleton semantics without a class64- Proxy Pattern — a Proxy can intercept access to a singleton to add logging or validation6566## Source6768https://patterns.dev/javascript/singleton-pattern6970## Process71721. Read the instructions and examples in this document.732. Apply the patterns to your implementation, adapting to your specific context.743. Verify your implementation against the details and edge cases listed above.7576## Harness Integration7778- **Type:** knowledge — this skill is a reference document, not a procedural workflow.79- **No tools or state** — consumed as context by other skills and agents.8081## Success Criteria8283- The patterns described in this document are applied correctly in the implementation.84- Edge cases and anti-patterns listed in this document are avoided.
Run npx skillmds@latest add intense-visions/js-singleton-pattern in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
JS Singleton Pattern It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Intense-Visions (@intense-visions) published this skill. Their other Agent Skills are listed on their SkillMD profile.