I have a client who wants us to build a custom auto-number function that applies only to a certain type of campaign record. They want to append the number to a text field for that specific campaign type, but because they will have many campaigns for other purposes, they don't want a very long number that would result from using the standard auto-number.

I'm thinking to store the counter as a Custom Setting (not custom metadata) and use Apex to append to the campaign and increment the counter as needed.

However, I'm concerned about concurrent inserts from multiple users. What happens if User A inserts 400 campaigns with data loader (Batch API), while User B manually creates a campaign at the same time? Does B's transaction begin while A is still running? And if so, can A's transaction finish before B?

The obvious problems here would be 1) A & B would start from the same counter value, and 2) B would update an incorrect value into the custom setting if it finished after A.

I've searched around but can find any info on multiple user concurrency. Does anyone know how it works, or can you point me to documentation?

  • 2
    Possible option: auto-number + a formula field to format/cut down the auto-generated value. Then use the formula-derived field for stuff.
    – identigral
    Jul 22, 2021 at 18:01

1 Answer 1


IMHO use of a custom settings is a bad idea; these are intended (like custom metadata type records) to be quite static. Continually updating the value is detrimental to performance.

SOQL includes FOR UPDATE for normal SObject records to ensure locking is applied; this stalls all transactions don't have the lock until the lock is released (which happens when the locking transaction completes). However, all transactions that are blocked for 10 seconds or more receive a QueryException. Remember too that Salesforce only allows a small number of long-running transactions. This implies that it would be a bad thing to try to do this synchronously, on insert of your campaign records, since you can get the situation where one or more concurrent creation is effectively forced to abort due to exceeding limits.

If you can have this auto-number allocated soon after the record is created (rather than immediate) you could effectively have a single, scheduled/background job that deals with providing these values. There are lots of different ways to implement such an arrangement, though you need to consider the burden on async executions and just how long a delay you can have before populating the value.

An alternative is to take the approach suggested by @identigral in the comment against your question: use a regular auto-number and a formula that derives a value from the auto-number; perhaps from the creation date/time and the last 5 digits of the auto-number, for example.

  • Thanks for the insights. I hoped to do this in a before-insert trigger, so FOR UPDATE wouldn't apply. Guess I'll have to do it asynchronously with an auto-number as identigral suggested. Jul 22, 2021 at 21:27

You must log in to answer this question.

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