Migrate from SuiteCRM to EspoCRM

How to move SuiteCRM records to EspoCRM using documented CSV import, what maps cleanly, what needs rebuilding, and what drives effort and risk.

On this page

Migrate from SuiteCRM to EspoCRM: what the move involves

Moving a SuiteCRM team to EspoCRM is a data and configuration remap, carried out through EspoCRM's documented CSV import, not an in-place upgrade. There is no supported path that converts a SuiteCRM instance into an EspoCRM instance, so the work is to export records from SuiteCRM, reshape them, and load them into a new EspoCRM installation in the right order. How much effort that takes depends mainly on the number of custom modules and on how many dropdown fields need translating, which is why the module inventory is the first thing to settle.

The most common source of errors is dropdown values. SuiteCRM's record export writes the ID of each dropdown option rather than its display label, so a status field that reads as a readable word in the interface arrives in the CSV as a code. EspoCRM's import expects the labels (or values) it knows for each enumeration field, so every dropdown in scope needs a translation table built from the SuiteCRM dropdown definitions and checked against the EspoCRM field options before any file is loaded. Confirm that every option ID in use has a matching EspoCRM option, and decide what happens to legacy values that have no equivalent.

Custom modules deserve the same discipline. Each one needs a decision about whether it becomes a custom entity in EspoCRM's Entity Manager, is folded into an existing entity, or is retired. Import in dependency order (accounts before contacts, contacts and accounts before opportunities and their relations), and use the import's duplicate matching and revert options for test loads. Run the whole sequence on a staging instance first, and confirm with your own records how many fields and relations each module carries, since that count, not the record total, drives the time required.

Which SuiteCRM objects map cleanly to EspoCRM

This table compares common SuiteCRM objects with their EspoCRM equivalents and marks whether each one moves through the documented CSV import path or needs rebuild work. Read it as a planning guide, not a field-level specification. Core records mostly move as CSV data, while custom modules, relationships, users and attachments usually need deliberate design. Confirm field-level mapping in your own instances before you commit to a plan.

SuiteCRM objectEspoCRM equivalentMigration noteImport path or rebuild
AccountsAccount entityExport from the SuiteCRM list view to CSV, then map columns to EspoCRM fields during import. Confirm field names and types in both instances.Documented import path
ContactsContact entityExport with record IDs and map relationship columns to account references. Check how email addresses and phone numbers are split.Documented import path
LeadsLead entityStatus values and lead sources are dropdown IDs in the export, so translate them to labels before import.Import path with label translation
OpportunitiesOpportunity entityImport after accounts and contacts so relationship fields resolve. Confirm amount, currency and sales stage mapping.Import path with label translation
Cases, calls, meetings, notes and tasksCase, Call, Meeting, Note and Task entitiesActivities often depend on parent records. Import parents first, then activities, and confirm which parent links survive.Import path, with checks on parent links
Dropdown fieldsEnum fields and option listsSuiteCRM exports option IDs, not display labels. Build a lookup table from each dropdown list and translate values before import.Translation work before import
RelationshipsLink fields and relationship definitionsMany-to-many links generally cannot be imported as simple columns. Plan how each link is recreated or populated through a secondary step.Rebuild work
Custom modulesCustom entities built in Entity ManagerEach SuiteCRM custom module needs a designed entity, fields, layouts and a mapping of its records. Its data is not a one-to-one copy.Rebuild work
Custom fieldsCustom fields added to existing entitiesField types, validation and layout placement differ, so confirm each custom field has a target before exporting.Rebuild work for unmatched fields
Users and teamsUsers, roles and teamsAccounts, passwords and roles are not carried by a records import. Recreate users and access model deliberately, and avoid assigning admin roles for daily work.Rebuild work
Attachments and documentsAttachments and file storageFiles are not part of a standard CSV import. Plan a separate transfer and confirm storage locations and permissions.Rebuild work

How the migration runs from inventory to decommission

