CRM migration
Field-level mapping, validation, and rollback between EspoCRM and Twenty CRM. We move data and schema; workflows are rebuilt natively in Twenty CRM.
EspoCRM
Source
Twenty CRM
Destination
Compatibility
8 of 12
objects map 1:1 between EspoCRM and Twenty CRM.
Complexity
BStandard
Timeline
4-6 weeks
Overview
Moving from EspoCRM to Twenty CRM is a migration between two open-source platforms at different stages of maturity. EspoCRM brings eleven years of development, an Entity Manager for no-code custom entity creation, and a REST API with a 200-record ceiling per request. Twenty CRM brings three years of active development, a modern TypeScript and PostgreSQL stack, a GraphQL-first API, and a native MCP server for AI agent integration on Cloud plans. The migration requires resolving EspoCRM's cross-referenced entity dependency graph, transferring filesystem-stored attachments from self-hosted instances, and rebuilding EspoCRM workflows and automations as Twenty workflows. We preserve custom entity metadata by exporting entityDefs before migrating records, and we flag WebSocket domain persistence issues that arise when EspoCRM was moved between servers without a full URL reconfiguration. Timeline ranges from four to eight weeks depending on entity count and custom object complexity.
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 Twenty CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
EspoCRM
Contact
Twenty CRM
People
1:1EspoCRM Contact records map directly to Twenty CRM People records. Email, phone, address, title, and all custom fields transfer 1:1. Multi-email fields in EspoCRM (where a Contact can have multiple email addresses) map to a primary email on the Twenty People record with secondary emails stored in a custom text field. Owner resolution uses email match against Twenty Members.
EspoCRM
Account
Twenty CRM
Company
1:1EspoCRM Account records map to Twenty CRM Company records. Website, industry, address, employee count, and annual revenue transfer. The domain field in EspoCRM becomes the website field in Twenty. Company is created before any People import so that the People→Company relationship is satisfied at import time.
EspoCRM
Lead
Twenty CRM
Person or Company (classification required)
1:manyEspoCRM Lead records have a status field that indicates whether the lead is new, assigned, in process, converted, or junk. Leads with status converted carry an ID pointing to the target Contact or Account and are migrated as People or Company records. Unconverted leads migrate as People with the original lead status preserved in a custom field for audit.
EspoCRM
Opportunity
Twenty CRM
Opportunity
1:1EspoCRM Opportunity records map to Twenty CRM Opportunity with amount, stage, probability, expected close date, and description fields preserved. The opportunity stage names are recorded in a custom field since Twenty uses its own stage vocabulary. We create the Opportunity records after Company to satisfy the CompanyId lookup.
EspoCRM
Lead Stage
Twenty CRM
Opportunity Stage
lossyEspoCRM pipeline stages map to Twenty Opportunity stages. We configure the Twenty opportunity pipeline with stages matching the EspoCRM stage names during setup. Probability values transfer as custom fields if the customer requires exact probability mapping for reporting.
EspoCRM
Case
Twenty CRM
Task or Note
lossyEspoCRM Cases (support tickets) have no direct Twenty CRM equivalent. Cases migrate as Tasks with the case number, priority, and resolution stored in custom fields, and the case conversation thread migrates as Notes attached to the Task record. The customer chooses whether to preserve Cases as Tasks or as a custom Case object created in Twenty's Data Model.
EspoCRM
Activity: Meeting, Call, Task
Twenty CRM
Task
1:1EspoCRM Activities (Meetings, Calls, Tasks) map to Twenty Task records. Meeting details (title, start time, end time, location) store in Task custom fields. Call duration and disposition store in custom fields. ActivityDate is set to the original EspoCRM timestamp to preserve timeline ordering.
EspoCRM
Activity: Email
Twenty CRM
Task
1:1EspoCRM Email activities migrate to Twenty Task records with the email body stored in the Task description field, sender and recipient stored in custom text fields, and the original timestamp preserved. Email threading and header metadata do not transfer as structured data.
EspoCRM
Document (Attachment)
Twenty CRM
Attachment
1:1EspoCRM Documents are stored as Attachment records linked to parent entities. On self-hosted instances, the actual file lives in data/files/ on the server filesystem. We extract referenced files during discovery, copy them to the migration staging environment, and re-upload them to Twenty via API after the parent record is created. CSV export alone does not capture file attachments; this is a parallel workflow to the database migration.
EspoCRM
User
Twenty CRM
Member
1:1EspoCRM User records map to Twenty Members. We resolve by email match. Any EspoCRM User without a matching Twenty Member is held in a reconciliation queue; the customer provisions the missing Member in Twenty before record migration resumes. Role and team memberships do not migrate and require manual reconfiguration in Twenty's settings.
EspoCRM
Custom Entity (Entity Manager)
Twenty CRM
Custom Object
1:1EspoCRM custom entity types created via Entity Manager map to Twenty CRM custom objects. We export the entityDefs metadata first to capture all field definitions and their types (multi-enum, currency, link-multiple, etc.), create the matching Twenty custom object and fields in Settings → Data Model before import, then migrate records using ID remapping tables to resolve any cross-entity lookups. Multi-enum fields exceeding 20 options in EspoCRM must be split into multiple multi-select fields or a single multi-select with a higher option cap set in Twenty.
EspoCRM
Campaign
Twenty CRM
Task (campaign tracking)
lossyEspoCRM Campaign records track marketing campaign metadata and target lists. Twenty CRM has no native Campaign object. Campaign metadata migrates as a custom object or as Tasks with campaign name, type, and status stored in custom fields. Target list membership (Leads and Contacts) does not migrate as structured relationships; we deliver a CSV of campaign-target mappings for the customer to rebuild manually in Twenty.
| EspoCRM | Twenty CRM | Compatibility | |
|---|---|---|---|
| Contact | People1:1 | Fully supported | |
| Account | Company1:1 | Fully supported | |
| Lead | Person or Company (classification required)1:many | Fully supported | |
| Opportunity | Opportunity1:1 | Fully supported | |
| Lead Stage | Opportunity Stagelossy | Fully supported | |
| Case | Task or Notelossy | Fully supported | |
| Activity: Meeting, Call, Task | Task1:1 | Fully supported | |
| Activity: Email | Task1:1 | Fully supported | |
| Document (Attachment) | Attachment1:1 | Fully supported | |
| User | Member1:1 | Fully supported | |
| Custom Entity (Entity Manager) | Custom Object1:1 | Fully supported | |
| Campaign | Task (campaign tracking)lossy | 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
Twenty CRM gotchas
Import order is enforced and critical
Export limited to 20,000 records and visible columns only
Soft-deleted records count toward uniqueness and trigger restores
API rate limits cap at 200 req/min on Organization tier
No native email sequences — follow-up cadences require external tools
Pair-specific challenges
Migration approach
Discovery and EspoCRM environment audit
We audit the source EspoCRM instance across all entity types, custom fields, Entity Manager metadata, attachment storage location (database or filesystem), active workflows and automations, and user role structure. We identify multi-enum fields with option counts, cross-entity relationships requiring dependency graph analysis, and attachment records needing filesystem extraction. The discovery output is a written scope document covering record counts per entity, custom entity dependency graph, and a list of workflows and integrations requiring manual rebuild.
Twenty workspace setup and data model configuration
We configure the Twenty CRM workspace before any data import. This includes creating custom objects matching EspoCRM Entity Manager entity types, adding custom fields with type-mapped Twenty field types, and inviting all team members who will be assigned as record Owners. Twenty requires all fields to exist before import; creating them first prevents validation failures during the CSV load phase. We also configure the Opportunity pipeline stages to match EspoCRM stage names.
Entity Manager metadata export and schema mapping
We export EspoCRM entityDefs metadata to capture all custom entity types, their field definitions, field types, and relationship configurations. This metadata drives the field-type mapping matrix that translates EspoCRM field types (multi-enum, currency, link-multiple) to Twenty equivalents. We also export a full record dump per entity type, paginated in chunks of 200 to comply with EspoCRM's API ceiling.
File attachment extraction from EspoCRM filesystem
For self-hosted EspoCRM instances, we identify all Attachment records and their corresponding filesystem paths under data/files/. We extract the referenced files, rename them with migration-safe identifiers, and stage them for upload to Twenty after their parent records are created. This step runs in parallel with the database extraction to avoid sequential delay.
Dependency-ordered migration into Twenty
We run migration in record-dependency order: Companies first, then People (Contacts and Leads), then Opportunities, then Activities and Notes, then Custom Entities last because they often contain lookups to standard objects. ID remapping tables track the relationship between EspoCRM record IDs and Twenty record IDs so that link-multiple and foreign-key references resolve correctly even when source and target IDs differ. After each phase, we emit a row-count reconciliation report before the next phase begins.
File attachment upload and association
After parent records are committed in Twenty, we upload the extracted files via Twenty's API, associating each attachment with the correct parent record ID using the ID remapping table. We verify that the attachment count in Twenty matches the attachment count discovered from EspoCRM.
Cutover, validation, and workflow rebuild handoff
We freeze EspoCRM writes during cutover, run a final delta migration of records modified during the migration window, then enable Twenty as the system of record. We deliver the EspoCRM workflow and automation inventory document to the customer's admin team with recommended Twenty equivalents for each. We support a one-week hypercare window for reconciliation issues. We do not rebuild EspoCRM workflows as Twenty workflows inside the migration scope; that work is documented separately for the customer's admin.
Platform deep dives
EspoCRM
Source
Strengths
Weaknesses
Twenty CRM
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 Twenty CRM.
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 Twenty CRM migration scoping. Not seeing yours? Book a call.
Walk through your EspoCRM to Twenty CRM 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 Twenty CRM
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.