I have a lead owner assignment logic with many conditions. When user presses a button "Get lead" a lead in the org is searched and ordered by the field rank (Soql order by rank__c), and when the lead is fetched its owner is assigned to the user.

We had a situation when multiple users clicked the button at the same time and got the same lead - so in case user1 and user2 click their buttons the same time - user 1 was assigned to leadA, and right afterwards -user 2 was assigned to leadA as well. So user 1 saw a message that he got the lead but actually it was overridden. Since we cant use FOR UPDATE and Order by in the same soql,

we changed the logic to 2 soql. first one the original soql - select id from lead where... order by rank__c desc limit 10 then we had another query - select id from lead where...(all conditions from above) and id in: first list FOR UPDATE limit X. then we search by the 1st list the lead in 2nd list - to get the one with the highest rank

My question is - how much should I limit the 2nd query (and the 1st query)? What could happen if I have 11 users clicking the same button the same time?

Any help will be appreciated. Thank you!!

2 Answers 2


You don't need to put a LIMIT in 2nd query. Better in the first query add filter condition if leads are assigned to the different owner or Query.

And use that list into the FOR UPDATE clause.

Also, other than FOR UPDATE, you can use Approval.Lock(List<SObject> recordsToLock, Boolean allOrNothing) where entire list will be locked for editing.

After the lock is getting released by current user then only another user can update that record.

Refer my blog post Locking Salesforce records for concurrent users to view or to perform any other actions

  • Actually, I had a mistake - I'm not putting a limit in the 2nd query - only on the 1st. I am adding a filter to the 1st list and using that data in the second query, but my question is - how do I avoid locking all records from the 1st list (when the are being referenced in the 2nd query with FOR UPDATE) - as I only need one - or maybe two if the first one in the list is currently processed by a different user or maybe three... and that can go on and on...
    – daveDev
    Feb 10, 2019 at 10:36
  • suppose 3 users clicks the button the same time user1 got the lock 1st- for the whole records - even though I want to lock only one record user2 and user3 will get 'unable to lock row' even though they have records they can work on them that are not used by user1 but unfortunately are in the locked list.
    – daveDev
    Feb 10, 2019 at 10:36

Not 100% sure, but:

The FOR UPDATE won't cause the second (or third etc.) user to receive an error directly, but instead will cause the process threads for the second (or third etc.) to be blocked until the lock on the records is released (by the processing for the first user completing) or 10 seconds have passed - at which point a QueryException will be thrown for the second (and subsequent) threads.

As long as your second query in your processing does the FOR UPDATE and you include enough context in the WHERE clause to exclude objects that have already been allocated, it should all just work. Having some nice "Sorry, the system was too busy to service your request, please try again" type message presented when an QueryException is thrown, you can provide a good user experience even when there are just too many users trying to use this facility.

You must log in to answer this question.

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