The sequence moves SuiteCRM data into EspoCRM in an order that keeps relationships intact, tests every import on staging, and leaves a verified, archived SuiteCRM copy before anything is switched off. Each step produces a check the team can sign off before the next one starts.

  1. Inventory modules, fields and customizations

    Start by listing every SuiteCRM module in use, the fields each one carries, which dropdown lists are customized, and which custom modules hold business data. Confirm the export scope against your exact SuiteCRM version, since field availability and export lists depend on the release, and check the version against the SuiteCRM compatibility matrix. Record which records are active, which are archived, and which relationships link modules. The output is a signed inventory that maps every module to a target in EspoCRM or to a documented decision to leave it behind.

  2. Export each module with IDs and labels

    Export each module from the List View Actions menu in SuiteCRM. The export includes the record ID alongside the fields in the module's export list, and dropdown fields come out as option IDs rather than display labels. Keep the exported IDs, because they are what link child records such as contacts and opportunities to their parents. Store each file as UTF-8 CSV in a versioned folder. The check is that each file's row count matches the record count reported in SuiteCRM for the same filter.

  3. Translate dropdown IDs to labels

    Build a lookup table for every dropdown field, mapping each SuiteCRM option ID to the label it displays and to the matching EspoCRM enum value. Apply the table to the exported files with a script or spreadsheet, and flag any ID that has no match rather than guessing. Review the flagged values with the business owners of each list, because retired or renamed options often need a decision. The output is translated files plus a log of unmapped values, with the log closed before import.

  4. Map custom modules to EspoCRM entities

    For each custom SuiteCRM module, create a matching custom entity in the EspoCRM Entity Manager, then define its fields, types and layouts to match the exported columns. Decide how each relationship becomes an EspoCRM link, and confirm which fields need to be required or unique. Where a custom module holds logic in SuiteCRM, document the rule so it can be rebuilt with Formula Script or workflows rather than copied as code. The check is a field-by-field mapping sheet that the data owner has reviewed.

  5. Run a pilot import on staging

    Install a staging EspoCRM instance and import a small, representative subset of records in dependency order. Use the import dialog's field mapping and duplicate matching on chosen fields, and start with Create Only mode for a clean run. Confirm that links resolve, that dropdown values display correctly, and that record counts match the export. Use the reverting function on the pilot data to test that a bad batch can be removed cleanly. Repeat the pilot until a full run produces no unresolved links or unexpected duplicates.

  6. Import in dependency order

    Import the full dataset in the order that keeps references valid: users and teams first, then accounts, then contacts, then opportunities, and finally the activities linked to those records. Create each parent before importing its children, so each child can link to an existing record. Larger files can be processed through cron so the import does not depend on a browser session. The check is a reconciliation report per entity showing imported, updated, skipped and failed counts, with every failure explained.

  7. Run a parallel period and cut over

    Keep SuiteCRM read-only or running alongside EspoCRM for an agreed period, so teams can compare records and confirm that daily work runs correctly in the new system. Reconcile changes made during the parallel period through a final delta import, using Update Only or Create and Update modes with matched IDs. Confirm user access, role permissions and integrations before the switch. The cutover is complete when the business owners sign off the reconciled counts and the final delta has been applied.

  8. Archive SuiteCRM and decommission

    Before shutting SuiteCRM down, take a full archive of its files and database, and store it under the retention rules your organization sets. Confirm that the archive can be restored by testing a restore to a separate environment, and document where it is kept and who can access it. Only then remove SuiteCRM from production, revoke its users and integrations, and update DNS and bookmarks. The output is a recorded decommission with a verified archive and a closed migration log.

Exporting SuiteCRM records and translating dropdown IDs

The central risk in this export is that SuiteCRM writes dropdown values as option IDs, not display labels. According to the SuiteCRM record management documentation, the list view export includes the record ID alongside the fields in the module's export list, and each dropdown field contains the ID of its option. EspoCRM's CSV import will not recognize those IDs as the values users see, so a Status or Lead Source column imported as-is would either fail validation or load values nobody can read. Before any file is prepared, the team should export one module, open the CSV, and list every enum field that appears in it. For each of those fields, build a lookup table that maps each SuiteCRM option ID to its label, using the dropdown definitions from the SuiteCRM instance itself. Confirm the mapping against each field's options in the EspoCRM Entity Manager, because labels that do not match an existing EspoCRM option need a decision: add the option first, or map to the closest existing value.

