Bypassing Salesforce Data Validation in Rules and APEX Triggers for Data Import & Migration
Salesforce offers several tools to ensure data consistency, such as validation rules and APEX triggers.
However, when migrating existing data to Salesforce, usually two conflicting requirements come up:
- Ensure that the data is valid — Business analysts and developers define rules and checks to maintain data quality moving forward.
- Import data quickly — This often involves importing data that may be incomplete or invalid according to the new validation rules.
While the ideal solution is to clean the data before import, this is rarely feasible due to several factors:
- Data cleanup may require considerable effort and time,
- Some data points may not be available in source data,
- It may be easier and more cost-effective to perform the data cleanup in Salesforce.
Moreover, data migration is often an iterative process, with migration rules and source data improving over time — sometimes extending beyond the go-live date.
As a result, there’s a need to bypass validation rules during data migration while at the same time, keeping them active for end users.
This post describes how to solve this problem.
Validation Rules
Validation rules are stored as part of an object’s metadata and can be individually enabled or disabled in the Object Manager:
While this is manageable for a small number of rules, manually handling multiple validation rules across various objects can become cumbersome.
Some tools, like sftoolkit.co, allow bulk modifications by adjusting object metadata. However, this still requires manual intervention, and deploying metadata can be a complex process.
A better solution is to designate a profile for which validation rules are always disabled and use the following logic:
$Profile.Name <> 'Data Migration Profile' && ( ... original validation logic ... )
For Data Migration Profile the first line always evaluates to false, and the following conditions are not evaluated — so the validation rule is effectively disabled for any user with the profile (rules are executed in the context of the user who triggered operation on an object).
The same can be achieved with a custom permission if multiple users with different profiles need to be migrating data:
!$Permission.Data_Migration /* <-- developer name of a permission */ && ( ... original validation logic ... )
Important One common challenge with validation rules is that organizations tend to overcomplicate them, creating overly strict rules that prove impractical in day-to-day operations. A more effective approach is to start with a minimum viable set of rules and gradually introduce additional ones as needed. |
Lookup Filters
The same logic can be applied to lookup filters, by adding an OR operation between the current lookup filter conditions and checking for data migration:
(Current filter conditions) OR (Data migration)
E.g.:
(Product: Active EQUALS True) OR (Current User Profile: Name EQUALS Data Migration Profile)
This change will not affect which items are selected on the layouts for regular users (i.e., without the migration profile).
APEX Triggers
While APEX triggers are not primarily designed for validation, they can be used for that purpose. Similar to validation rules, APEX triggers cannot be disabled globally and must be deactivated individually. Also, multiple triggers can be defined for a single object:
One option is to just disable triggers altogether — it is generally a good practice to have an option to disable triggers in a package, i.e., a well written package will have an option looking similar to this:
Disabling triggers, however, has potentially even more negative ramifications than disabling validation rules, as they usually perform more complex tasks than just validation.
The best way is to apply the same approach as with validation rules (APEX trigger is executed in the context of a calling user) and skip validation parts. This will be more complicated than validation rules because some logic may have to be executed regardless.
Again, just like with validation rules, this can be done with a profile (error checking omitted for clarity):
Id profileId = UserInfo.getProfileId(); Profile p = [SELECT Id, Name FROM Profile WHERE Id=:profileId]; If(p.Name <> 'Data Migration Profile'){ ... }
Or with a custom permission (error checking omitted for clarity):
String permissionName = 'Data Migration'; // permission name visible in the UI Boolean hasPermission = false; CustomPermission customPermission = [SELECT Id, DeveloperName FROM CustomPermission WHERE MasterLabel =: permissionName]; hasPermission = FatureManagement.checkPermission(customPermission.DeveloperName); // E.g. Data_Migration if( hasPermission == false ) { ... }
Whichever method is chosen it is a good practice to place the logic in a static helper method, e.g., DataHelper.InDataMigration(), to be able to make future changes in a single spot.
Important Disabling trigger processing for migrated data usually goes beyond just data validation — for example, it may be equally important do suppress email notifications (esp. to customers). |
Looking at Records
The examples above illustrate how to bypass validation and other processing logic based on user properties such as profile, login, or specific permissions.
In some cases, a complementary strategy of checking whether a particular record has been migrated or cleaned up can also be useful. For example, one may want to suppress email notifications sent when a particular record is created.
In this scenario, we recommend creating a formula field Is_Migrated to flag records that came from migration (typically they will just check external ids used as migration keys for being NOT NULL). This flag may have other uses such as distinguishing between migrated vs. Salesforce-originated records in list views, reports, etc.
Conclusions
Incorporating a method to bypass validation rules and triggers is a best practice for any Salesforce solution involving legacy data imports. This can be accomplished through various approaches, such as using profiles, custom permissions, designated users, or a combination of these methods, and it’s most effective when implemented early in the project.
Contact us today to find out how we can help you!