Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryCCustom Metadata Type
DevelopmentAdvanced

Custom Metadata Type

A Custom Metadata Type is a Salesforce configuration construct that stores records as metadata rather than data.

§ 01

Definition

A Custom Metadata Type is a Salesforce configuration construct that stores records as metadata rather than data. The records live in the same metadata tier as Apex classes, custom objects, and page layouts, which means they deploy through change sets, version in source control, and travel with managed packages. Apex, Flow, and formula fields can read Custom Metadata Type records without consuming SOQL governor limits, the same way they read Custom Settings.

Custom Metadata Types were introduced in 2015 as the strategic replacement for List Custom Settings. The difference matters: a Custom Setting record is data, a Custom Metadata record is metadata. Custom Metadata records can be deployed from sandbox to production, packaged into managed packages, and rolled back through deployment pipelines. They support cross-object relationships through Metadata Relationship fields, picklist fields, and protected visibility for managed-package authors. Most modern Salesforce configuration that does not need User or Profile hierarchy belongs in Custom Metadata Types rather than Custom Settings.

§ 02

How Custom Metadata Types replace Custom Settings for most configuration

Metadata versus data: the foundational distinction

Custom object records and Custom Setting records are data. They live in the data tier, count against data storage, and require Data Loader or manual entry to populate in each environment. Custom Metadata records are metadata. They live in the metadata tier alongside Apex and page layouts. Deploying a Custom Metadata record from sandbox to production is a metadata deployment, not a data migration. This distinction is the reason teams adopted Custom Metadata Types: configuration travels with deployments instead of being re-entered per environment.

Field types and Metadata Relationship fields

Custom Metadata Types support a broader range of field types than Custom Settings: Text, Number, Currency, Date, Date/Time, Checkbox, Email, Phone, URL, Percent, Long Text Area, and Picklist. The standout addition is Metadata Relationship, which lets a Custom Metadata record reference another Custom Metadata record or an EntityDefinition/FieldDefinition. This enables proper data-modeling patterns within configuration: a Tax Rule record can reference a Country, a Validation Setup record can reference a specific object and field.

Reading Custom Metadata in Apex without SOQL limits

Apex can read Custom Metadata Type records via SOQL: List<Tax_Rate__mdt> rates = [SELECT Country__c, Rate__c FROM Tax_Rate__mdt]. The SOQL query against the __mdt suffix does not count against the 100-query governor limit. The records also have a getInstance(developerName) method on the type itself: Tax_Rate__mdt.getInstance(''US''). Both access patterns are free against governor limits, which makes Custom Metadata ideal for configuration read in trigger handlers and batch processing.

Reading from Flow and formula fields

Flow reads Custom Metadata via the Get Records element, the same way it reads custom object data. Flow reads of Custom Metadata do count against the SOQL governor limit because Flow does not have the Apex cached APIs. Formula fields can reference Custom Metadata Type fields directly via the CustomMetadata global, useful for formula-driven business rules that depend on configurable thresholds without writing code.

Protected Custom Metadata and managed packages

Custom Metadata Types support a Protected visibility flag. Protected types are accessible only from code within the same managed package; subscriber org code cannot read or write them. This is the standard pattern for ISVs hiding configuration from subscriber admins: API keys, internal feature flags, license thresholds. Public Custom Metadata is accessible from any Apex, Flow, or formula in the org, which is the right choice for org-developed configuration.

Deploying Custom Metadata records via change sets and packages

Custom Metadata Type definitions deploy through change sets and metadata API like any custom object. Crucially, the records also deploy as metadata: include each Custom Metadata record in the change set or package manifest. This is what enables environment-promoted configuration. Setup > Custom Metadata Types > Records lets admins manage records through the UI for development, and the change set picks them up during deployment.

When Custom Settings still beat Custom Metadata

Hierarchy Custom Settings remain the only native option for User and Profile inheritance. If different users or profiles need different values for the same setting, Custom Metadata cannot do that natively without workarounds. List Custom Settings still beat Custom Metadata for configuration that admins need to edit in production without metadata deployments. The modern guidance is: default to Custom Metadata Types, fall back to Hierarchy Custom Settings for inheritance, and use List Custom Settings only when production-editable-without-deploy is a hard requirement.

