Case Study: When Process Builder Migration Almost Broke Production

This is one of those Salesforce stories
that starts innocently…
and ends with half the system refusing to work.

It’s also one of the best lessons about the difference
between Process Builder, Flow, and Apex execution context.

Background
The client had around 40 Process Builders running various parts of a Sales Cloud flow.

Everyone agreed this was too many.
Performance was suffering.
Debugging was impossible.
Governance was non-existent.

So the development team proposed refactoring everything into Apex classes.

A good idea — in theory.

The Migration


The team rewrote each automation as an Apex class with clean logic.

But there was one decision that changed everything:

They marked every class as:

public with sharing class …

In other words:

  • Apex executes with the permissions of the running user
  • NOT with full system access

Process Builder runs in system mode.
Apex (with sharing) does not.

But nobody asked the Product Owner
if business logic depended on system-level access.

It did.

UAT Was Skipped
Because this was “just refactoring,”
the team ran:

  • sanity checks
  • regression tests
  • a few end-to-end flows

Everything seemed fine.

So the changes went to production.

And then the system exploded.

The Failure
Suddenly:

  • automation stopped running
  • record updates failed
  • invoices didn’t generate
  • opportunity flows broke

Why?

Because users didn’t have the permissions
that Process Builder used to bypass.

The new Apex classes respected CRUD, FLS, and sharing —
and therefore refused to run many actions
that business users relied on.

Debugging
When we inspected the logs, we found errors like:

INSUFFICIENTACCESSORREADONLY

Errors that never surfaced before —
because Process Builder ignored them.

The Real Cause
The dev team assumed:

“Refactoring = same logic.”

But automation tools have different execution contexts:

  • Process Builder / Flow
    → runs in system mode (ignores permissions)
  • Apex “with sharing”
    → respects record access
  • Apex “without sharing”
    → bypass all restrictions

Choosing one over the other is not a technical detail.
It is a business decision.

The Fix
The team had to:

  • temporarily re-enable all Process Builders
  • rewrite Apex to run in system mode where appropriate
  • retest every scenario
  • coordinate an emergency deployment

It took days.

All because of one missing question:

“What permissions do business users actually have?”

The Lesson
Never assume that refactoring is “safe.”

As a Salesforce tester, always ask:

1. Does the new automation run in the same execution context?
If not → behaviour changes.

2. Does the user have the same access Process Builder used to bypass?
Usually not.

3. Should the user have that access?
Often no, but the system relied on it anyway.

4. Was the original behaviour intentional or accidental?
You’d be surprised how often the latter is true.

Final Thoughts
Salesforce doesn’t break because code is bad.
It breaks because assumptions are bad.

Automation tools behave differently
even when the logic is identical.

And if you don’t test execution context,
you are not testing automation —
you’re just clicking buttons.

More case studies from real projects coming soon.

Subscribe to Salesforce Tester

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe