Software Engineering

Leaving Salesforce: The Engineering Migration Runbook

TuniCyberLabs Team
8 min read

Every Salesforce exit guide stops at strategy. This is the engineering runbook: object load order, the permanent ID mapping table, the automation rewrite inventory, parallel-run reconciliation, cutover criteria, and a rollback plan you can actually execute.

Search for leaving Salesforce and you get strategy: total-cost decks, vendor comparisons, change-management advice. Useful, and none of it will load a single record. This is the other document: the engineering runbook for the exit itself. What to export and when, the order objects load in, the ID mapping table you will keep forever, the automation you must inventory before you can rewrite it, and the parallel run that earns you the right to cut over. It assumes the destination is a custom system, the path we map end to end in our complete guide to migrating from SaaS to custom software.

Why is leaving Salesforce an engineering project, not an export job?

Because the data is the easy part. A mature Salesforce org is a running program: Flows, Apex triggers, validation rules, and formula fields encoding years of business decisions, many undocumented. The export gives you a database; the runbook exists to move the program and prove, with reconciliation numbers, that the replacement behaves the same.

Treat the org as an archaeological site. Years of admins and consultants have layered automation on automation, and some of it fires on every save without anyone remembering why. Before any timeline is credible you need two inventories: the data model, objects, fields, relationships, record types, and the behaviour, meaning everything that runs. The CRM exit-readiness audit is the structured version of that first pass, and it sometimes concludes that only part of the stack should move, in which case the hybrid architecture pattern is the smaller, saner project.

When does the data-export countdown start, and what must be in the export?

The countdown starts the day you decide to leave, not the day the contract ends. While the subscription is active you have full API access on your terms; after termination you are relying on a contractual retrieval window that is typically short. Hold a complete, verified export before you give notice, never plan to fetch data afterwards.

  • Complete means more than records. Standard and custom objects with their system fields (created and last-modified dates and users), field history tables, files and attachments, email messages, and the metadata that describes the org itself.
  • Script it, do not click it. The weekly export service produces CSV snapshots, but what you want is a scripted Bulk API extraction you can rerun: deterministic, resumable, and diffable between runs. Build it like the jobs in Idempotent Data Pipelines: Batch Jobs That Survive Reruns, because you will run it many times before the run that counts.
  • Files are the long pole. Attachment volume commonly dwarfs record volume; start pulling ContentVersion data early and budget days, not hours.
  • Verify the contract, not the folklore. Exact post-termination retrieval windows, export tooling, and API entitlements change over time; check your Master Subscription Agreement and current Salesforce documentation rather than trusting blog posts, including this one.

In what order do you load objects into the new system?

Parents before children, references resolved in a second pass. A dependency-safe order for a typical org: users and owners, then accounts, contacts, products and price entries, opportunities, opportunity line items, cases, activities, and finally notes and files. Self-references such as account hierarchies load flat first and get parent links in pass two.

  • Derive the order, do not memorize it. Every lookup and master-detail field is an edge in a dependency graph; a topological sort of your actual schema gives your load order, and custom objects slot in wherever their lookups point.
  • Two passes beat clever ordering. Circular references, opportunity to primary contact, contact to account, are normal. Load records with nullable reference columns, then run an update pass that resolves them through the mapping table.
  • Load with constraints on. Put real foreign keys in the destination schema and leave them enabled. Every violation during load is a data-quality finding; orphaned records and dangling references are common in old orgs, and it is better to meet them now than in production.
  • Own your audit fields. In your schema you set the rules: store original created and modified timestamps in real columns so history survives, and record the migration itself as the provenance of each row.

How do you build the ID mapping table, and why do you keep it forever?

One table, four essential columns: the Salesforce 18-character ID, the new system's ID, the object type, and a migrated-at timestamp. Every load job writes it; every child load reads it to resolve foreign keys. It is not migration scaffolding, it is a permanent component of the new system.

  • Normalize to 18 characters first. Salesforce 15-character IDs are case-sensitive; the 18-character form adds a checksum suffix that makes them safe in case-insensitive tools. Convert every ID to its 18-character form before it enters the table, or spreadsheet-grade joins will silently cross-match different records.
  • Map metadata too. Picklist values to your enums, record types to your entity variants, and users to new accounts, including deactivated owners, who still own a surprising share of historical records.
  • Keep it forever because references outlive systems. Old email links, bookmarked URLs, documents quoting opportunity numbers, and partner integrations all carry Salesforce IDs. A tiny redirect endpoint that accepts an old ID, looks it up in the map, and forwards to the new record is cheap and buys years of goodwill.

How do you inventory the automation you are about to rewrite?