Keep the original SuiteCRM record ID in the EspoCRM record as well. Create a dedicated text field on each imported entity, for example named legacySuiteId, and populate it from the exported ID column. This field does three jobs. It lets you rebuild relationships in a second pass, because a contact can be linked to an account by looking up the account whose legacy ID matches the foreign key in the source data. It supports duplicate matching in the EspoCRM import, so a re-run in Create and Update mode updates existing rows rather than creating copies. It also gives you a traceable reference when someone asks where a record came from. Mark the field as not editable by standard users and consider making it indexed, so lookups stay fast on larger modules. Agree with the business owners whether this field stays in production or is removed after validation, since that decision affects reporting and data retention.

Test the export and lookup on a copy of the data before the full run. Use the SuiteCRM staging instance described in the migration documentation, not production, and confirm that the record counts per module match what the team expects. Check dates and currency fields as well as dropdowns, since their formats also differ between systems and should be verified before import. The result of this step is a repeatable set of lookup tables and a documented field mapping that the import run can reuse, so that corrections are made once in the mapping rather than by hand in each CSV.

Documented import paths for EspoCRM

EspoCRM offers two documented ways to load records: the CSV import in the user interface and the REST API for scripted loads. Both need the target entities, fields and link structure to exist before the first row is loaded, so the choice between them depends on file size, how often you will repeat the load and who will run it.

Import modes for CSV files

The CSV import offers Create Only, Create and Update and Update Only modes. For a SuiteCRM 7 to EspoCRM move, Create Only suits a first load into empty entities, while Create and Update suits a second pass that adds fields or relationships to records already loaded. Choose the mode per entity and confirm it against the record IDs you plan to keep as external references, since the mode decides whether a rerun creates duplicates.

Field mapping and option values

The import maps CSV columns to entity fields one by one. SuiteCRM exports dropdown options as internal IDs, so the mapping step is where those IDs must already be translated into the labels or enum values defined in EspoCRM. Check every enum, multi-enum and link column against a sample file before running the full load, because a mismatched value can fail silently in a single field.

Duplicate matching on chosen fields

Duplicate matching lets the import find existing records by fields you select, such as an external SuiteCRM record ID stored in a custom field or an account identifier. Store the legacy ID on every migrated entity so that reruns and later relationship imports can match reliably. Confirm which fields are unique in your data, since matching on a name or email alone often pairs records that only look alike.

Cron execution for large files

For large files, the import can run idle through cron rather than inside a browser session, so long loads do not depend on an open window. This requires cron to be configured on the server before the migration starts. Ask your team or partner to confirm the expected row count per file and to test the cron job on staging, since the run time and the number of files depend on the volume of each module.

Reverting imported records

The import can revert records created by a specific run. Use this to back out a failed batch before retrying, rather than deleting rows by hand in the database. Reverting only covers records created through that import, so records edited by a later run or by users are not restored automatically. Keep the import log and a SuiteCRM export for each entity as the fallback.

REST API for scripted loads

For high volumes or repeatable loads, the REST API can create records from a script. Use a dedicated API user with a role limited to the entities being loaded, and choose HMAC authentication, which the EspoCRM docs describe as the most secure option. Basic authentication is not recommended. Custom entities must exist in the Entity Manager with their fields before the script starts, so schedule that work before the first API call.

Mapping SuiteCRM custom modules to EspoCRM custom entities

