First, why the Orca? That is a project code name.
This story is how our internal Ryzodus AI System Model helped make an inherited Salesforce Org understandable and safe to change for both my team, and the clients Marketing Managers.
.
A private lending client had a Salesforce org that looked, from the outside, like it needed a total rebuild. Loan work was moving through Workflow Rules, Process Builder, record-triggered Flows, validation rules, approval paths, Tasks, and Email Alerts. Some paths were old enough that nobody could confidently explain their original purpose. Others were still business-critical.
That is a bad place to be clever. And a good place for a revenue systems audit and modeling engine.
The tempting response was to throw out the legacy automation and make the org look clean. That would have been a good way to interrupt loan operations. A status change in this system can create tasks, notify staff, update a related processing record, adjust a financial rollup, or start another automation. A Draw Request can be an approval event, a payment event, or both, depending on the field that changed. The org did not need a new philosophy. It needed its existing process to stop being fragile.
So I treated this as a stabilization effort: preserve known-good behavior, identify the places where two paths were trying to own one outcome, and make only changes we could explain, read back, and test the mechanics of the revenue system.
The actual problem was overlap around control fields
The first useful model was not a giant object map. It was a map of the few fields that behaved like orchestration switches.
For this org, a Loan Transaction status was not merely a label. It influenced notifications, follow-up work, a related processing record, and multiple lifecycle rules. A Draw Request’s approval status and payment status were separate switches with different owners and downstream effects. Contact fields served as intake staging for some draw and payoff requests. Those relationships made it possible to ask the right question before every edit: who writes this value, who reads it, and what else wakes up when it changes?
That view quickly exposed the dangerous pattern. The issue was not that there were old automations. It was that several automations could react to the same event, sometimes write the same record again, and then cause a second wave of flows, alerts, and state changes. An ordinary save became hard to reason about.
The system model did not make me omniscient
I was not the original Salesforce builder, and I did not begin this project with complete knowledge of the lending process. Project Orca did not magically give me that knowledge. It gave me something more useful: a maintained, source-grounded way to separate what the metadata confirmed, what the client said the business intended, what I could reasonably infer, and what was still unknown.
The model covered the core Salesforce records, control fields, automation paths, field ownership, known issues, and open questions. As the work expanded, it also mapped the system around Salesforce. Website forms and integration tools could create or update records before a Salesforce Flow ever ran. Marketing automation could react to flags written in Salesforce and feed engagement data back later. A behavior that looked local to one record could be part of a loop across WordPress, Zapier, ActiveCampaign, and Salesforce.
That wider context changed how I approached optimization. Removing a second save might make one Flow more efficient, but it could also remove the event an external integration was waiting for. A field that looked obsolete in Salesforce could still be a handshake with another system. The model let me trace those dependencies before treating them as clutter.
This was an agentic engineering project in a practical sense. The working model could hold far more organizational and metadata context than I could keep in my head at once, compare new evidence against prior findings, and preserve the history behind a decision. My responsibility was still to judge the evidence, recognize when the model did not know something, ask the right business owner, and decide what was safe to change.
The result was not a perfect digital twin of the company. It was a living map with confidence boundaries. That was enough to stop treating every production edit as a blind experiment.
One business outcome needs one intentional writer
One early review found two automation paths contributing to the same specialized construction-budget rollup. The older branch accumulated a total in one variable and later tried to write the result from a different variable. There was already a newer, purpose-built Flow responsible for the same budget-spend outcome.
I did not rewrite the financial calculation. I disabled only the faulty duplicate branch and left the purpose-built Flow as the canonical writer. The remaining elements were retained for rollback and audit visibility.
That is a useful rule far beyond Salesforce: when two automations can own the same business value, the system is not really under control. It may appear correct until the next edit. Pick one intentional writer, then make the second path unreachable or remove it only when the evidence is clear.
Salesforce Process Builder migration is a comparison exercise, not a button click
Salesforce can generate a Flow from Process Builder or from a Workflow Rule. It is useful as a draft generator. It is not a guarantee of behavior.
I treated every migration as a comparison between the old trigger, conditions, field writes, related-record actions, and side effects. Before an activation, I asked:
- What event should start this?
- Is it create-only, a field change, or any record update?
- Does it update the triggering record, create something related, send an alert, create a task, or clear a staging field?
- Does it contain a hard-coded owner, record type, recipient, or default value that needs to stay for parity?
- Will the new Flow wake up on unrelated edits?
- Is the new Flow’s active version actually the version I reviewed?
Contact automation was a batch of small contracts
The Contact record was a good example of why I did not treat migration as a cleanup project. It carries borrower, intake, routing, marketing, and operational-state data. An apparently small automation can update a field that another Flow, a Task process, or a staff handoff is waiting on.
I migrated four legacy Process Builder-style automations and six Contact Workflow Rules as small, behavior-preserving Flows. The practical work included a Chatter post for a payoff-intake event, status and campaign updates, a description abbreviation, an inbound-call indicator, a prequalification date, a Cold Call timestamp, and an account-driven Contact classification.
One pair of Cold Call Workflow Rules set and cleared the same timestamp. I combined them into one scoped Flow that handles both outcomes when the relevant status changes. That removed the possibility of two separate legacy rules competing to own one value without turning the Contact object into a giant new master Flow.
Another migration exposed a less obvious constraint: the original rule copied from a long text field, and Salesforce’s migration tool would not create that Flow automatically. The solution was not to loosen the trigger until it saved. I rebuilt the small field-setter manually, kept it narrow, and made its entry scope explicit. A Contact Flow that runs on every ordinary edit is how an innocent migration becomes a production nuisance.
The Chatter-post migration also mattered because it was not just a field update. The old automation posted on the Contact’s own feed when a loan-number intake event occurred. I reproduced that behavior with a text template and a Flow Chatter action, removed a redundant link back to the same record, and allowed a fresh post if the supplied loan number later changed. A legacy person mention was intentionally left in place pending a business-owner decision. That is the right order: preserve the known operational signal first; improve an ambiguous old convention only after someone owns the choice.
That caught two meaningful migration defects.
Start conditions can invert a working process
A migrated Contact Flow for creating a Draw Request had its Start condition reversed. Its internal decision correctly recognized a populated property field, but the Flow itself was set to begin when that field was blank. That meant it could wake up on thousands of irrelevant Contact updates and could skip a legitimate draw submission.
The repair was small: restore the original OR logic so the Flow starts only when the appropriate draw or payoff staging value is populated. The work was not small in principle. A Flow that saves without errors can still be logically absent when the business event arrives.
OR is dangerous when every condition is not equal
Another migration was more serious. A lifecycle Flow should move a loan to its post-review stage when a decision is made, but only if the loan has not already reached a protected later stage. The migration tool expressed the exclusions like this:
(decision A OR decision B OR decision C)
AND
(status != later stage 1 OR status != later stage 2 OR status != later stage 3)
The second group is effectively always true. A record can always be different from at least one value in a list. That translation could have moved an already-later-stage loan backwards.
The intended logic was:
(decision A OR decision B OR decision C)
AND
status != later stage 1
AND
status != later stage 2
AND
status != later stage 3
I corrected the condition, retrieved the saved version for confirmation, and took the high-impact transition to the operational owner for review. This is the kind of bug that looks reasonable in a migration screen and is not reasonable in production.
Preserving legacy behavior can still preserve a bad rule
I also found a case where the migration itself was faithful, but the inherited rule was operationally wrong.
An old rule was overwriting the primary loan date from a later recording event. The operations team clarified that the closing date, not the recording date, was the correct business date because downstream payment timing and follow-up logic depends on it. I had initially treated the legacy behavior as something to preserve. That was the wrong interpretation once the business owner clarified the real process.
We deactivated the conflicting Flow, isolated the current records that needed review, obtained approval for that exact scope, tested a pilot, and corrected 27 confirmed records. One remaining record was blocked by a separate email-sender failure, so it was not retried blindly.
That is a useful production rule: existing metadata is evidence of what the system has done. It is not final proof of what the business intends. When those disagree, the business owner decides, the scope stays narrow, and the correction gets its own verification plan.
Before-save is a performance pattern, not a religion
The Loan Transaction was the org’s most heavily automated record. The review found roughly 30 active record-triggered Flows, including many after-save Flows that only wrote fields on the record that had just triggered them. That pattern forces another save cycle and can wake more automation.
For a batch of pure field-setters, I checked whether any active automation depended on that extra save event. Only then did I move eligible updates from after-save to before-save. The same conditions and values were preserved; the unnecessary second write was not.
But I did not convert everything. One candidate relied on a formula field. Formula and roll-up values may not be recalculated early enough for a before-save Flow to use them reliably. The attempted conversion could not be activated, so the working after-save Flow was left in place. That was a valuable constraint to record: before-save is appropriate for a stored-field update on the same record, not a universal cleanup button.
For a related Flow, the system had a naming limit that could break a create/update path. The repair was to truncate the display name only where the field limit required it and use the Salesforce relationship ID as the authoritative link. A record’s name is a label. Its ID is the relationship.
Some legacy automation should be retired, and some should be parked
Migration is not always the right answer.
I found five active Workflow Rules with time-trigger shells but no actual actions: no field update, Task, alert, or outbound message. Their names implied follow-up behavior, but the metadata did not implement it. Those were retired without creating new Flows.
Another older review-request process had hard-coded references to people who were no longer current users. It likely did nothing in its present form, but it also touched campaign behavior and could have external dependencies outside Salesforce. I parked both the old behavior and the migrated draft pending client confirmation instead of silently changing user references and calling it a migration.
This is one of the quieter parts of good system work: distinguish an obsolete rule from an unknown process. Those are not the same thing.
Email alerts have three levels of proof
A missing Review Complete notification later showed why a Flow diagram is not enough.
The affected loan had changed to the correct status. The upstream approval Flow had done its job. But the downstream notification marker was still false, and the alert was configured to send from the running user. In this org, that made delivery sensitive to Salesforce domain verification and the context of the user or automation that triggered the change.
The repair had three parts:
- Move the upstream same-record status assignment to before-save, so it did not rely on a brittle downstream recursive save.
- Change the alert to a verified org-wide sender.
- Use designated test Loan Transactions to execute the full approval-to-review-complete path without touching a customer’s active work.
Two live tests reached the expected status and downstream marker. The intended recipient confirmed receipt. We then updated the template to show the employee who made the status change, so the more reliable sender context did not remove useful operational information.
A second recipient reported delayed delivery even though the alert named the correct recipients. That was an important boundary, not an excuse. Salesforce record state can show that a branch completed. It cannot prove every inbox received an email. At that point the remaining surface was mail delivery or organization-level filtering, and the correct evidence would be an email log or the recipient’s mail system.
| What I was proving | Evidence that supports it | What it does not prove |
|---|---|---|
| The correct Flow is active | Metadata readback and active-version verification | That a real record follows every branch correctly |
| The record path completed | Field history and downstream markers on a safe test record | That an email reached every recipient’s inbox |
| The alert is configured to send | Verified sender and alert/template review | That downstream mail filtering will not delay or quarantine it |
That separation is a useful diagnostic map for any Salesforce notification incident. Do not call an email issue fixed because the Flow looks correct. Do not blame a Flow when the record path completed and the message is delayed by a mail-security layer.
How I validated changes without pretending every change was fully tested
I used different levels of proof and wrote down which level each change reached.
- Metadata confirmation: compare old and new automation, deploy or activate only the reviewed version, then retrieve it again and check active state.
- Record-path confirmation: inspect representative field history, markers, related records, and task/alert behavior on an approved safe test scenario.
- Recipient confirmation: ask the actual operational recipient to confirm delivery when the change affects an email or alert.
- Ongoing monitoring: for migrations that should only run on a real future draw, payoff, or loan event, state exactly what the team should watch for instead of inventing a test that could create unwanted downstream records.
That made the work more honest and more useful. A deploy can succeed while the wrong Flow version is active. A record can transition correctly while an Email Alert fails. A later test can show a new problem that belongs to email filtering rather than Salesforce logic. Each fact needs its own evidence.
The successful result was mostly invisible
This kind of work is difficult for a client to see. Nobody opens Salesforce in the morning and celebrates that a Process Builder was replaced with a scoped Flow. They do not notice the redundant save that no longer happens or the automation branch that no longer wakes up on an unrelated edit.
They might notice the negative space. A record saves without stalling. A status transition completes. The expected Task appears. An email arrives. The page feels less temperamental. The error inbox gets quieter. What used to be mysterious automation is simply “the thing Salesforce does” again.
I cannot responsibly attach a percentage to that improvement. Project Orca did not begin with a controlled benchmark for page-load time, governor-limit consumption, or error volume. The evidence is more concrete and narrower: fewer unnecessary record writes, tighter Flow entry criteria, duplicate ownership removed from a financial update, broken migration logic corrected, sender-context failures repaired, and known high-risk paths exercised with safer tests.
The larger impact was change safety. Before Orca, adding a new Flow meant working around automation I did not fully understand. Afterward, I had a maintained map of the important writers, readers, handoffs, integrations, and unresolved questions. That did not eliminate risk. It made the blast radius visible enough that I could keep engineering the system instead of being afraid to touch it.
What I changed, and what I deliberately left alone
The core automation inventory documented 28 legacy-automation swaps. Most preserved existing behavior; the exceptions were reviewed and changed deliberately. The Loan Transaction scope accounted for 17: seven Process Builder automations and ten Workflow Rules. Contact-triggered work accounted for five Process Builder-style migrations, including Draw Request creation, plus six Workflow Rule migrations. I also retired five stale no-op rules, corrected migration conditions, removed one clearly duplicated financial-update path, repaired a related-record handoff, reduced eligible self-updates to before-save behavior, and addressed a production notification incident.
I did not call the org finished.
Several hard-coded owners, record types, fee defaults, recipients, and template assumptions were preserved because changing them would be a business decision, not a migration. A duplicate-account situation behind a default lender assignment was documented rather than quietly merged. Some flows were intentionally left after-save because their inputs or downstream effects made a timing conversion unsafe. Some legacy behavior was parked because its current owner and purpose were not confirmed.
That is not incomplete engineering. It is how to keep a production system from absorbing a revision somebody only half understands.
Practical patterns an AI or engineer can reuse
When analyzing a Salesforce org with Workflow Rules, Process Builder, and Flow living together, I would start here:
- Identify the fields that act as system switches: status, approval, payment, routing, and staged-intake fields.
- Build a writer/reader map before editing a Flow. The highest-risk issue is often two paths owning one result.
- Treat the migration tool as a draft generator. Compare trigger scope, condition logic, same-record writes, record creation, field clearing, task creation, recipients, and hard-coded references.
- Inspect every migrated Start condition. In particular, test
Is Null,Is Changed, andnot equallogic against the original condition and existing records. - Move a same-record update to before-save only after confirming the input is a stored value and no live downstream process requires the resulting second save event.
- Prefer Salesforce record IDs for relationships. A display name can be duplicated, edited, or truncated.
- Verify the active Flow version, not merely the latest saved or retrieved version.
- Separate process proof, record-path proof, and email-delivery proof.
- Retire legacy automation that truly has no actions. Park stale automation that may still represent an unconfirmed business process.
- Keep a change log that states what changed, what was tested, what still needs a future real-world observation, and what requires a business owner to decide.
The result
The client did not need a shiny replacement Salesforce org. They needed the current one to stop fighting its operators.
The real deliverable was not 28 migrated automations. It was a safer surface for every change that came afterward. Project Orca did not teach me everything about an inherited Salesforce org. It gave me enough verified system understanding to change it without treating every production save as a black box.
That meant making small, reversible changes around real operational risk; pushing a migration statement through the same level of scrutiny as a new Flow; and being willing to say, “I do not yet know whether this old process is still intended.” It also meant owning the one case where legacy behavior looked technically valid until the business owner clarified it was not.
The client-facing outcome was deliberately unremarkable: fewer stalls, fewer avoidable errors, and more of the operational “magic” happening when it was supposed to. Underneath that quiet result was a system model spanning Salesforce and the integrations around it, an audit trail of what changed and why, and a growing ability to engineer the platform holistically instead of one configuration screen at a time.
That is the kind of Salesforce work I want to be known for: enough architecture to see the system, enough discipline to protect production, and enough humility to let operational truth outrank an old configuration page.
System Debriefs are drafted from live working-session context by the engineering harness that did the work — this one by OpenAI Codex, from the session this post describes — then reviewed, verified, and published by me. A full write-up of how that works is coming; until then, this sentence is the disclosure.