I'm developing an integration that makes an HTTP call to an external system from SFDC. The entry point for this code is an opportunity trigger. After a user updates the opportunity, my trigger fires, and calls a future method to make the HTTP request. This works just fine.

However, I ran into a situation where there's code that runs on the quote object and programmatically updates opportunities via a future method. This in turn fires my code, which errors with:

execution of AfterUpdate caused by: System.AsyncException: Future method cannot be called from a future or batch method

I tried to account for this by using system.isBatch() || system.isFuture and if this evaluates to true, call a non-future version of my function that makes the HTTP callout. When I tried this, though, I got:

System.CalloutException: Callout from triggers are currently not supported.

What's the proper way to architect this so that my callout is allowed regardless of whether the opportunity is updated normally, from a future method, or from a batch?


1 Answer 1


If you need your future code to callout You will have to adjust your code that fires on the Quote that is updating the Opportunity records. Otherwise just skip your future code if being called by a future method.

Another option, if you cannot modify the offending trigger would be to have your code mark opportunities for later processing (If a future context) and have a batch (running hourly) pick them up and process. (Good if the other code is a managed package). Keeping in mind that if they are processed either by another trigger or the batch to unmark them for processing...

  • Thanks for the response. Unfortunately, the code that fires on the Quote object isn't mine and I can't touch it. I understand that the hourly batch is an alternative design, but this delays the synchronization considerably. If our requirement calls for real-time synchronization vs. hourly batch, is there a way to architect this so we don't lose the real-time callback?
    – nurath
    Commented Jul 27, 2015 at 15:12
  • @tarun - not really. You could try to hack up some code to use system.scheduleBatch for the next minute, but then you need to write code to ensure that it does not get called to many times yet still processes all the records
    – Eric
    Commented Jul 27, 2015 at 15:16
  • Thank you. Just to be clear, when you say "mark" a record, this would involve creating a custom field on the opportunity and setting its value in the trigger, then unsetting in the batch, right?
    – nurath
    Commented Jul 27, 2015 at 15:28
  • Thats one way yes, or you could get fancy and create a queue object to store ids (nice if you do not want to affect timestamps on the opportunity)
    – Eric
    Commented Jul 27, 2015 at 15:30

You must log in to answer this question.

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