A custom module that holds only text, number, date and checkbox fields maps most directly. In EspoCRM you create a matching custom entity in the Entity Manager, define each field with a type that fits its data, and then arrange the detail and list layouts. The data itself moves through the CSV path: export the module from SuiteCRM, translate any dropdown IDs, and import into the new entity in Create Only mode for the first load. Because no logic depends on these fields, the main work is naming and typing them consistently so the import mapping stays simple.

  • Field types first: Choose EspoCRM field types before importing, since changing a type later can strand existing values.
  • Layouts after data: Build the detail and list layouts once the fields exist, then confirm that every imported column is visible to the users who need it.
  • Naming discipline: Use one consistent naming convention for entity and field names so mapping files can be reused across modules.
  • Test imports on a copy: Run the first import against a staging instance and check a sample of records field by field.
  • Keep the source export: Retain the original SuiteCRM CSV files so a failed mapping can be corrected and rerun.

Before sign-off, ask your team to confirm the field list for each module against the SuiteCRM Studio definitions and the exported row counts.

Moving SuiteCRM logins and integrations to EspoCRM

Sign-in is the part of a SuiteCRM to EspoCRM move that most often has to be rebuilt rather than copied, because the two products authenticate users differently. SuiteCRM 8 can use LDAP, enabled with AUTH_TYPE=ldap, or SAML, enabled with AUTH_TYPE=saml. EspoCRM documents OpenID Connect sign-in since version 7.3, with optional user creation on first login, mapping of identity provider groups to EspoCRM teams, backchannel logout and a fallback login method. It also documents LDAP authentication, including Active Directory and OpenLDAP. Start by recording which method your SuiteCRM instance uses today, which identity provider serves it, and which groups or attributes decide who sees which records, because those choices determine whether OIDC or LDAP is the better match in EspoCRM.

Several behaviors do not carry across automatically. EspoCRM's own two-factor authentication is not compatible with OIDC, so if your identity provider currently enforces MFA for SuiteCRM, confirm that the provider handles it for every EspoCRM login path, including the fallback method. Do not assume SAML logout behavior transfers either: SuiteCRM's 8.7.0+ SAML implementation does not support IdP-initiated logout or POST binding to the logout service, so ending a session at the identity provider does not end the SuiteCRM session. Test what happens to an active EspoCRM session when a user is disabled at the identity provider, and decide how quickly that must take effect under your policy.

Confirm each integration with EspoCRM and with your identity provider before cutover, not from this page alone. Ask the identity provider team which claims or groups they will send, whether first-login user creation should be enabled or users should be pre-provisioned, and how the fallback login will be restricted. Keep an administrator path that does not depend on the identity provider, and test it. Plan a parallel test with a pilot group of named users, verifying team membership, role assignment and logout on each side, and record the results so the cutover decision rests on evidence.

What usually goes wrong in a SuiteCRM to EspoCRM move

Most failed SuiteCRM to EspoCRM moves fail at the seams: how values are translated, how records are linked, and how people are mapped to the data they own. The cards below cover six risks that connect the export, import and cutover steps, each with the check that prevents it.

Dropdown IDs imported as raw values

SuiteCRM exports the ID of each dropdown option rather than its display label, so a naive CSV import can write strings such as internal option keys into EspoCRM enum fields. Build a lookup table from each SuiteCRM dropdown list to the matching EspoCRM enum values before the first import. Then run a test import on a few records and check that every select field shows a readable label, not a code.

Lost relationships from missing source IDs

Contacts, accounts and opportunities reference each other by record ID, and those IDs only resolve if the export included them. If a module's export list omits the ID field, the relationship columns in later imports point at nothing. Confirm that the record ID is in every export file and keep a mapping of old ID to new EspoCRM ID for each module, so child records can be linked in dependency order.

Duplicate records on re-import

Running an import twice, or re-running a partly failed batch in Create Only mode, creates a second copy of every record. Choose a duplicate matching field and the Create and Update mode for re-runs, and test the match on a sample first. Keep the import reversible: EspoCRM can revert imported records, so note each batch's results before moving to the next.

Undocumented customizations in legacy folders

Custom code and templates in SuiteCRM often live outside the module framework, including files under the public and legacy folders. The SuiteCRM migration guidance warns that the migration may remove non-core files under public/legacy, so custom behavior can disappear without an error. Inventory every custom file and field before starting, decide which logic must be rebuilt in EspoCRM, and keep a full file and database backup on a staging copy.

