My goal: to have a field on Account that is read-only for everyone (including System Administrator) but the field can still be edited by Apex code. For example, when an Opportunity is closed as won, an Apex trigger (on the Opportunity object) will find the associated Account and update the read-only field.

Ideally, I would like there to be an Account trigger that checks to see if the update was performed by a user or by Apex code. If it was performed by a user, an error is returned saying that the user is not allowed to edit the field. If it was performed by the Apex code, the update goes through.

Is there any easy way to do this?

2 Answers 2


By doing this, you are binding your hands for future changes to your processes, such as bulk data loads or restores from backup. If you are set, however, on making this field Apex-only, you can use static variables in your trigger handlers to gate the update. This will ensure that the only way to run the update is from Apex - no workflows, no Process Builder, no UI, no API, nothing.

public without sharing class AccountTriggerHandler {
    public static Boolean updatingFromApex = false;

    public static void beforeUpdate(List<Account> scope) {
        if (!updatingFromApex) {
            // Implement error flow here.

Then, in your Opportunity code,

Map<Id, Account> toUpdate = new Map<Id, Account>();
// ... populate the Map by processing Opportunities ...

AccountTriggerHandler.updatingFromApex = true;
update toUpdate.values();
AccountTriggerHandler.updatingFromApex = false;

I really don't like this pattern but it will do what you want. You're locking yourself into a world where any change that contravenes this expectation will have to have an Apex deployment in front of it, which can really impede your ability to respond to issues.

Note that it could be bypassed by Anonymous Apex execution. Ultimately, you can't fortify the system against a user who has full rights to that system.


If you are happy to do the update asynchronously, you can set up the code that wants to change it to fire a platform event. If you have an Apex trigger implementation that consumes the platform event, this will be run as the Automated Process user. This can do the setting of the field. Thus you can have a validation rule on Account that says only the Automated Process user can perform the modification of this changed field.

Of course, the Sys Admin could just disable the validation rule. If you want to make it more "robust" you could add the check into your Account trigger, and add an error to the field when the trigger is executed by a user other than Automated Process and this field has changed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .