Switching from Salesforce
Salesforce data moves into Tessule as files: one CSV per object, the object’s own metadata beside it, and the file bodies. Nothing connects to your org, and no Salesforce credential is handed over. This guide is the checklist for producing that export, the definition of a complete set, what each part becomes in Tessule, and what stays behind.
There are two ways in:
- A few objects, through the import wizard. Export the objects, run
sf sobject describefor each, and the wizard types every column from the describe, links the objects to each other and proposes the tables. See Typing from Salesforce metadata. - A whole org, as a bundle. The export checklist below produces a folder the migration converter turns into schema plans, import plans, saved views, record layouts, a permissions skeleton and a coverage report, applied to a workspace in one order with owners, dates, authors, stage history, activities and files carried over. The converter is run with Tessule on your bundle — contact support@tessule.com.
Both routes keep the Salesforce Id of every record in a source_id field,
so a second run updates what the first created and links resolve across
files whether an Id is 15 or 18 characters long.
Before you export
Section titled “Before you export”- Clean up. Dedupe, retire unused picklist values and fields, and decide which objects move. Formula and roll-up fields are never in an export; Tessule recomputes them.
- Note who is active. Records owned by deactivated users keep their owner; the owner becomes a pending member who has no account until invited. Decide whether those people are invited.
- Freeze for the final run. Pause flows and integrations once the final export is taken, and keep the org read-only until the workspace is verified.
The export checklist
Section titled “The export checklist”Each step names the native Salesforce tool. Everything runs in your org, with your access.
- Users. Setup → Users → export, or
sf data export bulk --query "SELECT Id, Username, Email, Name, IsActive FROM User" --output-file users.csv --result-format csv. Owners, creators and editors are matched to people by email, so the user file is what gives every record its owner. - Object metadata, the minimum. For every object you move:
sf sobject describe --sobject Account --json > describe/Account.json. This is what types the fields exactly: labels, required and unique, picklist values, lookup targets.sf org list metadata --metadata-type CustomObjectlists the custom objects. - Configuration, the full package. Recommended:
sf project generate manifest --from-org <alias> --output-dir .thensf project retrieve start --manifest package.xml --target-org <alias> --output-dir metadata/. The package carries list views, layouts, validation rules, flows, profiles and permission sets, which become saved views, record layouts, constraints and the inventory of what to rebuild. Large orgs need several retrieves; keeppackage.xmlwith the export. - Data. Setup → Data Export → Export Now with the encoding set to
UTF-8, “Include images, documents, and attachments” and “Include
Salesforce Files and Salesforce CRM Content document versions” ticked, and
either “Include all data” or the objects you move plus
User,RecordType,OpportunityHistory,Task,Event,Note,Attachment,ContentDocument,ContentVersion,ContentDocumentLink,CampaignMember,OpportunityContactRole,OpportunityLineItemandPricebookEntry. Download within 48 hours and unzip intodata/(the CSVs) andfiles/(the bodies). At scale, or for deleted and archived rows, export per object withsf data export bulk --query "SELECT … FROM Task" --all-rows; archived tasks and events only come out with--all-rows. - The manifest. Write
bundle.json: the org id, the API version frompackage.xml, the export date, the object list, a row count per object (Setup → Storage Usage) and a SHA-256 per file. The converter checks the bundle against it first, so an incomplete set is caught before anything is uploaded.
Things that catch people out:
- The Data Export link expires after 48 hours.
- A UTF-16 export (the “Unicode” choice) is refused with the
iconvcommand that converts it. Choose UTF-8. - Deleted records come out only with “Export All” or
--all-rows; archived activities only with--all-rows. - Field history is kept for 18 months in Salesforce and comes out as the
*Historyobjects; only stage history is written into Tessule (below). - Inactive users still own records. They are matched like active ones.
The bundle
Section titled “The bundle”A complete, restorable export is one folder:
| Path | What | Required |
|---|---|---|
data/<Object>.csv |
One Data Export or Bulk API CSV per object, UTF-8 | yes |
describe/<Object>.json |
sf sobject describe --json per object |
yes (without one, a standard field is typed from Salesforce’s published object reference and every other column of that object is text) |
metadata/ |
The retrieved Metadata API package, source or mdapi format | recommended |
files/ |
Attachment and ContentVersion bodies, at the paths the CSVs name | when files move |
users.csv or data/User.csv |
The user directory | one of the two |
bundle.json |
The manifest: objects, row counts, a SHA-256 per file | recommended |
Keep the bundle. It is the off-platform archive of the org as it was at cutover, and the only form the migration can be re-run from. After the import, the workspace backup is the restorable artifact (see Backups); Salesforce’s own terms give a window after termination to export, and the bundle predates it.
What transfers
Section titled “What transfers”| In Salesforce | In Tessule |
|---|---|
| Standard and custom objects | One table per object, with source_id holding the Salesforce Id, required and unique |
| Fields | Typed from the describe: text and long text, email, phone, URL, integer and number, currency, percent, date, datetime, time, boolean, picklist and multi-select picklist with their values, geolocation; labels, help text, required and unique as set. A standard field the describe does not list is typed from Salesforce’s published object reference, with a picklist’s values taken from the exported rows; a custom field the describe does not list is text |
| Lookups and master-detail | Reference fields between the moved objects; master-detail as a required reference; self-references (ParentId) included; a lookup to several moved objects becomes a polymorphic reference to them |
| Junction objects | Child tables with two references and a composite unique constraint |
OwnerId, CreatedById, LastModifiedById |
The record’s owner and authors, matched to people by email; a person not yet a member is created as a pending member, claimed when they accept an invitation |
CreatedDate, LastModifiedDate |
The record’s own created and updated instants, not the import’s |
StageName, Status on Opportunity, Case and Lead |
Stage fields with Closed Won and Closed Lost as categories |
OpportunityHistory and stage field history |
The record’s stage history, every move dated as it happened, written as migrated history |
| Task, Event, Note | Activities of type task, meeting or call, and note, attached to the records their WhoId and WhatId named |
| Attachment, ContentVersion (latest version) | Files on their records, one per field, overflow in a <table>_files child table |
RecordTypeId |
A record_type picklist on the table |
| Validation rules on one record | check constraints, where the formula is in the supported grammar |
| Roll-up summaries, same-row formulas | Rollup and formula fields, where the operation maps |
| List views | Saved views: columns, filters whose operators map, sort |
| Page layouts | Record layouts: sections, field order, related lists |
| Profiles, permission sets, public groups | Groups with their members, an empty custom role per profile or permission set, private visibility where every non-admin profile was denied, and a report of the grants to set by hand; nothing is granted automatically |
| Flows, Process Builder, workflow rules, Apex, approval processes, reports, dashboards, email templates, assignment and sharing rules | An inventory, each with its Tessule equivalent, sorted active first |
What does not transfer
Section titled “What does not transfer”| Item | Why | What to do |
|---|---|---|
| Flows, Process Builder, workflow rules, Apex as running automation | A different execution model | Rebuild from the inventory in the flow editor; the AI assistant can draft from the inventory rows |
| Approval processes | Approvals here are rules on updates | Rebuild as approval rules and a flow on the decision |
| Reports and dashboards | A different query model | Rebuild as saved views with grouping, queries and dashboard tiles |
| Layout assignment per profile or record type | One layout per audience | Audience-specific layouts and conditional sections |
| Sharing rules, role hierarchy, queues, assignment and escalation rules | Not modelled | Roles, groups and record shares; round-robin as a flow |
| Field history other than stage moves | No API writes historical change entries | Keep the *History CSVs in the bundle |
Amount and close-date snapshots in OpportunityHistory |
Only the stage moves are history | Keep the CSV in the bundle |
| Dependent picklists and global value sets | Every value is offered regardless of the controlling field | The dependency is noted in the field description |
Cross-object, $User and CASE formulas |
Outside the supported grammar | Rebuild by hand from the report |
| Encrypted fields | No encrypted type | Review, then import as text or exclude |
| File versions, one file shared by many records | One file per field, no sharing | The latest version, copied per record |
| Email threads, Chatter, Knowledge, Communities | No model | Archive only |
| Multi-currency conversion | Amounts keep their currency code; sums are not converted | Report in one currency |
Applying a bundle
Section titled “Applying a bundle”The converter reads the bundle and writes the documents that build the
workspace, applied in this order: tables and fields, then the data (one
import job per object file, updating on source_id), then activities and
files, then the stage configuration, the stage history and the dated
baseline for records the history left out, then constraints, saved views and
record layouts. Every step is safe to run again. The principal applying the
plan is a workspace admin who also holds org:members:manage in the
workspace’s organization (to create pending members),
records:importProvenance (to set the original dates, authors and owners)
and records:backfillHistory (to write the stage history as migrated
history, through the job’s stage-history file or
POST /tables/{tableId}/stage-transitions/seed).
People are never invited by the import. Everyone the data names becomes a
pending member with no account and no seat, holding their records; an
organization admin invites them from the organization console when the time
comes, singly or with
POST /organizations/{organizationId}/invites/bulk, and an accepted
invitation claims the pending member, records and all.
Then verify: record counts per table against the manifest, a sample of owners, links, stages and files, and the coverage report, which lists every object and field with what it became and every compromise made on the way. Sign off before decommissioning the org.