Salesforce upsert vs update comes down to one question: what should happen when the record is not there? An update finds each record by its Salesforce record ID and never creates one, so a missing record returns an error. An upsert matches each record on one field: no match creates a record, one match updates it, and several matches return an error and write nothing.
The matrix above shows what our connector writes to Salesforce, beside the other tools we connect. A cell that says a write is not built yet is about our connector, not the tool's own API.
Which one to use
The records came out of Salesforce. Keep the record ID column and update. A record deleted since the export errors instead of coming back.
The records come from a system with its own key. Create a custom field in Salesforce, mark it External ID and unique, fill it on the records you already have, then upsert on it.
A cleanup job. Update. When a job is meant to change records that exist, an error on a missing record tells you something; an upsert creates a duplicate that turns up weeks later in a report.
Pick the match field with care
An idLookup field is not necessarily unique. When two records share a value, the upsert for that value stops with an error, so a unique External ID field is the usual choice. If you only have names and email addresses, find and merge duplicates before the load.
Neither write merges records for you. An upsert writes the fields you send to the one record it found, and the fields you leave out keep their values.
The matching rule follows Trailhead's Apex DML module.
What to do next
Test a handful of records first and read each result: created, updated or an error. Every write also spends API calls, so check the REST API limits before a large load.
In Oneprofile, an export to Salesforce offers create, update, or create or update, matched on the field you pick. A test run asks Salesforce what a real run would do and writes nothing.
