Clay logo, go to homepage
Clay GTM guide

How to Mass-Update Salesforce Records

A mass update is a bulk write to your system of record, and a bulk write goes wrong in bulk. Here is how to update thousands of records at once without creating duplicates or wiping data a rep already trusts.

May 21, 20269 min read

Updating a thousand Salesforce records is the easy part. Not creating a thousand duplicates, and not overwriting data a rep already trusts, is the hard part.

A mass update is a bulk write to your system of record, and a bulk write goes wrong in bulk. Pick the wrong action and you spawn a second copy of every record. Push blank cells over good values and you wipe fields nobody asked you to touch. Skip the test and you find out in production, where a Salesforce write cannot be undone. The teams that do this safely treat it like a release: stage the new values, choose the write action deliberately, protect the fields they do not own, and test against a sandbox first. This is how to run a mass update in Salesforce without the cleanup afterward.

What you need before you start:

  • A Clay account connected to Salesforce: Ideally with a sandbox alongside production.
  • Admin or RevOps permission: Enough access to update the objects and fields in scope.
  • A clear list of which fields you are changing and why: The safest mass update is the narrowest one that still does the job.

Step 1: Pull the exact records you want to update into Clay

Update a defined set, never everything.

Clay's native Salesforce integration imports objects directly, so you start from a filtered set rather than the whole org. Build a Salesforce view, report, or a Salesforce SOQL query for precisely the records in scope (accounts in an open deal, contacts with a missing region, leads created before a certain date) and import that into a Clay table. The single most important field to carry over is the Salesforce Record ID on every row. It is the key that makes the write land on the exact record later, with no guessing about which Acme or which Jordan Lee you mean.

If you import from a Salesforce report, note that reports have no unique row identifier, so select the fields that uniquely identify each row when you bring it in. Pulling by object or SOQL carries the Record ID natively, which is why those are the cleaner inputs for a write-back.

Step 2: Prepare the new values before you touch Salesforce

The update is only as good as the values you write.

Build the corrected values as columns in the Clay table next to each record: normalize inconsistent fields with the formatters (Normalize Company Name, Normalize Phone Number, Format Date/Time, Remove Extra Whitespace), fill gaps with enrichment, and validate anything that has to be deliverable. Keep the original Salesforce value in its own column beside the new one so you can eyeball the diff before anything writes. A mass update is a good moment to fix format drift, not just fill blanks: standardizing USA, U.S., and United States into one value across 5,000 records is exactly the kind of thing that is painful by hand and trivial in a table.

Update the fields that change a decision or a workflow. Leave the rest. Every field you write is a field you can get wrong at scale.

Step 3: Choose the right write action, because that is what prevents duplicates

This is the step people get wrong, and it is the difference between an update and a mess.

Because you imported records carrying their Salesforce Record ID, the correct action is Update record, which keys on that Record ID and writes to the exact existing record. It does not create anything, so there is nothing to duplicate. Two related actions exist for the other cases, and using them by mistake is how duplicates appear: Upsert creates-or-updates in one step but requires an external ID on the object, so reach for it only when you are matching on your own identifier instead of the Salesforce Record ID; Create record is for net-new rows only, and Clay configures it to prevent duplicates by default.

Auto-cycles the three write actions. Click a card to hold it and read how it lands, click it again to resume.

1,000 records imported with their Salesforce Record ID

Update record

Use when you are updating records you imported

0 duplicates

Writes to the existing record. Nothing is created, so there is nothing to duplicate.

Auto-cycling · click a card to hold

You imported the Record ID, so Update record is the one to use: it lands on the exact existing record with zero duplicates. Create and Upsert solve different problems and cause duplicates when used by mistake.

Step 4: Turn on Ignore blank values and fence off the fields you do not own

A mass update should write less than you think.

Enable Ignore blank values on the Update action so an empty cell in your staged data never overwrites a populated field in Salesforce. Without it, a record you could not enrich writes a blank over a value a rep entered by hand, and you have made the CRM worse at scale. Then exclude the fields you do not own from the mapping entirely: deal notes, custom scores, manually corrected titles, relationship context. Map only the columns you actually intend to change.

Auto-maps the fields. Flip Ignore blank values off to see a blank cell wipe a good value, and on to prevent it.

Batch of 1,000 records
IndustryIndustryUpdate if changed
Employee countNumberOfEmployeesUpdate if changed
RegionRegion__cUpdate if changed
Phone(1 blank cell)Phoneblank skipped, value kept
Account Owner NotesProtected · excluded from write

Fields written: 3 · Blanks skipped: 1 · Protected: 1

Ignore blank values plus a protected-field exclusion turns a risky bulk write into a safe one: empty cells never wipe good data, and rep-owned fields are never touched.

Step 5: Test the whole write against a sandbox before production

A Salesforce write from Clay cannot be undone, so the first real run should not be in production.

Connect your sandbox as a Salesforce Test Env under Settings, point the same mapping at it, and run the update against throwaway data first. Confirm the right fields changed on the right records, that protected fields stayed put, and that no duplicates appeared. Treat the production run as a release that follows a passing test, not as the test itself. Before you flip it live, preview the scope: how the batch splits into records that will change, records already correct, and records held back.

Auto-runs the preview in the sandbox. Click a bin to inspect it, and toggle Test Env vs Production to see why you test first.

Previewing 1,000 records

Sandbox — safe to re-run against throwaway data

Duplicates created0

Previewing the write in the Salesforce Test Env shows exactly how the batch splits into changed, unchanged, and held records, and that zero duplicates are created, all before a single irreversible production write.

Step 6: Run it, then put recurring updates on a schedule

A one-time mass update is a snapshot. The fields you just fixed start drifting again the next day.

Run the update from the Clay table once the sandbox test passes. Then, for fields that decay (title, employer, phone, headcount), schedule the same workflow to re-run on a cadence instead of repeating the project by hand each quarter. Watch the cost as you scale: every row spends Actions for the orchestration, and any provider results spend Data Credits, so scope each scheduled run to the records that actually need refreshing rather than re-writing the whole object every time.

Clay has become the orchestration layer for everything GTM. Salesforce for record-keeping, Snowflake for product data, and Clay for turning it all into automated action.

Auto-plays the recurring update loop. Click a node to inspect it.

1/5Records due for refresh
1

Records due for refresh

Filter a Salesforce view on a Last Updated date older than your window

Hands to Import to Clay: Records past the window queue themselves

Putting the mass update on a self-maintaining schedule keeps decaying fields current without rewriting the whole object, and scoping the refresh window controls the credit cost.

When the loop runs, the records reps open stay current instead of sliding back to stale, and the coverage you fixed holds.

88%

share of its data gap Hex filled with Clay's enrichment, versus its previous single vendor

Read the full story

Common failure modes, and how to avoid them

Most mass updates fail the same few ways. Watch for these.

  • Using Create instead of Update: A Create action run across records that already exist spawns a duplicate for every row. For records you imported, use Update record keyed on the Salesforce Record ID; reach for Upsert only when you key on an external ID.
  • Writing blanks over good data: A record you could not enrich pushes an empty cell over a populated field. Turn on Ignore blank values so empty cells are skipped, never written.
  • Overwriting fields a rep owns: A bulk write that touches deal notes, manual scores, or corrected titles destroys trust fast. Map only the fields you intend to change and exclude the rest.
  • Testing in production: A Salesforce write cannot be undone, so a mistake at scale is permanent. Run the full mapping against the Salesforce Test Env first, then promote to production.
  • Treating it as one-and-done: The fields you fixed decay again at roughly 3 to 5 percent a month. Schedule the update to re-run on the decaying fields instead of repeating the cleanup by hand.

Mass-update Salesforce without the cleanup

Prepare the values, pick the right write action, protect what reps own, and update thousands of records safely.

Frequently asked questions

How do I update thousands of Salesforce records at once without creating duplicates?

Import the records into a Clay table carrying their Salesforce Record ID, stage the new values as columns, and write them back with the Update record action keyed on that Record ID. Because Update writes to the exact existing record, re-running it refreshes data instead of duplicating it. Use Create only for net-new rows (Clay prevents duplicates there by default) and Upsert only when you match on an external ID.

What is the difference between Update, Upsert, and Create in Clay's Salesforce integration?

Update record modifies an existing record and keys on the Salesforce Record ID. Upsert creates-or-updates in one step but requires an external ID on the object. Create record makes a new record and is configured to prevent duplicates by default. For a mass update of records you already imported, Update record is the right choice because you hold the Record ID.

How do I stop a mass update from overwriting good Salesforce data?

Enable Ignore blank values so an empty cell never overwrites a populated field, and exclude manually maintained fields (deal notes, custom scores, corrected titles) from the field mapping entirely. Keep the original value in a column next to the new one so you can review the diff before writing.

Can I undo a mass update in Salesforce?

No. Once Clay updates or creates a record in Salesforce, the action cannot be undone. That is why you connect your sandbox as a Salesforce Test Env and run the full mapping there first, confirm the right fields changed on the right records, and only then run it against production.

How do I keep Salesforce records updated automatically after the first run?

Add a Last Updated field and build a dynamic Salesforce view filtered to records older than your chosen window. Clay imports that view on a schedule, re-runs the same update workflow, writes the values back, and stamps the date so each record leaves the queue until its next cycle. Scope the window to control credit cost.