User and team mapping errors

Record ownership, assigned users and team access all depend on users existing in EspoCRM before records are imported. If a SuiteCRM user maps to the wrong EspoCRM user, or to none, records land with the wrong owner and visibility rules hide them from the people who need them. Create a user and team mapping sheet signed off by the business owner, create the users first, and check ownership on a sample of accounts in each team.

Cutover without a parallel period

Switching users to EspoCRM on the same day the final import runs leaves no time to find gaps in the data, and SuiteCRM changes made during the final window may never reach the new system. Plan a parallel period in which both systems stay available, define which system is the record of truth for each day, and run a reconciliation of record counts and key fields before the old system is set to read-only.

What drives the cost and duration of the migration

This table lists the factors that change how much work a SuiteCRM to EspoCRM move takes, how each one affects effort, and what to request in a written quote. No price or duration is given here, because a quote follows the written scope. Read the rows as the questions your team should answer before asking for one.

DriverEffect on effortWhat to ask for in a quote
Number of custom modulesEach SuiteCRM custom module needs an EspoCRM custom entity, layouts and field mapping, so effort rises with module count.A module-by-module mapping table showing the target entity, fields and any logic to rebuild.
Record volume per moduleLarge exports need batching, idle execution through cron and checks after each run, which lengthens verification.The batch approach, the expected run order and how reverts are handled for large files.
Number of dropdown fieldsEach dropdown exports as an option ID, so every list needs a translation table from ID to label before import.Confirmation that every dropdown is translated and a list of options that have no label in the source.
Relationship depthParent and child links must be imported in dependency order, and link fields must be resolved to EspoCRM record IDs, which adds steps and testing.An import sequence that shows which records load first and how relationships are matched.
Attachments and documentsFiles are exported separately from record CSVs, so they need their own transfer path and link checks.The method for moving files, the storage location in EspoCRM and a check of linked records afterward.
Customizations and logicCustom code, workflows and business rules in SuiteCRM are not carried over by CSV, so each one is rebuilt or retired by hand.An inventory of customizations with a decision for each: rebuild in Formula Script, rebuild in a workflow, or retire.
Identity integrationMoving SuiteCRM LDAP or SAML sign-in to EspoCRM requires separate setup and testing, and logout behavior must be checked.The identity provider, the planned OIDC or LDAP configuration and the test cases for sign-in and sign-out.
User and team structureUsers, roles and teams must be recreated and matched to records, and ownership fields must be checked after import.A role and team design, the user list to be created and how ownership is assigned on imported records.
Parallel run lengthRunning both systems side by side adds reconciliation work and a period of duplicate data entry, both recurring until cutover.The length of the parallel run agreed in writing, who reconciles data and the cutover checklist.
TrainingSales, service and marketing staff need instruction in the new layouts, workflows and logic, which is a one-time cost.Training scope, the number of sessions, the audience and whether materials are handed over.

Questions buyers ask before moving from SuiteCRM to EspoCRM

How much effort does a SuiteCRM to EspoCRM move take?

The effort depends mostly on how much of your SuiteCRM setup has to be rebuilt rather than carried across. Export and import of standard module records is the simpler part. The larger items are custom modules that must be mapped to custom entities, dropdown option IDs that must be translated to labels before import, relationships between records, attachments, and the workflows and integrations that depend on the old data model. Ask for a module inventory with record counts and a list of customizations before accepting any estimate, because those two lists drive most of the work. A fixed-scope quote follows from the written scope.

How long does the migration run, and what sets the timeline?

The timeline is set by the number of modules in scope, how clean the source data is, how many custom modules need a designed entity model, and how many people must review and sign off each stage. Staging rehearsals add time, and so does a parallel run. Timelines are agreed in the written scope, so ask for the planned phases, the review points and the dependencies each phase has on your teams. Ask your provider which of these items they have not yet measured in your environment, since that is where schedules usually slip.

