The Flow That Fires Six Times
A record-triggered flow on Opportunity updates a custom Deal Score field, and a second after-save flow on Opportunity updates the parent Account's Open Pipeline field. A nightly ERP integration upserts 40,000 opportunities with a batch size of 200 and includes Deal Score in its payload. Since launch, the integration intermittently fails with UNABLE_TO_LOCK_ROW on Account, the Account pipeline field is roughly double the true value, and users report Deal Score reverting to an older value minutes after they save. The team also has an active duplicate rule on Opportunity (Alert action, fuzzy company-name matching rule) and three validation rules whose error conditions reference Deal Score.
1. Rank the causes of the three symptoms and state the fix for each.
Read the worked answer
1. UNABLE_TO_LOCK_ROW on Account. The after-save flow updates the parent Account, so a 200-record batch touching the same Account repeatedly attempts to lock the same parent row within one transaction. Fixes: recalculate the Account aggregate once per Account per transaction instead of per child; move the parent update to the asynchronous path (or a queueable/scheduled recalculation); and reduce batch size. Sorting the payload by Account reduces lock churn considerably.
2. Doubled pipeline. The update is non-idempotent. If the flow does Open_Pipeline__c = Open_Pipeline__c + Amount, then every re-fire-from a later update, from the flow's own DML chain, or from a load re-run-adds again. Replace increments with a full SUM recalculation, add ISCHANGED entry criteria so no-op saves don't fire, and consolidate so only one flow owns the Account field.
3. Deal Score reverting. Three suspects, in order: the ERP payload overwrites it on every upsert; a before-save flow overwrites what the after-save flow set later in the same transaction (Order of Execution); or a second flow writes the same field. Fix by making the field automation-owned-read-only via field-level security, removed from all layouts, stripped from the integration payload-and by keeping exactly one flow per object per timing.
Rule of thumb: before-save flows for same-record field updates, after-save only for cross-object effects.
2. How do you prepare the duplicate rule and validation rules for a 40,000-record ERP load?
Read the worked answer
Duplicate rule
- The Alert action does not block API writes. The load will create duplicates silently and raise 40,000 alerts nobody ever sees. Alert is safe only if the matching is trustworthy.
- Block is worse for this load: with allOrNone false you get partial success and a large error log that takes hours to triage.
- The real fix is scoping. Duplicate rules can be assigned per profile, so give the integration user an exact-match rule on the ERP external ID and keep the fuzzy company-name Alert rule assigned to internal profiles only. Fuzzy matching on company name at 40k volume produces both false positives ("Acme" vs "Acme Inc") and false negatives, and it is slow.
Validation rules
- Three of them reference Deal Score. If Deal Score is populated by flow on insert, validation can fail the record before the flow ever supplies a value.
- Either relax the error condition so Deal Score is not required at insert time, or bypass deliberately for the integration user with a custom permission checked inside the error condition. Never bypass by deactivating the rule globally mid-load; you will forget to turn it back on.
Sequencing: dry run 200 records in a sandbox at production batch size, confirm counts and duplicate behavior, then narrow the aggregate flow's entry criteria so a 40k load does not fan out 40k parent updates.