Custom Settings are a Salesforce data type for org-wide configuration — feature flags, thresholds, API endpoints, integration keys, “bypass this trigger” toggles. The defining feature: their records are cached in the application server’s memory, so reading them in Apex doesn’t cost a SOQL query.
Decimal threshold = Trigger_Settings__c.getInstance().Score_Threshold__c;
// no SOQL fired, no governor cost
For new projects in 2026, Custom Metadata Types has effectively replaced Custom Settings for almost every use case. But every Salesforce codebase still contains Custom Settings, and the interview will probe whether you understand them.
Two flavors
Custom Settings come in two flavours: List and Hierarchy.
List Custom Settings
Hold a flat list of records, like a lookup table. You access individual records by Name.
Country_Code__c india = Country_Code__c.getValues('IN');
String currency = india.Currency__c;
Use case: list of country codes, a set of currency rates, a table of integration endpoints by region.
Hierarchy Custom Settings
Have a single record that the platform resolves per-user, per-profile, or org-wide — whichever level is most specific for the running user.
Feature_Flags__c flags = Feature_Flags__c.getInstance(); // current user
Boolean canUseNewSearch = flags.Use_New_Search__c;
Use case: feature flags that some users can opt into, defaults that admins override per profile.
The cache contract
Custom Setting records live in the application cache automatically. The platform invalidates the cache when the record is updated. Reads are O(1) memory access, not SOQL.
This is why they were originally introduced — pre-cloud, the alternative was either hardcoding values (terrible) or doing a SOQL query on every trigger fire (governor-limit nightmare).
How they’re created
- Setup → Custom Settings → New
- Pick “List” or “Hierarchy”
- Add fields like any custom object
- Add records via Setup or Apex
Records are managed in Setup, not in the data tab. Each list-type Custom Setting can hold up to 300 records by default (org-wide).
How they differ from Custom Objects
| Aspect | Custom Object | Custom Setting |
|---|---|---|
| API suffix | __c | __c (visually the same, but distinct type) |
| Storage | Counts against data storage | Counts against cached settings (10 MB cap) |
| Caching | No automatic cache — SOQL every time | Yes — getInstance() and getValues() are O(1) |
| Validation rules / triggers | Yes | No |
| Reports, list views, tabs | Yes | No |
| Sharing rules | Yes | No |
| Cross-org distribution | Manual | Manual; not picked up automatically by managed packages |
Why Custom Metadata replaced them
Salesforce introduced Custom Metadata Types (__mdt) for the same use cases. The differences that matter:
| Aspect | Custom Setting | Custom Metadata Type |
|---|---|---|
| Counts against | Cached settings (10 MB) | Metadata (no storage cost) |
| Deployable between orgs | Manual data load | Yes — deploys like code |
| Visible in Setup | Yes | Yes |
| Listed in packages | Records: no | Records: yes |
| Updates via DML in Apex | Yes | No — Metadata API only |
| Reference from formula fields | Limited | Full |
The deal-breaker for Custom Settings in 2026: records don’t deploy between orgs. A change set or unlocked-package deploy carries the definition but not the data. Custom Metadata Types deploy the data with the metadata, so dev → UAT → prod promotion is one-step.
The remaining reason to use Custom Settings: you need to update the values from Apex. Custom Metadata can only be edited via the Metadata API (Metadata.Operations.enqueueDeployment), which is async and admin-only.
Performance tips
getInstance()is cached. Call it freely.getValues('Key')for list settings hits the same cache.getAll()loads every record in the setting — fine for small lists, slow for the 300-record max.- Don’t
[SELECT ... FROM My_Setting__c]— it works but fires a SOQL query, defeating the cache. Always use the static accessors.
Visibility
A Custom Setting’s Visibility toggle (Protected vs Public) decides whether code in managed packages outside the defining package can read it. Public custom settings are visible to all subscriber code; Protected are only visible to code in the same managed package.
What interviewers are really looking for
The naming check: List vs Hierarchy. The senior signal includes: (1) records are cached automatically — getInstance() is governor-free, (2) Custom Settings don’t deploy between orgs with their data, which is why Custom Metadata replaces them for new work, (3) the one remaining use case for Custom Settings is when you must update the values from Apex, which Custom Metadata doesn’t allow.
Verified against: Salesforce Help — Custom Settings, Apex Developer Guide — Custom Settings. Last reviewed 2026-05-17.