What must our team provide before the migration starts?

Your team needs to provide a module inventory, named data owners for each module, access to a staging copy of SuiteCRM, and a decision-maker who signs off each mapping and each import. Data owners confirm which records are current, which dropdown labels are still in use, and which duplicates can be merged. Sign-off should cover the field mapping, the import order and the cutover date. Without named owners, mapping questions tend to stall until someone makes the call late in the project.

Can our internal team run the migration without a partner?

Yes, a capable internal team can run a migration like this if it has someone who knows the SuiteCRM data model, someone who can design EspoCRM entities and layouts, and time to test on staging. The work is mostly careful mapping, scripting of the translation steps and disciplined testing, not a special product. The risks are the usual ones for a first migration: missed customizations, unverified duplicates and cutover mistakes. Compare your team's capacity with the module inventory and the testing plan before deciding, and ask a partner to quote only the parts you want to hand over.

Can SuiteCRM 8 data be moved to EspoCRM by upgrading?

No. Moving data from SuiteCRM to EspoCRM is a data migration, not an upgrade, because the two products are separate applications with different schemas. SuiteCRM's own documentation describes moving from SuiteCRM 7 to 8 as a migration too, where a new environment is set up and the data is moved into it. For this project, export from SuiteCRM, translate the values, and import into a new EspoCRM instance. Keep the SuiteCRM source read-only until the import is verified.

Do we need a parallel run after cutover?

A parallel run is not always required, but many teams keep SuiteCRM available in read-only mode for a period so staff can check records against the source. Whether you need one depends on how much daily work depends on SuiteCRM, how many integrations feed it, and how confident the reconciliation is. Plan the reconciliation checks in advance: record counts per module, sample record comparisons, relationship checks and the reverting option in the EspoCRM import tool, which can undo a bad import. Confirm the retention period for the old SuiteCRM instance with your compliance owner.

What do EspoCRM licensing and hosting cost?

EspoCRM is licensed under AGPL-3.0 and the open-source edition can be downloaded and self-hosted for free, according to the EspoCRM pricing page. Self-hosting still carries costs for servers, the database, backups, TLS certificates, maintenance time and any implementation work you hand to a partner. If you prefer the vendor's hosted service, EspoCRM Cloud is priced per user per month: 15 US dollars on the Basic plan (minimum 3 users), 25 dollars on Enterprise (minimum 5 users) and 69 dollars on Ultimate (minimum 10 users), with the Advanced Pack included in all cloud plans, according to the same pricing page. Confirm current prices on the vendor page, and ask any quote to separate one-time implementation work from recurring hosting and support.

How DeployOpen works on this

DeployOpen starts by mapping your SuiteCRM 7 or 8 modules, dropdown lists and custom modules to EspoCRM entities before any data moves. The work is delivered in your own infrastructure, with a written scope, tested import sequences and documented handover so your team can run the EspoCRM instance afterward.

How we scope

  • Inventory of SuiteCRM modules, custom fields, dropdown lists and record volumes in the written scope
  • Mapping of each custom module to an EspoCRM custom entity, with the dropdown ID to label translation table
  • Confirmation of your SuiteCRM version, since 7 to 8 is a migration to a new environment, not an upgrade

How we build

  • Staging EspoCRM instance in your infrastructure, with SuiteCRM exports and a full file and database backup taken first
  • Import runs in dependency order (accounts, contacts, opportunities, related records) using Create Only or Create and Update modes
  • Reconciliation of record counts and sample records per module, with a documented revert step for each import batch

How we hand over

  • Written record of the field mapping, translation tables, import order and any excluded data
  • Runbook covering the cutover sequence, rollback steps and post-migration checks your team performs
  • Walkthrough with your administrators and the training they need to maintain the new entities and layouts

How we support

  • Post-cutover support available as a retainer for fixes, questions and follow-up imports
  • Support scope agreed in writing, covering the EspoCRM version and extensions in your environment
  • Option to schedule later review of additional SuiteCRM data or modules not in the original scope

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.