SfSkills Domains Docs GitHub

Home / admin / record-type-id-management

record-type-id-management

RecordType ID differences across orgs: dynamic lookup via Schema.SObjectType methods, DeveloperName for stable refs, hard-coded ID anti-patterns, record-type caching, deployment impact. NOT for deciding whether to use record types at all — use admin/record-types-and-page-layouts. NOT for layout/profile explosion at scale — use admin/record-type-strategy-at-scale. NOT for hard-coded Profile, Queue or User IDs in Apex — use apex/apex-hardcoded-id-elimination.

Open the skill folder on GitHub


Record Type ID Management

Activate when code, flow, or configuration references record types by ID. Record type IDs are org-specific and change across sandbox refreshes, packaging, and org clones. Hard-coded IDs are one of the most common causes of "works in sandbox, fails in production" deployment failures on Salesforce.

Before Starting

Core Concepts

DeveloperName is the stable handle

Record types have three identifiers: Id (org-specific), Name (user-facing label), DeveloperName (API name). Only DeveloperName is stable across orgs. All code and config should reference by DeveloperName, resolving to Id at runtime.

Schema.SObjectType resolution

Apex: Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName().get('Business_Account').getRecordTypeId(). Returns the Id in the current org. Works everywhere — triggers, batch, LWC @AuraEnabled methods.

Flow

Flow formula or Get Records on RecordType with SobjectType and DeveloperName filters. Avoid referencing record-type Ids directly in flow; use the record type lookup component or DeveloperName-based query.

Validation rules and formulas

Formulas can reference $RecordType.DeveloperName (scoped to the context record). Compare to strings rather than IDs. RecordType.DeveloperName = 'Business_Account' survives deployment; RecordTypeId = "012..." does not.

LWC

LWC receives record-type Id via @wire(getObjectInfo) which returns recordTypeInfos keyed by Id with name and developerName attributes. Resolve DeveloperName → Id on the client once per session.

Common Patterns

Pattern: Central Apex utility for record-type resolution

public class RecordTypes {
    public static Id idFor(SObjectType type, String developerName) {
        return type.getDescribe().getRecordTypeInfosByDeveloperName()
                   .get(developerName).getRecordTypeId();
    }
}

Use as RecordTypes.idFor(Account.SObjectType, 'Business_Account'). Cached by the platform; cheap to call repeatedly.

Pattern: Custom Metadata Type as record-type registry

RecordTypeRef__mdt with Object__c, DeveloperName__c, and any semantic flags. Apex/Flow read the CMDT, then resolve to Id. Useful when the same logical "primary" record type differs across products.

Pattern: Validation rule via DeveloperName

AND($RecordType.DeveloperName = 'Business_Account', ISBLANK(Industry)). No ID in the formula. Deploys cleanly to every org.

Decision Guidance

Reference pointPreferred pattern
Apex logicSchema.getRecordTypeInfosByDeveloperName
Flow decisionDeveloperName via Get Records
Validation rule$RecordType.DeveloperName
Formula field$RecordType.DeveloperName
LWC@wire(getObjectInfo) → lookup by developerName
Assignment rule / Approval processRecord-type aware criteria on DeveloperName if possible
  1. Grep codebase for 012[A-Za-z0-9]{12,15} literals and audit every match.
  2. Catalog every record type per object with SELECT DeveloperName, SObjectType FROM RecordType.
  3. Replace each hard-coded Id with the DeveloperName resolution pattern matching its reference point.
  4. Introduce a central RecordTypes utility and migrate Apex references.
  5. Update validation rules and formulas to $RecordType.DeveloperName.
  6. Run a sandbox-refresh smoke test: deploy to a freshly refreshed sandbox and verify no test failures reference ID literals.
  7. Add a CI check that blocks commits containing 18-char record-type IDs.

Review Checklist

Salesforce-Specific Gotchas

  1. Master record type has DeveloperName Master — handle gracefully when looking up the master programmatically.
  2. Inactive record types are not excluded by getRecordTypeInfosByDeveloperName. Filter on isActive() if you care.
  3. Change Sets preserve DeveloperName but not Id. The destination org creates a new Id — code that hard-codes Id from the source fails on first run.

Output Artifacts

ArtifactDescription
Hard-coded ID auditList of files + line numbers with IDs
Central resolver utilityApex class with caching
CI checkRegex hook blocking new ID literals
DeveloperName catalogObject × DeveloperName × purpose

Package files