Like most multi-user systems, Salesforce does not block users from viewing a record via the UI while an update is in progress. This can cause an issue where two users are updating the same record at the same time. I don’t mean “Click Save” at the same time, I am referring to an “update interval”, something like the following sequence of events:
- User 1 opens a Contact record
- User 2 opens the same Contact record
- Users 1 and 2 are looking at the exact same data
- User 1 edits the phone number and clicks save
- User 2 is now looking at old data, (i.e. a phone number that is inconsistent with what’s stored in the DB)
- User 2 edits the email address and click save.
Salesforce will reject the second update and display a message like so:
So how exactly does this work? When we click the Edit button while looking at a record, Salesforce documents the record’s “Last Modify Date” at the time of the click. When we click Save, Salesforce checks the date again. If it matches, Salesforce knows no changes occurred since we grabbed the record and allows the save to go through. If it differs, Salesforce knows someone else changed the record while we were editing it and displays an error. (This pattern is generally referred to as optimistic locking.)
This is a great solution when we have a user sitting in front of a computer screen who can see the error message and deal with it, but what about when two systems are trying to do a similar process? This is the classic case of an “update conflict”.
Clients often ask for a bidirectional data synchronization (integration) between two systems (and in my line of work one of those systems is always Salesforce). Every time, without fail, my immediate reaction is “Are You sure you want to do that? What about update conflicts?” to which I get a blank stare, or a “What are the odds of that happening?”. The problem is they aren’t thinking in terms of batch job run times or whole records.
Consider the following: We have a bidirectional data synchronization between and ERP and Salesforce, it runs every 15 min, first it pushes data from Salesforce to the ERP, then from the ERP to Salesforce.
- The ERP User updates a phone number (in the ERP)
- A Salesforce user updates the Website address of the corresponding account in Salesforce
- The Salesforce to ERP Sync Job runs pushing the Salesforce record to the ERP – The entire record is pushed, phone number included (because we don’t really know what field changed, we only have the record last modify date)
- The ERP to Salesforce job runs next, but the new phone number has already been overwritten.
So, in this case we are unknowingly making a rule that if data is updated in both systems in the same 15-minute interval, we will simply throw away the ERP update, even if there is no conflict at the field level.
Now, yes, we can write code to track field level changes (in both systems), and we can move to a more real time sync process, but the -more we try to put together a solution, the more we see the need for increased code complexity and a manual “update conflict log review” process, there’s just no getting around it.
So, what is my recommendation? – Conflict avoidance. Simply put, seriously question whether a bidirectional data synchronization is really needed, and if possible, go with a Two-way unidirectional sync instead.
Bidirectional Data Synchronization: Avoiding Conflicts
Generally, there are three basic types of synchronization:
- Two-way unidirectional
Unidirectional syncs are one-way synchronization during which data flows from a source system to a target system. The source system is referred to as the master system because it “owns” the data. The goal is to bring the target system up to date with the latest data from the source system. In general, you don’t allow updates to the target system on any field owned by the master system. I say “in general” because there are instances in which there is a requirement to allow users to override the data in the target system, not push back that data to the source, and not have it overwritten by the source data the next time the synchronization job runs.
Bidirectional synchronizations are used when you need to keep data in sync between two systems and allow for users to update the same piece of data in both systems. For example, let’s say we want to allow users to update a company’s shipping address in the ERP system and in Salesforce, and we want the update to be reflected in the other system regardless of in which system the update was made. In this case, both systems are considered to be the source and the target. Again, I recommend that bidirectional syncs be avoided whenever possible because of the complexities of dealing with update conflicts. You may think that a general rule of “the last system updated wins” will work, but it’s usually not that simple (as shown above). We need to come up with some set of rules on how to manage the data when it’s updated in both systems simultaneously (i.e. during the update interval).
In lieu of a bidirectional sync, I recommend you make two new fields (or sets of fields) in Salesforce. Going back to our example, we would create two sets of fields: one for the ERP shipping address and one for the Salesforce shipping address, and then either have a trigger (or a workflow) that has rules to populate the native Salesforce shipping address fields or a formula that calculates it based on some set of conflict resolution rules. This practice essentially turns your bidirectional sync into a two-way unidirectional sync, eliminating the risk of data loss. (Because we always have both the ERP address and the Salesforce address – so a user can deal with the issue if needed. Yes, there is a conflict but there is no data loss).
Two-way Unidirectional Synchronization
A two-way unidirectional sync is when you sync the same object in both directions, but each system syncs only some fields or records where there is no overlap. This lack of overlap means there can’t be any data conflicts, so you can just sync system A to system B, then system B to system A with no risk of data loss. It really is just two unidirectional syncs. It’s important to understand that this is fundamentally different than a bidirectional sync. With bidirectional syncs, you must deal with data conflicts; with two-way unidirectional syncs, you don’t. The terminology is often confused. People say “bidirectional” when they mean “two-way unidirectional.” What’s important is always to ask for clarification. Ask specifically if there is the potential for data conflicts and, if so, be sure to put in rules to handle them.
Here are the two most common two-way unidirectional use cases (That I have seen):
- Prospect conversion is the first case. From the time a lead is created, up until a person (or company) places an order, Salesforce owns the Prospect record. After an order is placed, the prospect is converted into a customer and the ERP (or order processing system) takes ownership of the record. This is clearly a two-way unidirectional sync, because we have a clear line of which system owns which records at any given time, and there is never joint ownership of any record.
- In the second case, Salesforce owns some key information about an object, but data from some other system needs to be surfaced in Salesforce, so a designated set of fields is updated on a regular basis from that other system. For example, the ERP system owns and pushes updates for billing addresses (which is made read-only in Salesforce), but mailing addresses are owned and maintained in Salesforce and get pushed to the ERP (where they are read-only). Again, a clear line is drawn to which system owns which fields, and there is never any joint ownership of any field.
Generally, when people ask for a “bidirectional” integration, a “two-way unidirectional” integration will probably meet the business needs. True Bi-directional syncs are difficult to get right and usually require some level of manual user intervention to deal with conflicts. So, I find its best two avoid Bi-directional syncs where possible, and we have discussed a few techniques to do that.
Once we remove the need for conflict resolution, data synchronization becomes a relatively straightforward build.
This article is adapted from my book “Developing Data Migrations and Integrations with Salesforce: Patterns and Best Practices” (Apress December 2018)