What is the best way to get the Record Type ID in Apex?
When developing in Salesforce, especially for managed packages or production-grade Force.com applications, one common question arises: What is the best approach to retrieve a Record Type ID in Apex? There are a few ways to get the Record Type ID of a specific record type, but choosing the right one depends on performance, reliability, and scalability. Let’s explore these approaches and understand which method is most suitable and why.
The first method is to use a SOQL query. For example, you can write the following code to get the Record Type ID for the Business
record type on the Account
object:
RecordType recType = [SELECT Id FROM RecordType WHERE SobjectType = 'Account' AND DeveloperName = 'Business'];
This approach works efficiently because it uses the DeveloperName
field instead of the Name
. The DeveloperName
remains constant even if the administrator changes the record type label or display name. Therefore, this query continues to work even when the record type name changes. However, it consumes one SOQL query, which counts toward governor limits. If you need to retrieve record types frequently in your logic, this can become less efficient.
The second approach is to use the Describe
method available through the Schema class. This method allows you to fetch record type information without performing a SOQL query. For example:
Schema.DescribeSObjectResult d = Account.SObjectType.getDescribe();
Map<String, Schema.RecordTypeInfo> rtMapByName = d.getRecordTypeInfosByName();
Schema.RecordTypeInfo rtByName = rtMapByName.get('Business');
Id recordTypeId = rtByName.getRecordTypeId();
This method uses metadata describe calls, which do not consume SOQL limits but instead count toward the describe call limits. The advantage here is that the data is retrieved from metadata rather than the database, making it a good choice when you need performance without affecting query limits. However, it may return record types unavailable to the current user, which can cause permission-related issues if you try to assign such record types during record creation.
Now, while both methods can work in general development, they may not be ideal when building an industrial-strength or managed package-level Force.com application. The key reason is that record type Id
values differ across orgs, and the Name
field can vary depending on the org’s language settings or admin modifications. Therefore, relying on either of these fields directly is risky. The safest approach is to reference record types using their DeveloperName
, which is unique, stable, and consistent across environments.
In addition, there are two essential aspects to consider when working with record types: whether the record type is active in the organization (IsActive
field) and whether it is available to the running user (isAvailable
property). The IsActive
field is accessible from the RecordType
object, while the isAvailable
property is obtained through the RecordTypeInfo
class using the Schema methods. Combining these two ensures that you only use record types that are both active and available to the user executing the code.
Here is a robust and reusable utility method that demonstrates the best approach. It retrieves all active and available record type IDs for a given object and caches them by DeveloperName
:
private static Map<Schema.SObjectType, Map<String, Id>> rtypesCache = new Map<Schema.SObjectType, Map<String, Id>>();
private static List<SObject> results = new List<SObject>();
private static Map<String, Id> getRecordTypeMapForObjectGeneric(Schema.SObjectType token) {
Map<String, Id> mapRecordTypes = rtypesCache.get(token);
if (mapRecordTypes == null) {
mapRecordTypes = new Map<String, Id>();
rtypesCache.put(token, mapRecordTypes);
} else {
return mapRecordTypes;
}
Schema.DescribeSObjectResult obj = token.getDescribe();
if (results == null || results.isEmpty()) {
String soql = 'SELECT Id, Name, DeveloperName, SObjectType FROM RecordType WHERE IsActive = TRUE';
try {
results = Database.query(soql);
} catch (Exception ex) {
results = new List<SObject>();
}
}
Map<Id, Schema.RecordTypeInfo> recordTypeInfos = obj.getRecordTypeInfosById();
for (SObject rt : results) {
if (recordTypeInfos.get(rt.Id) != null && recordTypeInfos.get(rt.Id).isAvailable()) {
mapRecordTypes.put(String.valueOf(rt.get('DeveloperName')), rt.Id);
}
}
return mapRecordTypes;
}
This method first checks if the cache already contains record type information for the object. If not, it queries all active record types from the RecordType
object and filters them to include only those that are available to the current user. The result is stored in a map keyed by DeveloperName
, which makes it stable across different organizations. This caching approach also improves performance since describe results and record type queries are reused rather than repeated.
Here’s how you can use this utility method inside a trigger or Apex logic:
Map<String, Id> accountTypes = getRecordTypeMapForObjectGeneric(Account.SObjectType);
for (Account a : Trigger.new) {
if (a.NumberOfEmployees > 10000 && accountTypes.containsKey('Really_Stinking_Big_Account')) {
a.RecordTypeId = accountTypes.get('Really_Stinking_Big_Account');
} else if (accountTypes.containsKey('Small_Peanuts_Account')) {
a.RecordTypeId = accountTypes.get('Small_Peanuts_Account');
}
}
This example dynamically checks for available record types and assigns them only if the record type is both active and accessible to the running user. The advantage of this design is that it works in any org, regardless of how record types are translated or customized. It also ensures compatibility with Salesforce editions like Professional or Group Edition that may not support record types directly.
In conclusion, while both the SOQL and Describe approaches are valid, the best and most scalable method is to query record types by their DeveloperName
, cache the results, and verify both IsActive
and isAvailable
attributes. This ensures that your code is secure, efficient, and compatible across multiple orgs, user profiles, and languages.
Enroll for Career-Building Salesforce Training with 100% Money Back Guarantee
Our Salesforce Course is thoughtfully designed to give you a comprehensive understanding of the Salesforce platform, equipping you with essential skills to excel in the CRM industry. The program covers key modules such as Salesforce Admin, Developer, and AI, blending theoretical knowledge with hands-on practice. Through real-world projects and practical exercises, you’ll gain the expertise needed to solve complex business challenges using Salesforce solutions. Our expert instructors ensure you develop both technical proficiency and industry insights to thrive in the Salesforce ecosystem.
Beyond technical skills, our Salesforce Training in Florida provides personalized mentorship, certification support, and interview coaching to boost your career prospects. You’ll have access to in-depth study materials, real-time project experience, and ongoing guidance throughout your learning journey. By the end of the course, you’ll be well-equipped for certification exams and possess the practical problem-solving skills that employers highly value. Start your Salesforce journey with us today and open the door to exciting career opportunities. Sign up for a Free Demo now!