Two types: List and Hierarchy. They share the underlying caching mechanism but differ in how records are looked up and what API call you use.
1. List Custom Settings
A flat lookup table. Each record has a Name (a string key) and arbitrary fields. You fetch records by their Name.
// One record by key
Country_Code__c india = Country_Code__c.getValues('IN');
String currency = india.Currency__c;
// All records
Map<String, Country_Code__c> all = Country_Code__c.getAll();
for (String code : all.keySet()) {
System.debug(code + ' → ' + all.get(code).Currency__c);
}
Common uses:
- ISO country / currency / state code tables
- Static mappings (regions → endpoints, codes → labels)
- Tax brackets, pricing tiers, holiday calendars
Up to 300 records per List setting by default (and the cap can be raised).
2. Hierarchy Custom Settings
A single resolved record that the platform picks based on a precedence rule:
- The running User’s personal record, if one exists.
- The running user’s Profile record, if one exists.
- The Organization-wide default record.
Feature_Flags__c flags = Feature_Flags__c.getInstance(); // for current user
Feature_Flags__c orgFlags = Feature_Flags__c.getOrgDefaults(); // org-wide only
Feature_Flags__c userFlags = Feature_Flags__c.getInstance(userId); // specific user
You can also create Hierarchy records keyed by Profile Id rather than User Id. The platform handles the cascade automatically; getInstance() returns the most-specific match.
Common uses:
- Feature flags (“enable new search for me”)
- Per-profile threshold overrides (“Sales Manager profile sees opportunities ≥ $1k; Reps see ≥ $10k”)
- Trigger bypass switches that admins can toggle for themselves while debugging
When to choose which
| Need | Pick |
|---|---|
| Lookup table indexed by a string key | List |
| Configuration that varies per user/profile | Hierarchy |
| One single configuration record for the whole org | Hierarchy (use getOrgDefaults()) |
| Multiple records of the same shape but different keys | List |
A side-by-side example
// LIST — flat table of region endpoints
Region_Endpoint__c r = Region_Endpoint__c.getValues('US-WEST');
String url = r.Endpoint_URL__c;
// HIERARCHY — single config that varies per user
Trigger_Settings__c t = Trigger_Settings__c.getInstance();
Boolean accountTriggerEnabled = t.Account_Trigger_Enabled__c;
A list setting always returns one specific record by key. A hierarchy setting returns the appropriate version for the running user/profile/org.
What both share
- Cached in memory —
getInstance(),getValues(),getAll(),getOrgDefaults()don’t fire SOQL. - DML is allowed —
insert,update,deletework in Apex (this is the one thing Custom Metadata can’t do). - Defined in Setup, not the Object Manager’s standard custom object UI.
- Don’t deploy with their data between orgs — change sets only carry the schema, not the records. (This is why Custom Metadata replaced them for new work.)
A common bug: querying a Custom Setting with SOQL
You can write SELECT Name, Currency__c FROM Country_Code__c — and it works. But you’ve just fired a SOQL query and bypassed the cache. Always use the static accessors:
// BAD — defeats the cache
List<Country_Code__c> codes = [SELECT Name, Currency__c FROM Country_Code__c];
// GOOD — cached, no SOQL
Map<String, Country_Code__c> codes = Country_Code__c.getAll();
What interviewers are really looking for
The first answer: List and Hierarchy. The senior signal: (1) Hierarchy’s resolution cascade — User → Profile → Org, (2) the right API for each — getValues for List, getInstance/getOrgDefaults for Hierarchy, (3) records are cached automatically — never use SOQL on them, (4) Custom Metadata Types is the modern replacement, but Custom Settings still win when Apex needs to write the values at runtime.
Verified against: Salesforce Help — Custom Settings Methods and Types, Apex Developer Guide — Custom Setting Methods. Last reviewed 2026-05-17.