A Hierarchy Custom Setting holds one resolved record per user, picked by a cascade: User → Profile → Organization. The most-specific match wins. The pattern is built specifically for cases like feature flags, per-profile thresholds, and individual override switches — config that varies by who’s running the code.
How the cascade works
When you call MySetting__c.getInstance():
- The platform looks for a record whose
SetupOwnerIdis the current user’s Id. If one exists, return it. - Otherwise, look for a record whose
SetupOwnerIdis the current user’s Profile Id. If one exists, return it. - Otherwise, return the Organization-wide default record.
You always get something (assuming an Org default exists). The cascade hides the details — your Apex code just does getInstance() and gets the right values.
The Setup UI
When you edit a Hierarchy Custom Setting in Setup, you see three sections:
- Default Organization Level Value — the fallback for everyone.
- Profile-Level Values — per-profile overrides.
- User-Level Values — individual-user overrides.
Each user record overrides each profile record overrides the org default.
A worked example
Custom Setting: Trigger_Settings__c with one checkbox Account_Trigger_Enabled__c.
- Org default:
Account_Trigger_Enabled__c = true(the default). - Profile “Data Loader User”:
Account_Trigger_Enabled__c = false(bypass triggers during bulk loads). - User vikas@example.com:
Account_Trigger_Enabled__c = false(he’s debugging).
Boolean enabled = Trigger_Settings__c.getInstance().Account_Trigger_Enabled__c;
- If Vikas runs the trigger,
enabled = false(user-level wins). - If another Data Loader User runs it,
enabled = false(profile-level wins). - If anyone else runs it,
enabled = true(org default).
The three accessor methods
// 1) The resolved value for the running user (uses the cascade)
Trigger_Settings__c mine = Trigger_Settings__c.getInstance();
// 2) Force the org default, ignoring user/profile overrides
Trigger_Settings__c org = Trigger_Settings__c.getOrgDefaults();
// 3) The resolved value for a specific user (uses the cascade for that user)
Trigger_Settings__c other = Trigger_Settings__c.getInstance(someUserId);
getOrgDefaults() is useful in tests, async jobs, and any context where you don’t want individual-user behaviour to leak in.
Use cases
| Scenario | Why hierarchy fits |
|---|---|
| Feature flags admins can enable per-user | Per-user override on top of the org default |
| Trigger bypass switches while debugging | User-level toggle without code change |
| Per-profile thresholds (different teams, different rules) | Profile-level override |
| Region-specific integration endpoints | Org default per environment; per-profile if regional teams need overrides |
Common pitfalls
- Forgetting to seed the org default —
getInstance()returns an empty record (all nulls) if no default exists. Calling.Account_Trigger_Enabled__con a null record returns null, not the platform’s idea of “the default true.” Always seed the Org default in deployment scripts. - Trying to manage these via apex DML in production with concurrent writes — record locks apply just like any object.
- Testing in
@isTestwithout seeding the setting —Test.startTest()doesn’t auto-populate settings. Insert what you need in@TestSetup.
When NOT to use Hierarchy
- The config never varies — use Org default only with
getOrgDefaults(), or move to Custom Metadata Types. - The config is a list of records — use List Custom Settings or Custom Metadata.
- You need to deploy the records along with the code — switch to Custom Metadata Types.
What interviewers are really looking for
The naming check: User → Profile → Org cascade. The senior signal includes: (1) the three accessors (getInstance(), getOrgDefaults(), getInstance(userId)) and when to use each, (2) SetupOwnerId is the field that decides which level a record belongs to, (3) you must seed the Org default or getInstance() returns a record with null fields, (4) it’s the right tool when admins need to toggle behaviour for individual users without a code change, and the wrong tool when the config is purely static (use Custom Metadata).
Verified against: Salesforce Help — Hierarchy Custom Settings. Last reviewed 2026-05-17.