Salesforce Trigger: When to use Before versus After

When creating a trigger in Salesforce, you need to decide whether you want actions to occur before or after, as in before insert, before update, before delete versus after insert, after update, after delete.

The Apex documentation actually has a great article on this called Apex Trigger: Context Variable Considerations.

For instance, if you’re getting an error message

System.FinalException: Record is read-only

It may be due to a code segment like this:

trigger Test_Trigger on Object__c (after update) {
  for (Object__c object : Trigger.New) {
    object.Field__c = 'New Value';

This is because, specifically in an after update, when attempting to change fields using Trigger.New, this is “[n]ot allowed. A runtime error is thrown, as is already saved.”

This entry was tagged , , , . Bookmark the permalink.

14 Responses to Salesforce Trigger: When to use Before versus After

  1. Chandra says:

    Can someone one send me a sample Apex trigger?

    I tried all the operations and keep getting error when triggered. Some of the errors are below:

    System.SObjectException: DML statment cannot operate on or trigger.old: Trigger.myTrigger:

    System.FinalException: Record is read-only: Trigger.myTrigger:

  2. Ray Dehler says:

    Yes, if you’re updating an object from an ‘after update’, you have to explicitly create a new instance of that object and run an explicit update call. Maybe it would be most helpful if you showed the code that caused that issue?

  3. Mayank Joshi says:

    Just a sample,if someone need this .If you will use this trigger with ‘After Update’ event .It will throw System.FinalException: Record is read-only ,just to resolve it .It is required to use ‘before Update’ event as mentioned by Ray already .

    More info is in the Salesforce Docs:

    Although Great Work ,I was reading your Article . This Trigger can change the current User to Current OwnerId of Opportunity While Editing .I did a bit Hard Coding (e.g by passing ID Directly )

    trigger TestLookUpField on Opportunity (before update) {
    //Iterate and Passed to OwnerId for changing current Owner Value .
    for (Opportunity opp : {
    system.debug(‘May Day May Day May Day ;)’+opp);

    Thanks .
    Mayank Joshi

  4. Carlo says:

    I discovered a problem yesterday which has now made me realise that several of my triggers were actually doing nothing.

    I was using some after delete triggers to remove child objects which are not master detail related [because I have already hit the 6 limit].

    trigger name {after delete}
    list delList = new list([select Id from object where parent in :trigger.old])
    delete delList

    Yes thats right it did nothing.

    Yes my test code didn’t really test it or I would have known this.

  5. Siim says:

    So to remove child objects which are not master detail related we should use before delete triggers? Should we consider order of execution or any other factors when deciding when to use before or after triggers?

  6. Sunil says:

    Hi i am sunil I don’t have much knowledge on coding could anybody please help by mailing your contact number to my mail help me.

  7. Sunil says:

    currently i am in Bangalore.My contact no:09620599954 could anybody please help me.

  8. Vishal says:

    Its a bit off the topic question, But still I want to ask since it has taken my head away now: I have written a trigger after update, after insert on Account object. This trigger works perfect when there is no error while uploading records with data-loader. But, the trigger skips the whole batch of records if there is any error in atleast one of the record in batch which failed the insert/update of that record. Can you please help me on this?

    • Ray Dehler says:


      You have two options. Either you make the trigger act before insert, before update (meaning no implicit update has to occur to change the values as you requested), or you have to call Database.update(records, false); instead of update records;

      The optional opt_allOrNoneparameter specifies whether the operation allows partial success. If you specify false for this parameter and a record fails, the remainder of the DML operation can still succeed. This method returns a result object that can be used to verify which records succeeded, which failed, and why.

  9. venu says:

    please provide the trigger events i.e after delete and before delete with an example

  10. vikram says:

    i want to subscribe for this updates..plz help me

  11. Gomathi says:

    Very good article about trigger in salesforce like when it use before or after like that.

    thanks to post

Comments are closed.