Design Patterns: Singleton in Salesforce Apex

04.10.2025. 2 min read
Design Patterns APEX

The singleton pattern behaves a little differently in Salesforce than in languages like C# or Java. In Apex, a singleton instance persists only for the lifetime of the current transaction (execution context). This leads some developers to dismiss the pattern as “useless” in Salesforce. However, this view is incomplete: singletons can be extremely useful within a single execution, especially when repeated object creation or data retrieval would otherwise waste CPU or heap resources.

A singleton is simply a class with a private constructor and a static accessor method. The accessor instantiates the class once and returns the same instance for subsequent calls. This minimizes redundant work, keeps configuration centralized, and ensures consistency.

Example:

public class ConfigService {
    private static ConfigService instance;
    private Map<String, My_Config__mdt> settings;


    // Private constructor
    private ConfigService() {
        settings = new Map<String, My_Config__mdt>();
        for (My_Config__mdt cfg : [
            SELECT DeveloperName, Setting_Value__c FROM My_Config__mdt
        ]) {
            settings.put(cfg.DeveloperName, cfg);
        }
    }


    // Public accessor
    public static ConfigService getInstance() {
        if (instance == null) {
            instance = new ConfigService();
        }
        return instance;
    }


    public String getValue(String key) {
        return settings.containsKey(key) ? settings.get(key).Setting_Value__c : null;
    }
}

ConfigService usage:

String threshold = ConfigService.getInstance().getValue('DiscountThreshold');

Use singleton for lean and efficient code:

  1. Avoids duplication: Ensures an object or configuration is created once and reused.
  2. Minimizes overhead: Cuts down on redundant SOQL queries, DML operations, or object instantiations that waste CPU cycles.
  3. Streamlines memory usage: Stores frequently accessed data in a single instance, balancing CPU savings with minimal heap cost.
  4. Keeps logic centralized: Encapsulates common retrieval or processing logic in one place, making the codebase easier to maintain.
  5. Improves consistency: Guarantees uniform values across the transaction, reducing the risk of mismatched or outdated references.
  6. Supports scalability: Helps long-running or complex transactions stay efficient by reducing unnecessary work.
  7. Promotes reusability: A well-designed singleton can serve multiple classes and contexts without rewriting logic.

About

Here you’ll find stories, ideas, and reflections around Salesforce Revenue Cloud. We write about the everyday challenges of quoting, billing, and managing subscriptions, but also share lessons we’ve learned along the way.