§ 03

How to create a Custom Metadata Type

Creating a Custom Metadata Type is similar to creating a custom object. The difference shows up at deployment time, where records travel with metadata changes instead of requiring separate data loads. Plan the field types, decide between Public and Protected visibility, and design the records as a deployable artifact from the start.

  1. Confirm Custom Metadata is the right tool

    Use Custom Metadata for static configuration that should deploy with code, support cross-object relationships, and stay out of the data tier. Use Hierarchy Custom Settings if User or Profile inheritance is required. Use List Custom Settings only when production admin editing without deploy is critical.

  2. Create the Custom Metadata Type

    Setup > Custom Metadata Types > New Custom Metadata Type. Enter label, plural label, and API name. The API name automatically gets the __mdt suffix. Choose Public or Protected visibility based on whether external code should access the records.

  3. Add custom fields

    From the type detail page > Custom Fields & Relationships > New. Pick the field type. Metadata Relationship fields let one record reference another Custom Metadata record or an EntityDefinition/FieldDefinition. Picklist fields are supported, unlike on Custom Settings.

  4. Build records via the Manage button

    Setup > Custom Metadata Types > the type > Manage Records > New. For each record, enter the Label, Developer Name (the primary key for getInstance lookups), and the field values. Records appear in the manifest as separate metadata files.

  5. Reference from Apex with getInstance or SOQL

    Tax_Rate__mdt rate = Tax_Rate__mdt.getInstance(''US''); for direct lookup. List<Tax_Rate__mdt> rates = [SELECT Country__c, Rate__c FROM Tax_Rate__mdt]; for bulk read. Both access patterns are free against SOQL governor limits.

  6. Reference from formulas via the CustomMetadata global

    Formula syntax: CustomMetadata.Tax_Rate__mdt.Default.Rate__c (prefixed with the formula-engine dollar global) in formula fields. This is the formula-engine path to Custom Metadata, useful for business rules that depend on configurable thresholds without touching Apex.

  7. Deploy via change set or metadata API

    Include the Custom Metadata Type definition AND the individual records in the change set or package manifest. Each record is its own metadata file (Tax_Rate.US.md-meta.xml). The deployment moves both type and records to the target org.

  8. Version the metadata in source control

    Custom Metadata records belong in the version-controlled repo alongside Apex classes. Use SFDX project format. Pull request reviews catch configuration changes the same way they catch code changes, which is the major workflow win over Custom Settings.

Key options
Visibility (Public or Protected)remember

Public for org-wide access. Protected for managed-package-only access. Drives whether subscriber-org code can read the records.

Field Typesremember

Text, Number, Date, Checkbox, Picklist, Long Text Area, Metadata Relationship. Broader than Custom Settings; picklists and relationships work natively.

Record Developer Nameremember

The primary key used by getInstance and formula lookups. Cannot be changed after creation without breaking references.

Gotchas
  • Custom Metadata records are metadata. Inserts and updates via API require Metadata API or the Metadata.Operations Apex class, not standard DML. Apex DML on __mdt objects throws an error.
  • Custom Metadata does not support User or Profile hierarchy. Use Hierarchy Custom Settings if different users need different values for the same setting.
  • Flow Get Records on Custom Metadata counts against SOQL governor limits because Flow does not use the Apex cache. Cache results in Flow variables when reading multiple times.
  • Protected visibility is irrevocable once a managed package is uploaded. Downgrading from Protected to Public breaks the package security boundary, so design carefully up front.
  • Deploying Custom Metadata records requires explicit inclusion in the change set or package manifest. Forgetting to include records during deployment is a common cause of post-deployment behavior changes.
§

Trust & references

Sources

Cross-checked against the following references.

Official documentation

Straight from the source - Salesforce's reference material on Custom Metadata Type.

Keep learning

Hands-on resources to go deeper on Custom Metadata Type.

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

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. What makes Custom Metadata Types different from Custom Settings?

Q2. Which is a good use case for Custom Metadata Types?

Q3. Can Custom Metadata Types be queried from Formula fields and Validation Rules?

§

Discussion

Loading…

Loading discussion…