CRM migration
Field-level mapping, validation, and rollback between EspoCRM and Freshsales. We move data and schema; workflows are rebuilt natively in Freshsales.
EspoCRM
Source
Freshsales
Destination
Compatibility
9 of 11
objects map 1:1 between EspoCRM and Freshsales.
Complexity
BStandard
Timeline
3-5 weeks
Overview
Moving from EspoCRM to Freshsales is a structural migration that moves data from a self-hosted AGPLv3 platform to a cloud-native SaaS CRM with built-in email, calling, chat, and AI-powered lead scoring. EspoCRM's Entity Manager creates custom entity types that require metadata export before record migration; Freshsales has no equivalent Entity Manager, so custom entity records map to custom fields on standard objects or to Freshsales custom objects pre-created in the destination. EspoCRM's default 200-record API ceiling and multi-enum field cap of 20 options are migration-surface risks we detect during discovery. Self-hosted EspoCRM instances store file attachments on the server filesystem under data/files/, which requires a separate file-transfer step alongside the database export. We do not migrate EspoCRM Workflows, BPM processes, or custom PHP scripts as code; we deliver a written inventory of these for the customer's admin to rebuild in Freshsales.
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 Freshsales, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
EspoCRM
Contact
Freshsales
Contact
1:1EspoCRM Contact records map directly to Freshsales Contact. We map name, email, phone, address, and any custom fields 1:1. Multi-email fields in EspoCRM (where a contact can have multiple email addresses) are handled by mapping the primary email to the standard email field and storing additional emails in a Freshsales custom multi-value text field that the customer's admin configures before import. If the source EspoCRM instance uses multi-enum fields with more than 20 options, we flag these during discovery and either split into multiple picklist fields or store as a comma-separated text field.
EspoCRM
Account
Freshsales
Account
1:1EspoCRM Account records map to Freshsales Account with company name, website, industry, billing address, and phone preserved. Account is created before Contact import so that the Contact-to-Account relationship is satisfied at insert time. EspoCRM link-multiple relationships from Account to Contact are reconstructed as Freshsales Account-Contact lookups using ID remapping tables.
EspoCRM
Lead
Freshsales
Lead
1:1EspoCRM Lead records with conversion status map to Freshsales Lead. The EspoCRM lead_status field maps to Freshsales Lead Status. Any lead_score or rating values stored as custom fields migrate to Freshsales custom fields. Leads that were converted in EspoCRM (with linked Account and Contact created) are imported as Freshsales Leads with a note flagging their converted status; the customer decides whether to convert them again in Freshsales or treat them as closed leads.
EspoCRM
Opportunity
Freshsales
Deal
1:1EspoCRM Opportunity records map to Freshsales Deal. Opportunity amount, stage, probability, and expected close date transfer to Freshsales Deal amount, stage, probability, and expected close date. EspoCRM stage values are mapped to Freshsales pipeline stage names during discovery. The Opportunity-to-Account link is resolved via the Account ID remapping table at migration time.
EspoCRM
Case
Freshsales
Case
1:1EspoCRM Case records (support tickets) map to Freshsales Case. Case status, priority, resolution fields, and the full conversation thread (stored as Activity or Note records in EspoCRM) migrate to Freshsales Case with the same relationships. The EspoCRM case number becomes a custom field on Freshsales Case to preserve audit traceability.
EspoCRM
Campaign
Freshsales
Campaign
1:1EspoCRM Campaign records migrate to Freshsales Campaign. Campaign targeting lists (linked Leads and Contacts) are recreated as Freshsales Campaign Members after the Lead and Contact imports complete. We note that EspoCRM email send history (open rates, click data) does not migrate because this is a live-metrics feature; only the campaign record and targeting list transfer.
EspoCRM
Custom Entity (Entity Manager)
Freshsales
Custom Field or Custom Object
lossyEspoCRM custom entity types created via Entity Manager require metadata export before record migration. We export the entityDefs metadata to identify all custom fields, field types, and relationships. For simple custom entities with a 1:many relationship to a standard object (e.g., a Project entity linked to Account), we create Freshsales custom fields on the parent object and store the custom entity data as serialized JSON in a long-text field or split into individual custom fields based on data type. For complex custom entities with cross-references to other custom entities, we pre-create Freshsales custom objects, define lookup relationships, and migrate in dependency order using topological sort.
EspoCRM
Activities (Meetings, Calls, Tasks)
Freshsales
Activities
1:1EspoCRM Activities (Meetings, Calls, Tasks) linked to Contacts, Accounts, or Opportunities migrate to Freshsales Activities on the corresponding record. We resolve the parent record via ID remapping tables and preserve the original activity timestamp for timeline ordering. Meeting attendees are stored as Freshsales Activity participants linked via the activity ID.
EspoCRM
Email (stream records)
Freshsales
EspoCRM stream records of type Email migrate to Freshsales Email records linked to the sender and recipient Contact or Lead. Email body content transfers as HTML. The EspoCRM Stream (activity feed) is a live-data feature and is not reproduced in Freshsales; only the email record itself migrates.
EspoCRM
Attachment (filesystem)
Freshsales
Attachment (cloud storage)
lossyOn self-hosted EspoCRM instances, uploaded files live on the server filesystem under data/files/ and are not stored as database blobs. A standard database export will not capture these files. We identify Attachment records during discovery, extract the referenced files from the filesystem archive, transfer them alongside the record migration, and re-register each file with the corresponding Freshsales object record. We validate that Freshsales file storage limits on the destination plan accommodate the total attachment volume before migration begins.
EspoCRM
User
Freshsales
User
1:1EspoCRM User records map to Freshsales User by email match. We extract user name, email, role assignment, and team memberships from EspoCRM. EspoCRM role permissions have no direct Freshsales equivalent, so we deliver a role mapping table for the customer's admin to configure Freshsales roles, territories, and visibility groups post-migration. Unmatched EspoCRM users go to a reconciliation queue.
| EspoCRM | Freshsales | Compatibility | |
|---|---|---|---|
| Contact | Contact1:1 | Fully supported | |
| Account | Account1:1 | Fully supported | |
| Lead | Lead1:1 | Fully supported | |
| Opportunity | Deal1:1 | Fully supported | |
| Case | Case1:1 | Fully supported | |
| Campaign | Campaign1:1 | Fully supported | |
| Custom Entity (Entity Manager) | Custom Field or Custom Objectlossy | Fully supported | |
| Activities (Meetings, Calls, Tasks) | Activities1:1 | Fully supported | |
| Email (stream records) | Email1:1 | Fully supported | |
| Attachment (filesystem) | Attachment (cloud storage)lossy | Fully supported | |
| User | User1: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
Freshsales gotchas
Freddy AI is Pro-tier only despite heavy marketing
Post-migration emails and sequences are disabled
Bot session credits are a one-time 500-session allocation
Phone credits charged per minute with no cap
File storage limits scale with plan tier
Pair-specific challenges
Migration approach
Discovery and entity audit
We audit the source EspoCRM instance across all entity types including Entity Manager custom entities, custom fields, multi-enum field option counts, attachment records, and cross-entity relationship types. We extract the entityDefs metadata for all custom entities and inventory the data/files/ directory for filesystem-stored attachments. We also identify the EspoCRM API endpoint structure, confirm whether the instance is cloud or self-hosted, and assess record volumes per entity type. The discovery output is a written migration scope with entity counts, custom field inventory, multi-enum flag report, and attachment volume estimate.
Destination schema preparation in Freshsales
We create Freshsales custom fields to match EspoCRM custom fields that do not have direct Freshsales equivalents, configure picklist values (checking Freshsales's 500-option limit against the source multi-enum counts), and pre-create any Freshsales custom objects needed for complex Entity Manager entity types. We configure pipeline stages in Freshsales to match EspoCRM Opportunity stages. All schema changes are applied to the destination Freshsales account before any record migration begins. We coordinate with the customer's Freshsales admin to apply any role and visibility configurations.
Dependency graph analysis and import ordering
We analyze all EspoCRM entity types and their cross-references to construct a dependency graph. Topological sorting of this graph determines the safe import order (e.g., Accounts before Contacts, Contacts before Activities). We build ID remapping tables so that when source EspoCRM IDs appear as foreign keys in related records, they map correctly to the Freshsales IDs assigned during import. This step resolves the chicken-and-egg ordering problem that causes orphaned relationships in automated migration tools.
Filesystem attachment extraction and staging
For self-hosted EspoCRM instances, we identify all Attachment records during discovery, map each attachment record to its filesystem path under data/files/, and extract the files to a staging directory. We validate that each extracted file's MIME type is supported by Freshsales attachment upload. We estimate total attachment volume and confirm it fits within the destination Freshsales plan's storage limits before proceeding to import.
Production migration in dependency order
We run production migration in record-dependency order: Accounts, then Leads, then Contacts, then Opportunities, then Cases, then Campaigns, then Activities and Emails, then Custom Entities, then Attachments last. Each phase emits a row-count reconciliation report before the next phase begins. ID remapping tables are updated after each phase so that subsequent phases resolve parent lookups correctly. We use the Freshsales Bulk Import API for large record sets and the REST API for smaller entities and attachments.
Cutover, validation, and Workflow inventory handoff
We freeze EspoCRM writes during cutover, run a final delta migration of any records modified during the migration window, then enable Freshsales as the system of record. We deliver a written inventory of all EspoCRM Workflows, BPM processes, and custom PHP/Before-Save scripts requiring rebuild in Freshsales. We support a one-week hypercare window where we resolve reconciliation issues raised by the customer's team. We do not rebuild EspoCRM automations as Freshsales workflows inside the migration scope; that is a separate engagement.
Platform deep dives
EspoCRM
Source
Strengths
Weaknesses
Freshsales
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 2 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 Freshsales.
Object compatibility
2 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 Freshsales migration scoping. Not seeing yours? Book a call.
Walk through your EspoCRM to Freshsales 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 Freshsales
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.