Custom Settings and Custom Metadata Patterns
Pattern Intent: Centralize configuration so that logic and data can change at different speeds without code rewrites or risky production edits.
Overview
Custom Settings and Custom Metadata Types provide declarative configuration storage:
- Custom Settings: Row-level configuration cached in memory, good for org-wide and user-level flags.
- Custom Metadata Types (CMDT): Metadata that can be deployed between orgs and packaged; preferred for most configuration in modern architectures.
This document explains how to choose between them and how to structure configuration for Flows, Apex, and integrations.
Prerequisites
- Required Knowledge:
- Basic understanding of objects and records in Salesforce.
- Ability to create fields and records in Setup.
- Recommended Reading:
When to Use
Use Custom Metadata When
- Configuration must be deployed between environments (Git → CI/CD → orgs).
- You need version control and change tracking for configuration.
- Configuration is referenced by Apex, Flows, and validation rules.
- You work on managed packages or multi-org solutions.
Use Custom Settings When
- Values are org-specific and not usually deployed (e.g., per-sandbox toggles).
- You need user- or profile-level overrides (
Hierarchytype). - You require very fast, cached access to simple flags and limits.
Avoid Both When
- The data is transactional (belongs in objects, not configuration).
- You need highly dynamic user-entered data that changes frequently.
Core Concepts
Configuration as Data
Treat configuration as data:
- Keep business rules in CMDT where possible.
- Keep operational flags (e.g., “maintenance mode”) in Custom Settings.
Lookup by External Keys
Use stable keys (e.g., DeveloperName, external Id-style fields) to look up CMDT or settings:
- Avoid hardcoding record Ids in Apex or Flow.
- Use enums or constants in Apex to reference configuration keys.
Patterns and Examples
Pattern 1: Feature Flag via Hierarchy Custom Setting
- Create a
HierarchyCustom Setting with a Boolean field such asEnable_Feature_X__c. - Read it in Apex via
MySetting__c.getInstance().Enable_Feature_X__c. - Allow per-user or per-profile overrides for pilots.
Pattern 2: CMDT-Driven Routing Rules
- Use a CMDT like
Routing_Rule__mdtwith fields:Channel__cRecordType__cTarget_Queue__c
- Query CMDT in Apex or Flow to determine routing without changing code.
Pattern 3: Decision Framework: Custom Object vs CMDT vs Custom Setting
Use the decision frameworks described in the Decision Frameworks section of the repo (to be expanded) to select the right storage based on:
- Who maintains the data.
- How often it changes.
- Whether it must be deployed between orgs.
Edge Cases and Limitations
- CMDT records cannot be modified by end users in production without deployments (good for control, bad for rapid changes).
- Custom Settings can be changed in production UI, which can be risky if not controlled.
- Both CMDT and Custom Settings count toward limits (number of records and total configuration).
Related Patterns
Q&A
Q: When should I migrate from Custom Settings to Custom Metadata?
A: Migrate when you need deployment control, versioning, or packaging for configuration. CMDT is preferred for long-lived configuration, while Custom Settings are better for environment-specific toggles and hierarchy overrides.
Q: Can I use CMDT in Flows?
A: Yes. Modern Flows can reference CMDT via Get Records and decision elements. This enables configuration-driven Flows where business rules are stored outside the Flow definition.