CRM migration
Field-level mapping, validation, and rollback between EspoCRM and Salesforce Sales Cloud. We move data and schema; workflows are rebuilt natively in Salesforce Sales Cloud.
EspoCRM
Source
Salesforce Sales Cloud
Destination
Compatibility
14 of 16
objects map 1:1 between EspoCRM and Salesforce Sales Cloud.
Complexity
BStandard
Timeline
4-6 weeks
Overview
Moving from EspoCRM to Salesforce is a structural migration across different deployment models: EspoCRM's AGPLv3 open-source platform (self-hosted or cloud at $15-$69 per user per month) versus Salesforce's multi-tenant SaaS ecosystem (starting at $75 per user per month on Sales Cloud Starter). EspoCRM's Entity Manager lets administrators build custom entity types without code, and those custom entities carry cross-reference relationships that must be resolved in dependency order during migration. We handle the 200-record API ceiling through paginated extraction, transfer filesystem-stored attachment files from self-hosted instances separately from the database export, and map EspoCRM's Leads, Contacts, Accounts, Opportunities, Cases, and Campaigns to their Salesforce equivalents. Salesforce Validation Rules and field-level security profiles can block record inserts if not coordinated with the destination org admin before migration. Workflows, BPM processes built with EspoCRM's Advanced Pack extension, and custom PHP/Before-Save scripts do not migrate; we deliver a written inventory for the customer's admin to rebuild in Salesforce Flow. Files stored on EspoCRM's filesystem require a separate transfer step that database exports alone do not capture.
Every standard and custom field arrives verified.
AI proposes the map; you confirm before any record moves.
Parent–child, lookups, and ownership stay linked.
Calls, emails, meetings — with original timestamps.
Documents, uploads, and inline notes move with the record.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a EspoCRM object lands in Salesforce Sales Cloud, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
EspoCRM
Contact
Salesforce Sales Cloud
Contact
1:1EspoCRM Contact records map directly to Salesforce Contact. The Email field serves as the dedupe key during import. We map all standard fields (FirstName, LastName, Phone, MobilePhone, MailingAddress) plus any custom fields. EspoCRM multi-email fields (multiple email addresses on one contact) require splitting: the primary email maps to Email and additional addresses are stored in a custom Textarea field custom_email_secondary__c. Multi-enum fields (capped at 20 options in EspoCRM) map to Salesforce Multi-Select Picklist fields with no option count limit.
EspoCRM
Account
Salesforce Sales Cloud
Account
1:1EspoCRM Account records map to Salesforce Account. We use the Account Name as the dedupe key. The industry sector, annual revenue, number of employees, website, and billing address fields map directly. Custom fields on EspoCRM Account map to custom fields on Salesforce Account (with __c suffix). Account must be created before Contact import so that AccountId Lookup is satisfied at insert time.
EspoCRM
Lead
Salesforce Sales Cloud
Lead
1:1EspoCRM Lead records map to Salesforce Lead. EspoCRM stores Lead status in a status field with custom values; we map those values to Salesforce Lead Status picklist entries, creating new Status values in the destination org if the EspoCRM values do not already exist. Converted Leads (those that have been converted to Contact and Account in EspoCRM) are handled separately: we migrate the original Lead record and link it to the converted Contact via a custom field espo_converted_contact_id__c for audit trail.
EspoCRM
Lead conversion
Salesforce Sales Cloud
Contact + Account (from conversion)
1:manyEspoCRM stores converted Lead records with links to the resulting Contact and Account. During migration, we identify converted Leads by the presence of convertedContactId and convertedAccountId fields, then create both the Account (if not already present) and the Contact in Salesforce, and store the original EspoCRM Lead ID on the Contact in a custom field espo_lead_id__c for lineage tracking.
EspoCRM
Opportunity
Salesforce Sales Cloud
Opportunity
1:1EspoCRM Opportunity records map to Salesforce Opportunity. Stage, probability, amount, close date, and description fields migrate directly. The pipeline assignment in EspoCRM maps to a Salesforce Record Type and Sales Process that we configure before migration. Custom fields on EspoCRM Opportunity (including any fields tracking product lines or deal-specific attributes) map to custom Opportunity fields in Salesforce.
EspoCRM
Case
Salesforce Sales Cloud
Case
1:1EspoCRM Case records (support tickets) map to Salesforce Case. Status, Priority, and Resolution fields map to their Salesforce equivalents. The conversation thread (case comments and customer replies) migrates as CaseComment records linked to the Case. Attachments on Cases are extracted from the EspoCRM filesystem (on self-hosted) or database (on cloud) and re-registered as Salesforce ContentDocument records linked to the Case via ContentDocumentLink.
EspoCRM
Campaign
Salesforce Sales Cloud
Campaign
1:1EspoCRM Campaign records map to Salesforce Campaign. Campaign name, type, status, start date, end date, budgeted cost, and actual cost migrate directly. The target Leads and Contacts list migrates as CampaignMember records (with Member Status values). We do not replicate email send history, open rates, or click-through data; EspoCRM does not expose this as structured data via its API, and reconstructing it from email integration logs is outside migration scope.
EspoCRM
User
Salesforce Sales Cloud
User
1:1EspoCRM User records map to Salesforce User records by email address match. Role assignments and team memberships are recorded in custom fields (espo_role__c, espo_teams__c) because Salesforce role hierarchies and groups are org-wide structures that require admin design decisions rather than direct mapping. The customer's Salesforce admin provisions Users in the destination org before migration; we reconcile EspoCRM users against existing Salesforce Users and flag any without a match for manual provisioning.
EspoCRM
Activity: Meeting
Salesforce Sales Cloud
Event
1:1EspoCRM Meeting records map to Salesforce Event with StartDateTime, EndDateTime, and Location preserved. The meeting description becomes the Event Description field. Attendees are mapped to EventRelation records pointing to the corresponding Contact, Lead, or User in Salesforce. Activity date ordering is preserved by setting the original EspoCRM timestamp.
EspoCRM
Activity: Call
Salesforce Sales Cloud
Task (TaskSubtype = Call)
1:1EspoCRM Call records map to Salesforce Task with TaskSubtype set to Call. Call duration, disposition, and any notes migrate to custom Task fields. The original timestamp is preserved in ActivityDate. If the EspoCRM instance stores call recordings as file attachments, those files are extracted from the filesystem and attached to the Task as ContentDocument records.
EspoCRM
Activity: Task
Salesforce Sales Cloud
Task
1:1EspoCRM standalone Task records map to Salesforce Task with Status, Priority, DueDate, and ActivityDate preserved. Task assignment migrates by resolving the EspoCRM assigned user (by email) to the Salesforce OwnerId via the User mapping. If the EspoCRM task is linked to a parent record (Contact, Account, Opportunity, Case), we resolve the parent reference and set WhatId or WhoId accordingly.
EspoCRM
Activity: Email
Salesforce Sales Cloud
EmailMessage + Task
1:1EspoCRM email records migrate to Salesforce as EmailMessage records (the email content) linked to an Activity Task record (the timeline entry). The email body, subject, from address, and to address migrate directly. The WhoId on the Task points to the related Contact or Lead; the WhatId points to the related Opportunity, Account, or Case. EmailMessage direction (inbound vs outbound) is preserved.
EspoCRM
Document (Attachment)
Salesforce Sales Cloud
ContentVersion + ContentDocument
1:1EspoCRM Document records linked to other entities (Contacts, Accounts, Opportunities) map to Salesforce ContentVersion and ContentDocument records. On self-hosted EspoCRM instances, the actual file data lives on the server filesystem under data/files/ rather than in the database. We identify all Document records during discovery, extract the referenced files from the filesystem archive, and upload them to Salesforce as ContentVersion records. On cloud-hosted EspoCRM, the file data is in the database and migrates with the standard database export. We re-register each file with the corresponding ContentDocumentLink to the parent record (Contact, Account, Opportunity, or Case).
EspoCRM
Custom Entity (Entity Manager)
Salesforce Sales Cloud
Custom Object (__c)
1:1EspoCRM custom entity types created via Entity Manager map to Salesforce Custom Objects with a __c suffix. We export the entityDefs metadata from EspoCRM first (field names, types, relationships, validation rules), then pre-create the destination Salesforce custom object schema including all custom fields, lookup relationships to standard objects (Contact, Account, Opportunity, Case), and validation rules. Custom entity relationships that reference other custom entities require topological sorting: we build a dependency graph, import entities with no dependencies first, then progressively import entities whose dependencies are satisfied.
EspoCRM
Custom Entity Relationship (link-multiple)
Salesforce Sales Cloud
Custom Object Lookup or Master-Detail
lossyEspoCRM link-multiple relationships (many-to-many or many-to-one) map to Salesforce Custom Object lookups or Master-Detail fields depending on the cascade-delete requirement. If EspoCRM's relationship is configured as required (mandatory link), we use Master-Detail; otherwise we use Lookup. Junction objects in EspoCRM (entities that hold two link-multiple references as a many-to-many join table) map to Salesforce junction objects with two Lookup fields.
EspoCRM
Note
Salesforce Sales Cloud
Note
1:1EspoCRM Note records migrate to Salesforce Note records. The Note body migrates as plain text. If the Note contains embedded images, those images are extracted as separate files from the EspoCRM filesystem and re-attached to the Salesforce Note. Notes are linked via ContentDocumentLink to the parent record (Contact, Account, Opportunity, Case, or custom object).
| EspoCRM | Salesforce Sales Cloud | Compatibility | |
|---|---|---|---|
| Contact | Contact1:1 | Fully supported | |
| Account | Account1:1 | Fully supported | |
| Lead | Lead1:1 | Fully supported | |
| Lead conversion | Contact + Account (from conversion)1:many | Fully supported | |
| Opportunity | Opportunity1:1 | Fully supported | |
| Case | Case1:1 | Fully supported | |
| Campaign | Campaign1:1 | Fully supported | |
| User | User1:1 | Fully supported | |
| Activity: Meeting | Event1:1 | Fully supported | |
| Activity: Call | Task (TaskSubtype = Call)1:1 | Fully supported | |
| Activity: Task | Task1:1 | Fully supported | |
| Activity: Email | EmailMessage + Task1:1 | Fully supported | |
| Document (Attachment) | ContentVersion + ContentDocument1:1 | Fully supported | |
| Custom Entity (Entity Manager) | Custom Object (__c)1:1 | Fully supported | |
| Custom Entity Relationship (link-multiple) | Custom Object Lookup or Master-Detaillossy | Fully supported | |
| Note | Note1:1 | Fully supported |
Gotchas + challenges
Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.
EspoCRM gotchas
Default 200-record API GET ceiling requires pagination
Server migration leaves WebSocket references pointing to old domain
Multi-enum field option cap of 20 limits data fidelity
Custom entity import ordering creates chicken-and-egg reference problems
Attachments on self-hosted instances are filesystem-stored
Salesforce Sales Cloud gotchas
Workflow Rules and Process Builder are retired
Bulk API batch quota exhaustion during large imports
Storage overage billing is non-obvious
Account-Contact many-to-many relationship mapping
Territory and team member import ordering dependencies
Pair-specific challenges
Migration approach
Discovery and source system audit
We audit the EspoCRM instance across deployment type (self-hosted or cloud), API configuration, total record counts per entity type, custom entity types and their field definitions (exported from entityDefs metadata), active workflows and BPM processes (Advanced Pack), and attachment volume (file count and total storage size on filesystem for self-hosted). We pair this with a review of the destination Salesforce org's current schema, Validation Rules, field-level security profiles, and available API licenses. The discovery output is a written migration scope with entity-level record counts, a custom entity dependency graph, and a Salesforce edition recommendation.
Schema design and dependency resolution
We design the destination Salesforce schema. For custom entity types, we pre-create the custom objects with __c API names matched to EspoCRM entity names, including all custom fields, lookup relationships, and validation rules. We build the dependency graph for custom entities and define the topological import order. We configure Salesforce Record Types and Sales Processes for Opportunity migration. Schema is deployed into a Salesforce Sandbox first via metadata API for validation before production migration begins.
Sandbox migration and reconciliation
We run a full migration into a Salesforce Sandbox (Full Copy or Partial Copy) using production-like data volume. The customer's EspoCRM admin and Salesforce admin jointly reconcile record counts, spot-check 25-50 records per entity type against the EspoCRM source, and validate that lookup relationships resolved correctly. Any mapping corrections, validation rule conflicts, or custom entity dependency issues surface here before production migration begins.
Filesystem extraction and owner reconciliation
For self-hosted EspoCRM instances, we extract all files from the data/files/ directory and index them against the Attachment records in the database. For cloud-hosted instances, we extract file blob data from the database export. We also reconcile EspoCRM Users against Salesforce Users by email address match. Any EspoCRM User without a matching Salesforce User goes to a reconciliation queue for the customer's Salesforce admin to provision before record import resumes.
Production migration in dependency order
We run production migration in record-dependency order: Accounts first, then Contacts and Leads (with the Lead conversion split resolved), then Opportunities with Record Type and Sales Process assigned, then Cases, then Campaigns and CampaignMembers, then Activities (Tasks, Events, EmailMessages via Bulk API 2.0 with chunking), then Custom Entities in topological order, then Notes and Attachments. Each phase emits a row-count reconciliation report before the next phase begins. EspoCRM's 200-record API ceiling is handled through paginated extraction loops with configurable maxSize.
Cutover, validation, and automation rebuild handoff
We freeze EspoCRM writes during cutover, run a final delta migration of any records modified during the migration window, then enable Salesforce as the system of record. We deliver the Workflow and BPM inventory document to the customer's admin team. We support a one-week hypercare window where we resolve reconciliation issues raised by the customer's team. We do not rebuild EspoCRM Workflows or Advanced Pack BPM processes as Salesforce Flow inside the migration scope; that is a separate engagement or an internal admin task.
Platform deep dives
EspoCRM
Source
Strengths
Weaknesses
Salesforce Sales Cloud
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 1 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across EspoCRM and Salesforce Sales Cloud.
Object compatibility
1 of 8 objects need a mapping; the rest are 1:1.
Field mapping clarity
Field mapping is derived from defaults — final spec confirmed during the sample migration.
Timeline complexity
8-object category — typical timelines run 2–7 days end-to-end.
API constraints
EspoCRM: Not publicly documented; rate limits can be configured server-side in the EspoCRM config file.
Data volume sensitivity
EspoCRM doesn't expose a bulk API — REST + parallelization used for high-volume runs.
Estimator
Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.
Step 1
Pick a category, then your source and destination platforms.
Category
FAQ
Answers to the questions buyers ask most during EspoCRM to Salesforce Sales Cloud migration scoping. Not seeing yours? Book a call.
Walk through your EspoCRM to Salesforce Sales Cloud migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave EspoCRM
Other ways to arrive at Salesforce Sales Cloud
Ready when you are
Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.