Skip to main content

SF-0299 · Compare · Medium

What is the advantage of custom metadata over custom settings? Or what is the difference between custom metadata and custom settings?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

Both custom metadata types and custom settings store configuration. The decisive difference is how the records move between orgs: custom metadata records flow through metadata deployments alongside the schema, while custom settings records do not. That single fact drives almost every other decision between the two.

Side-by-side

AspectCustom Metadata Types (__mdt)Custom Settings (List or Hierarchy)
API suffix__mdt__c (like custom objects)
Records are metadata?Yes — deploy with change sets / packagesNo — must be migrated as data
Runtime writes from Apex?No — use Metadata API (async)Yes — standard DML
Cached read (no SOQL limit)?Yes — getAll() / getInstance()Yes — getAll() / getInstance() / getOrgDefaults()
RelationshipsMetadata relationships to other CMDT/objectsLimited; no master-detail
Per-user/profile valuesNo (would need to build manually)Yes — Hierarchy type natively supports it
Reportable?NoNo (with rare exceptions)
In packagesRecords ship with the packageSchema ships; records do not
Best forConfig that should travel with codePer-user toggles, runtime-writable counters

The deployment difference (the headline)

When you create an Integration Endpoint record in dev as a custom metadata record, you can include it in a change set, deploy it to UAT, then deploy to production. The record is XML in your repo. Three orgs, same record, no scripts, no data loader.

The same scenario with a custom setting requires:

  1. Export the records from dev (data loader, anonymous Apex, or workbench).
  2. Re-create them in UAT.
  3. Re-create them in production.
  4. Hope nobody forgot to do steps 2-3.

This is why CMDT has become the default for new configuration in modern Salesforce projects. Custom settings predate CMDT (CMDT was introduced in Winter ‘15) and are slowly being deprecated as the recommended approach for application configuration.

The write-path difference

// Custom setting — write at runtime with normal DML
Integration_Config__c cfg = Integration_Config__c.getInstance();
cfg.Last_Sync__c = System.now();
upsert cfg;

// Custom metadata — write via Metadata API, async
Metadata.DeployContainer container = new Metadata.DeployContainer();
Metadata.CustomMetadata cm = new Metadata.CustomMetadata();
cm.fullName = 'Integration_Endpoint.Stripe';
cm.values.add(new Metadata.CustomMetadataValue(
    field = 'Endpoint_URL__c', value = 'https://new.url'
));
container.addMetadata(cm);
Metadata.Operations.enqueueDeployment(container, null);

Custom settings can be written from Apex synchronously. Custom metadata cannot. If your use case writes records at runtime — usage counters, last-sync timestamps, per-user preferences — custom settings are the only option among the two.

When to use which

Use Custom Metadata Types when:

  • Configuration moves with code releases (feature flags, integration endpoints, routing rules).
  • Admins should rarely or never edit values at runtime.
  • You want records in the package so subscribers get them automatically.
  • You want cached, no-SOQL-cost reads.

Use Custom Settings when:

  • You need to write at runtime from Apex (counters, timestamps, audit markers).
  • You need per-user or per-profile values (Hierarchy type handles this natively).
  • The values are genuinely runtime data that shouldn’t ship with code.

Use neither when:

  • The data is user-facing and needs list views, reports, or related lists → use a custom object.
  • The value is a single org-wide string → consider a Custom Label for translatability.

Hierarchy vs List custom settings

Custom Settings come in two flavours, and the question often combines them:

TypeGranularityAPI
ListOne value per record keyMyConfig__c.getValues('MyKey')
HierarchyOrg default + per-profile + per-user overrideMyConfig__c.getInstance(userId)

Hierarchy is the closest thing in Salesforce to “per-user feature flags” without writing logic yourself.

What interviewers are really looking for

The shorthand answer is “metadata vs data.” The full answer hits three points: deployment (records-as-metadata is the headline advantage), write semantics (DML vs Metadata API), and Hierarchy custom settings as the one use case CMDT cannot replicate. Mention that CMDT is the modern default for configuration that ships with code, and you’ve nailed the architect-level signal.

Verified against: Apex Developer Guide — Custom Metadata Types, Custom Settings. Last reviewed 2026-05-17 for Spring ‘26 release.