Extract every Flow, Apex trigger and class, validation rule, formula field, rollup summary, assignment rule, approval process, and scheduled job into one register, then force each row to a verdict: rewrite, replace with a human process, or delete. In long-lived orgs, a large share commonly ends up in delete.

  • Pull it mechanically. The Metadata API, or an sfdx project export, lists every automation artifact; a register built from memory will miss the ones that bite.
  • For each row record: what triggers it, what it changes, who owns the business rule, and whatever last-fired evidence you can find in debug logs or flow run histories.
  • Rewrites become code with tests. Behaviour that lived as configuration becomes explicit, reviewable application logic, the moment to give it the coverage described in A Testing Strategy That Survives Refactoring. Formula fields become computed columns or views; rollup summaries become queries; validation rules usually become both a database constraint and an application-level check.
  • Do not port one-to-one. The point of leaving is a domain model that fits. A faithful reimplementation of fifteen years of accreted configuration rebuilds the maze in a language you now have to maintain.

How do you run Salesforce and the new system in parallel without chaos?

One authority per object family at any moment, and a reconciliation job that proves the copies agree. The workable sequence: the new system shadows in read-only, then authority flips one family at a time, Salesforce becoming read-only for that family, with daily diff reports until mismatches reach zero.

  • Never let users dual-write. Two editable systems for the same object is how you manufacture un-reconcilable data. The non-authoritative side is a synced replica or frozen, nothing in between.
  • Sync continuously during the transition. Change events from the authoritative side keep the replica current; on the custom side, an outbox table gives the same guarantee, the machinery from Change Data Capture in Practice: Debezium, Kafka, and the Outbox Pattern.
  • Make reconciliation a report, not a vibe. Daily counts per object family, checksums over a sampled field set, and a named list of mismatched records. Drift is a bug with an owner, not a footnote.
  • Time-box it. A few weeks per object family is common; open-ended parallel running means paying for two systems while trusting neither.

What are the cutover criteria, and what does rollback actually mean?

Cutover is a checklist, not a date. Typical gates: zero unexplained reconciliation differences for a set number of consecutive days, automation parity signed off by process owners, integrations repointed and verified, users trained on real work, and a rehearsed rollback. Rollback means Salesforce is still there, read-only and current, until the window closes.

  • Rollback is the parallel-run machinery reversed. Because Salesforce stays read-only and synced during the rollback window, reverting is an authority flip plus a replay of the delta, not a restore from backups. That only holds if you rehearse it, the same discipline as PostgreSQL High Availability: The Failover You Rehearse.
  • Keep licences deliberately, briefly. Budget for Salesforce through the parallel run plus a defined post-cutover window. When it closes: take a final archive export, terminate, and keep the archive and the mapping table permanently.
  • Use the leverage while you have it. A working parallel run is also a negotiating position at renewal time; we cover that dynamic in building the exit before the renewal.

How TuniCyberLabs helps

We build the destination system and the migration pipeline as one project, domain model, load jobs, mapping table, reconciliation reports, and the security review of the result, for companies across the EU and North Africa that want the exit engineered, not improvised.

If your renewal lands within the next twelve months, the countdown has already started: talk to our custom software engineering team about turning your org inventory into a load-order plan.

TAGS
SalesforceCRM migrationdata migrationSaaS exitsoftware engineeringsystem integrationrunbook

Frequently Asked Questions

How long does a full Salesforce migration typically take?

+

For a mature org, commonly six to eighteen months from decision to terminated contract, with the parallel run accounting for a surprising share. Small orgs with light automation can move far faster. The honest driver is not record volume but automation count and integration count, inventory those first and your estimate stops being a guess.

What is the hardest data to get out of Salesforce?

+

Files and history, not records. Attachments and ContentVersion data are bulky and slow to pull; field history tables are large and often forgotten until someone needs an audit trail; and email threads live in awkward shapes. Standard object records are the easy part. Start extracting files early, and rehearse the full export at least twice before the run that counts.

Do we have to rewrite every Flow and Apex trigger?

+

No, and you should not. Inventory them all, then force each into rewrite, replace-with-process, or delete. In long-lived orgs a meaningful share is commonly dead: automations nobody can explain, guarding cases that no longer exist. Rewriting only the logic that earns its place is where much of the payoff of leaving actually comes from.

Should we keep Salesforce licences after cutover?

+

Yes, briefly and deliberately. Keep the org alive and read-only through a defined rollback window after cutover, so reversal is an authority flip rather than a restore. When the window closes, take a final archive export, terminate, and keep the archive plus the ID mapping table permanently. Do not rely on post-termination retrieval; verify your window in the agreement and plan never to need it.

Can we leave Salesforce gradually instead of a big-bang cutover?

+

Yes, that is the recommended shape. Flip authority one object family at a time: accounts and contacts, then opportunities and orders, then cases, each with its own parallel run and reconciliation gate. And if marketing or another function is genuinely well served by its current tool, a hybrid architecture that moves only the operational core can be the better end state entirely.

What does rollback look like if the new system fails after cutover?

+

It is the parallel-run machinery pointed backwards. Because Salesforce is still read-only and current during the rollback window, rollback means flipping authority back per object family and replaying the delta from the new system into Salesforce. That only works if you rehearsed it before cutover, an unrehearsed rollback plan is a wish, not a plan.

Need help with
this topic
?

Our team specializes in the technologies and strategies discussed in this article. Let’s talk about how we can help your business.

Get in Touch