Although I understand that if we seperate out the transaction this error gets fixed but my question is how is the work uncommitted and why can't Salesforce do a callout after some records are inserted or updated with DmL. Have gone through many references but I still din get the exact reason

  • 3
    Best guess is that it's to do with holding a consistent state in memory. Salesforce can't tell how long it will take for the callout to complete, so doesn't know how long it needs to hold that updated state in memory. That's at odds with the multi-tennented environment that it presents. Ideally it would give you an option to commit things, but alas... Apr 4 '20 at 8:51

If you make a DML operation, salesforce opens a thread to database or takes one from pool when available.

If the transaction is successful, data is committed and thread is closed.

If the transaction fails, the data is rolled back to previous state and thread is closed.

But when you do a callout, salesforce needs to keep a thread open till the transaction is complete. This is clearly a problem because in worst case scenario the thread has to remain open for 120 seconds (Max timeout of a callout).

Consider this in a multi tenant environment where millions of requests are executed. Keeping a thread open for long time will choke other operations on the database resulting is adverse performance issues.

That is why you aren't allowed to make a callout after DML.

In opposite case, DML after callout, the thread is opened when callout is done, so no issues there.

Another question would be why doesn't salesforce closes the thread after a DML is complete which is answered by Rob's comment.

  • I din quiet get that. So are you implying that the Dml operations run on a seperate thread? In that case the Transaction where the Dml is running is anyways seperate from the transaction running the call-out. Why would it be a problem? From what I understand as soon as the Dml operation happens the entire steps in the order of execution in apex is ran and at the end of these steps changes are committed to the database. So after this if I am doing a callout how is it uncommitted work? Apr 4 '20 at 9:28
  • The thread I mentioned is not a CPU thread. It means a connections to database. To make sure that DB state remains correct, SF needs to hold on to that connection.
    – manjit5190
    Apr 4 '20 at 9:44
  • Thanks for getting back. So as per all the above explanation: when I do a DML first, a connection is established with the database and once the Dml is successful the thread (connection) is closed. Now only after this I am doing the call-out right? Why is it still a problem? Why is it considered as an uncommitted work? I may be missing something here but I don't get it since the entire order of execution is complete and the data is committed at the end of order of execution for that Dml statement. Apr 4 '20 at 10:26
  • No, the thread is not closed when DML is successful because the transaction may error out in subsequent code. The thread is closed when transaction is closed which happens after every line of code that is loaded to memory finishes execution and that includes your callout.
    – manjit5190
    Apr 4 '20 at 10:43
  • 2
    @manjit5190 Stated differently, once you've performed some DML, the database has to hold locks on affected records. The lock time should be minimized to avoid concurrent edit errors. Being able to hold a record hostage for over two minutes is about the worst possible thing that can happen when you're trying to minimize those lock times.
    – sfdcfox
    Apr 4 '20 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.