List Custom Settings
A List Custom Setting is a type of Salesforce custom setting that stores reusable key-value data in the application cache, where every record is the same for every user.
Definition
A List Custom Setting is a type of Salesforce custom setting that stores reusable key-value data in the application cache, where every record is the same for every user. Each row is identified by a Name field, and Apex reads it through the generated getValues(name) and getAll() methods. Because the data lives in the cache, those reads do not count against SOQL query governor limits.
A List Custom Setting differs from a Hierarchy Custom Setting in one key way: it has no per-user or per-profile precedence. The value is identical for the whole org. That makes it a good fit for configuration that applies to everyone, such as country codes, tax rates, integration endpoints, or a feature kill switch. It is a cached lookup table, not a full custom object, so it carries field-type restrictions and a size cap.
How List Custom Settings work and where they fit
List versus Hierarchy: pick once, at creation
Salesforce ships two custom setting types, and the choice is permanent. A List Custom Setting treats every record as independent and global. Ask for a record by its Name and you get the same value no matter who is logged in. A Hierarchy Custom Setting layers an org default under profile-level overrides under user-level overrides, then returns the most specific match for the running user. Choose List when the configuration is the same for everyone, such as a table of currency codes or a map of error messages. Choose Hierarchy when a value legitimately changes per user or per profile, such as a personal API quota. You cannot convert one type into the other after creation, so the decision belongs in your design, not in a later cleanup. A common mistake is reaching for Hierarchy out of habit when the data never varies per user. That adds cascade logic you do not need and makes the records harder to reason about. If two people should always see the same answer, List is the simpler and more honest model.
Reading data from Apex without SOQL
The platform generates typed accessor methods on the custom setting sObject, so you never write SOQL against it. getAll() returns every record as a Map keyed by the Name field, which is ideal when code needs to iterate or look several values up at once. The shape is Map<String, MySetting__c> all = MySetting__c.getAll();. getValues(name) returns a single record matching that Name, or null when no record exists, so guard against null before reading a field. Both calls read from the application cache rather than the database. That is the headline benefit: a code path that needs configuration on every transaction can fetch it freely without burning one of your 100 synchronous SOQL queries. The same data is also reachable from formulas, validation rules, and flows in many contexts, though the Apex accessors are the most common entry point. Cache them in a static variable if a single transaction reads the same setting many times, since even a cache hit is cheaper when it happens once.
Supported field types and the 10 MB cap
List Custom Settings support a deliberately narrow set of field types: Checkbox, Currency, Date, Date/Time, Email, Number, Percent, Phone, Text, Text Area, and URL. Formula fields, picklists, and any relationship field (Lookup or Master-Detail) are not available. Text fields are limited in length, so a setting is not the place for long blocks of content. The harder ceiling is size. All custom setting data in an org shares a single cap of roughly 10 MB, and that pool is shared across every List and Hierarchy setting combined. Salesforce calculates the exact allowance from your number of full user licenses, with 10 MB as the practical maximum for most orgs. Each record costs about 2 KB, which works out to a few thousand records before you run out of room. Cross the limit and the platform blocks new records until you free space. Plan size up front: settings are for compact reference data, not for storing thousands of transactional rows that belong in a real object.
The deployment data gap
Here is the catch that surprises teams. When you deploy through a change set or a package, the custom setting definition travels (the object header and its fields), but the records inside do not. The target org receives an empty setting. For environment-specific values this is often what you want, since you would never push sandbox endpoints into production. For shared reference data it is pure friction, because someone has to recreate every row by hand or run a script after each deployment. Common workarounds include populating records with an Apex post-install script, loading them with Data Loader against a CSV, or writing a small anonymous Apex block as part of the release checklist. Whatever you choose, document it, because a deploy that silently ships an empty setting tends to fail at runtime in a confusing way. Code calls getValues, gets null, and behaves as if the feature were turned off. Treat the data load as a required deployment step, not an afterthought, and verify the rows exist before you call the release done.
Custom Metadata Types: the modern alternative
Custom Metadata Types were built largely to close the deployment data gap. A custom metadata record is treated as metadata, so it moves with your code through change sets, unlocked packages, and source-tracked deployments. No post-deploy data load, no empty setting in production. For list-style configuration that should travel with releases, such as tax rates, support tiers, or routing rules, Custom Metadata Types are usually the better choice today, and Salesforce makes converting a List Custom Setting into a type fairly easy. They also support relationship and picklist-style fields that settings lack. List Custom Settings still hold ground in two cases. First, data that should stay environment-specific, where you actually want it to not deploy. Second, larger data sets, since metadata records carry their own limits and a setting can hold compact reference data the cache serves quickly. Salesforce does not recommend converting Hierarchy settings to metadata, because the per-user cascade has no clean equivalent. So the rule of thumb is: new shared config goes to Custom Metadata Types, while List Custom Settings cover environment values and legacy code.
When a real custom object is the right call
A List Custom Setting is intentionally simple, and that simplicity is its limit. The moment your configuration needs behavior, the setting stops being enough. You cannot put a validation rule, a trigger, a flow, a sharing rule, or a lookup relationship on a custom setting. There is no record-level security; every user who can read the setting reads all of it. If admins need to manage hundreds or thousands of rows through list views and reports, a setting is awkward, and you may hit the size cap anyway. In those cases, use a regular custom object. You get the full feature set: relationships, automation, validation, sharing, reporting, and effectively unlimited rows that count against normal data storage rather than the cache. The trade-off is that object reads use SOQL and do count against governor limits, so you lose the free cached access. A practical pattern is to keep tiny, hot, read-on-every-transaction config in a List Custom Setting or Custom Metadata Type, and push anything that needs validation, security, or volume into a proper object.
Create a List Custom Setting and read it from Apex
You create a List Custom Setting in Setup, add its fields, then add the actual data records. The definition deploys between orgs, but the records do not, so plan to load data separately in each environment.
- Create the setting
In Setup, go to Custom Settings and click New. Enter a Label and Object Name, choose Setting Type = List, set Visibility to Public or Protected, then save.
- Add custom fields
On the setting detail page, add the fields you need from the supported types (Text, Number, Checkbox, Date, Email, URL, and similar). Lookups, picklists, and formulas are not available.
- Add data records
Click Manage, then New, and create each record. The Name field identifies the row that getValues(name) will return, so use stable, predictable names your code can rely on.
- Read it from Apex
Call MySetting__c.getValues('Some_Name') for one record or MySetting__c.getAll() for the full Map. Neither call consumes a SOQL query, since the data is served from the application cache.
Set this to List so every record is global. The alternative, Hierarchy, adds per-user and per-profile overrides you do not want for shared data, and the type cannot be changed later.
Public exposes the setting to subscriber code in a managed package; Protected hides it. For an org-internal setting either works, but Protected is safer if you later package the code.
The unique text key for each record. Code fetches a row by this Name, so treat it as a stable identifier and avoid renaming records that running code depends on.
- The definition deploys through change sets, but the records do not. The target org gets an empty setting until you load the data manually or by script.
- getValues(name) returns null when no record matches, so null-check before reading a field or the transaction throws a null pointer error.
- All custom setting data shares a roughly 10 MB org-wide cap across List and Hierarchy combined. Large or growing data sets belong in a custom object instead.
- Updates take a few seconds to propagate across application servers, so a record written and re-read in the same flow may briefly return a stale value.
Prefer this walkthrough as its own page? How to List Custom Settings in Salesforce, step by step
Trust & references
Cross-checked against the following references.
- Custom Settings | Apex Developer GuideSalesforce
- Custom Settings Limits and ConsiderationsSalesforce
Straight from the source - Salesforce's reference material on List Custom Settings.
Hands-on resources to go deeper on List Custom Settings.
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Test your knowledge
Q1. How do List Custom Settings differ from Hierarchy Custom Settings in how records are resolved?
Q2. What is the documented total storage cap across all Custom Settings, List and Hierarchy combined, in an org?
Q3. Which modern feature was introduced specifically to solve the List Custom Settings deployment-data problem, since its records travel with code?
Discussion
Loading discussion…