I have use case which i'm trying to wrap my head around for best approach. I have a vfp showing list of records where user can add/edit/remove records and do a final SAVE (which includes a dml->upsert followed by dml->delete(if there are any). I also have a trigger on after insert, after update, after delete where when a user edits a record & updates/deletes these records then the trigger handler is called to aggregate currency field on all the related records & create a opportunitylineitem with that aggregated value.

So here's what I'm having trouble with - user removes and updates records on the vfp followed by SAVE which will - then controller will perform an upsert dml followed by delete dml - then as per the order of exec 1st the after insert trigger is fired -> which in our case will bypass as there are no new records inserted - 2nd enters after update - > here it aggregates all the records (including the deleted record as here afterupdate is still in "upsert" state & doesn't know there is a delete operation performed on the record. -> finally it enters after delete where it aggregates all the records (which will now have appropriate aggregation by eliminating deleted record). This part is where I'm struggling with on how to over come this issue where if there is an update + delete then do not execute this method in udpate block & instead execute only delete block. Appreciate all you inputs here. Here's the thread to my code & vfp. Thanks! Method used in After Insert, After Update and After Delete must fire only when once even though there are multiple DML(Add,update,delete)

  • Just for clarity, is the behaviour in the trigger also used outside of the user interacting with this Visualforce page? Dec 18, 2022 at 22:13
  • @CallumMacErlich I mean, at any given point a user can perform only ONE action(either delete, update, create) outside of vfp. So the trigger won't have trouble processing individual dml ops. However, in the case of vfp, a user performs upsert(insert/update+delete) then bulk records enter the trigger where records inserted will go to insert block( where updated record data is not available at this point) & then create opplineitem aggregate, -> update goes to update block (here the inserted records are available to query along with latest value of updated records) similarly for delete block
    – SMorse
    Dec 18, 2022 at 23:14
  • I was asking to confirm if users could actually perform those actions on these records outside of your VF Page, but that does answer that thanks. I've got an idea which I'll share shortly. Dec 18, 2022 at 23:46

1 Answer 1


We can delay the logic being called in the same way that we'd deal with recursion in a trigger, by using a static variable that your trigger then checks to skip the After Update logic in the case of there also being After Delete actions to undertake.

To do this, you can implement a new Class that contains a static variable, along the lines of the below:

public with sharing class TriggerBypass {
    public static Boolean bypassUpdateTriggerAction = false;


In your Visualforce page, when you determine that deletes are required, you can set this bypass variable to true before doing the upsert and skip your AfterUpdate logic if it has been set to true.

This approach can be extended to have each of your trigger contexts as well.

As mentioned, this is similar to the approach for preventing trigger recursion that is available here: https://help.salesforce.com/s/articleView?id=000386331&type=1

  • ok that makes sense. something like this if(TriggerBypass.bypassUpdateTriggerAction){. execute method }. How about if user tries to update the record from standard edit page? In that case how to set this boolean to true so that it will execute?
    – SMorse
    Dec 19, 2022 at 1:27
  • @SMorse the bypass will only be set to true within the context of the transaction that sets it to true. So apart from where you're explicitly setting it to true within the same transaction, it will be false and the logic won't be bypassed. Dec 19, 2022 at 1:31
  • thanks for the help. I was hoping not to create any additional class just for this specific use case alone & was hesitant to take this route but looks like there is not other way to do this so I went ahead & created the class to handle this. :) Appreciate your help!
    – SMorse
    Dec 19, 2022 at 4:57

You must log in to answer this question.

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