Section 01
Why teams migrate to Twenty CRM
The four shapes a Twenty CRM migration takes, and what makes the platform easier — or harder — than the category average.
Twenty was founded by Charles Bochet and Félix Malfait, launched publicly through Y Combinator (S23), and ships under an AGPL-3.0 licence with a self-hostable codebase on GitHub 112. The team positions Twenty as a modern, open-source alternative to Salesforce and HubSpot — built from a clean slate in TypeScript, NestJS, React and PostgreSQL.
The typical Twenty customer is a developer-led startup, a SaaS company, or a small-to-mid-market team — 5 to 100 users — that wants Salesforce-depth customisation without the licensing cost, or a team replacing Zoho or HubSpot to escape contact-tier billing and vendor lock-in. Compared with Salesforce, Twenty positions on no governor limits, no per-seat licence and a metadata-driven data model that lets you build custom objects the same way the platform builds standard ones.
The shapes of migration that actually land on Twenty tend to fall into four patterns. First, Salesforce or HubSpot exits, driven by total cost of ownership and a desire for data ownership — practitioners cite $9/user Cloud or $0 licensing for self-host versus $25–$165/user/month on legacy CRMs. Second, Zoho consolidations, where a small team has hit reliability or customisation limits and wants a cleaner data model 28.
Third, homegrown or vibe-coded CRM replacements — teams that built something in Lovable, Airtable or Notion and have outgrown it, but still want full control over the schema 29. Fourth, self-hosted CRM moves from EspoCRM, SuiteCRM or Dolibarr when a team wants a modern stack (React, Postgres) over PHP.
Each shape has a different difficulty profile: a Zoho migration usually has clean object parity but messy custom-field labels, while a Salesforce migration drags Apex, Flows and validation rules that do not move across at all.
What makes migrating *to* Twenty easier than the category average is its data model. Custom objects use the same treatment as standard ones — there is no Enterprise gate and no extra licence. Self-host gives you direct PostgreSQL access for power-user bulk imports, which is a path most managed CRMs simply do not offer 38.
What makes it harder than the average is that Twenty is still an actively evolving project. The People and Companies standard objects ship with a narrower set of pre-built fields than HubSpot or Salesforce, which means every new workspace spends 30 to 60 minutes creating basic fields before the first import 41.
The CSV import path was capped at 2,000 rows in early 2025 and was raised to 10,000 in later releases — the limit is moving, but it is still much tighter than the row caps you may be used to on HubSpot or Salesforce 68.
Views, workflows and permissions do not import — they are rebuilt manually after the data lands 12. Teams that scope for that rebuild work up front finish on time; teams that assume parity with Salesforce or HubSpot do not.
Twenty's open data model removes lock-in; what it does not remove is the rebuild work for views, workflows and sequences.
Section 02
The Twenty CRM data model you need to map into
Standard objects, custom objects via metadata UI, junction relations, and the upsert keys you'll wire on every field — the destination schema decoded.
Twenty's CRM is built around a small set of standard objects plus an unrestricted custom-object layer driven from metadata tables 36. Workspaces are the multi-tenant boundary — every object, field and record lives inside a workspace, and one Twenty deployment can host many.
Before you can map a field on the source side, you need to know exactly which destination object the row belongs on, what fields it requires, and which value will serve as its upsert key. The table below summarises the standard objects in a Twenty workspace and the additional ones you typically end up creating.
| Object | Stores | Required on import | Tier |
|---|---|---|---|
| People | Individuals — contacts, leads, partners | Name (first/last); email recommended as unique key | Standard, all deployments |
| Companies | Organisations associated with people and opportunities | Name; domain recommended as unique key | Standard, all deployments |
| Opportunities | Deals in a sales pipeline | Name, stage, company or contact association | Standard, all deployments |
| Notes | Free-form notes attached to people, companies, opportunities | Title or body, target record association | Standard, all deployments |
| Tasks | To-dos and action items linked to records | Title, due date optional, assignee | Standard, all deployments |
| Workspace Members | Users in the workspace; referenced as owners/assignees | Email; must exist before import to bind ownership | Standard; provision before data |
| Custom Objects | Anything else — Projects, Subscriptions, Volunteers, Listings | Define in Settings → Data Model before importing records | Unlimited; same treatment as standard |
| Junction Objects | Many-to-many connectors between two objects | Enable Junction Relations in Settings → Updates → Lab | Standard, all deployments [42] |
People can use email as the unique identifier — Workspace Members are also addressable by email, which is how you bind ownership during a CSV import 3. Companies are most reliably matched on domain in the format https://acme.com (Twenty stores the full URL form and rejects acme.com or www.acme.com as not matching) 3.
Opportunities, custom objects and any other object without a natural key should use Twenty's internal id (UUID) as the upsert key. You can either let Twenty assign IDs and store them back in the source, or generate UUIDs in the source and pass them in. Re-importing a CSV with previously defined IDs is supported but has known edge cases when columns are omitted 33. Plan the unique-key strategy on day one.
Once you import, Twenty validates each row against the field schema before committing — errors highlight in yellow in the UI and you can fix them inline before the import is confirmed 22. Custom field types determine validation and storage; the catalogue below covers what you can model and the limits you need to plan around.
| Field type | Limits | Notes |
|---|---|---|
| Text / Long Text | Postgres text (effectively unbounded) | Long Text used for multi-line; no native rich-text yet 33 |
| Number | Integer or decimal | Currency is a separate type carrying a currency code |
| Date / Date & Time | ISO-8601 | Date & Time required for activity timestamps |
| Select (single) | User-defined options | Imports must use internal option names, not display labels 322 |
| Multi-Select | User-defined options | Multiple values per cell; round-trip caveat on overwrite 14 |
| Email / Phone / Domain / Links | Composite types — primary + additional | Use Email for People; Domain for Companies |
| Relation | Many-to-one or one-to-many | Reference parent by id or unique field (email/domain) 3 |
| JSON | Postgres JSONB | Structured data store; not formula-aware |
| Rating / Boolean / Currency | 1–5 / true-false / decimal+code | Boolean must import as TRUE/FALSE uppercase 3 |
| Computed / Formula | Not yet supported | Open feature request — rebuild as workflow or app-side logic 11 |
Relationships in Twenty are modelled as relation fields on the object. Many-to-many is supported via a junction object pattern — you create an intermediate object (for example, Project Assignment) with two many-to-one relations, then enable the Junction Relations lab toggle to render linked records directly instead of the intermediate row 42.
There is no native master-detail cascade-delete: deleting a parent does not automatically delete children. If your source platform relied on cascade semantics, reproduce them in a Twenty workflow on the parent's Deleted event, or rely on the underlying Postgres foreign-key behaviour when self-hosting with a custom schema.
Section 03
Pre-migration prep — the work before you touch Twenty CRM
What must be true on the source, the destination, and across the team before the first row hits the import wizard.
The single best predictor of a clean Twenty migration is how much work you do on the source side before the first import button is pressed. Twenty's own documentation frames migration as 'an opportunity for a fresh start — don't bring over clutter' 12, and the import wizard is unforgiving about fields that do not yet exist on the destination object.
Fields must exist before import. Uploading a CSV creates records but does not create fields.
Treat the source export as raw material that needs to be shaped to Twenty's expected formats — email lowercased, phone normalised to E.164 with country codes, domains rewritten to the https://acme.com form, select values converted to internal option names, dates rewritten to ISO-8601, booleans uppercased to TRUE/FALSE 3.
Source-side prep
- Audit and dedup the source database before export. Twenty does not ship pre-built dedup tooling outside of a manual Merge Records action introduced in 1.3.0, so duplicates landing during import become a manual cleanup task.
- Decide what to leave behind — outdated contacts with no activity in 2+ years, unused custom fields, test data, opt-outs. Twenty's docs explicitly recommend pruning before migration 12.
- Normalise emails to lowercase and trim whitespace. Email is the natural unique key for People and Workspace Members.
- Rewrite domains to the canonical
https://domain.comform. Twenty stores domains with the URL prefix and will not matchdomain.comorwww.domain.com3. - Convert select-field display labels to internal option names for every dropdown — pipeline stages, status fields, custom enumerations. Enable Advanced Mode in Twenty Settings to see the internal name for each option 2226.
- Generate or preserve a stable external ID — either keep the source platform's primary key in a custom field, or pre-allocate UUIDs that will become Twenty's
idon import.
Destination-side prep
- Decide self-host vs. Twenty Cloud before you provision. Self-host runs on Docker Compose with PostgreSQL and Redis, needs at least 2 vCPU and 4 GB RAM, and gives you direct database access. Cloud (
app.twenty.com) bills at $9/user/month and removes the infrastructure burden. - Stand up a test workspace as a sandbox. Twenty's free tier and self-host model make this trivial: spin up a parallel instance, dry-run the import, validate, then re-run against the production workspace.
- Invite users before importing data. Twenty's docs are emphatic — if your import references owners or assignees by email, those users must exist in the workspace first, otherwise relations cannot be mapped 83.
- Pre-create every custom object and custom field under Settings → Data Model. The CSV import creates records, never fields — uploading a column for a non-existent field returns an unmapped column error 38.
- Configure select-field options with the internal option names you plan to use in your source-side transformation, not the human display labels.
People prep
Cutover only works if humans cooperate. Lock down a source-system freeze window — typically 24 to 72 hours — and communicate it to every department that touches the CRM. Train sales reps on Twenty's table and Kanban views, the Command Menu (the ⋮ icon used to trigger imports), and the workflow rebuild plan.
A typical small-team Twenty migration runs one to two business days end-to-end; a 50,000-record consolidation with custom objects and historical activities runs one to two weeks of elapsed time. Build the human runway accordingly.
Section 04
Import mechanisms: CSV wizard and direct database access
Two paths in, each with different limits and shapes. Picking the wrong one is how a Twenty migration stalls at scale.
Twenty exposes load paths whose right choice depends on dataset size, object mix, and whether you need to re-run idempotently. The CSV import wizard covers most one-shot migrations under 50,000 records. Direct PostgreSQL access on self-host adds a path for power users prepared to bypass the application layer entirely 38.
CSV import wizard
The native import lives in the Command Menu — open the object's table view, click the ⋮ icon top right, then Import records 18. Supported formats are CSV (recommended), XLSX and the legacy XLS 13. Each file must contain only one object type — People in one file, Companies in another, Opportunities in a third 18.
Steps: download the template to confirm column names, upload the CSV, map columns to Twenty fields, review errors highlighted in yellow and fix them inline in the UI, then confirm the import 22. Pre-import validation runs *before* the records are written, so you can correct a malformed boolean or an unrecognised select value without polluting the workspace 22.
Limits: 10,000 records per file in current releases, up from the original 2,000-row cap 68. Twenty's documentation recommends splitting 10,000–50,000-record loads into multiple files 38151.
Direct PostgreSQL (self-host only)
Self-hosted Twenty exposes its underlying Postgres database. For power-user bulk imports — hundreds of thousands of records, custom-object loads with complex relations, or migrations where you want SQL-level transactional control — connecting directly to the database and writing rows is the fastest path 38. The trade-off: you bypass Twenty's validation layer, the Metadata schema mapping, and the application-side change events, so workflows will not fire for inserts done this way.
Under 2,000 records → CSV wizard. 2,000–10,000 → single CSV file. 10,000–50,000 → split CSVs. Self-host plus 100k+ rows → direct Postgres after a sandbox dry run.
Section 05
Mapping your data into Twenty CRM
The longest section — because field mapping is where almost every Twenty migration that fails actually breaks.
Mapping is where every migration earns its scars. The schema decisions you make in your mapping spreadsheet determine whether Kanban views work on day two, whether workflows fire correctly on day five, and whether your team trusts the data on day thirty.
Work object by object, top to bottom of the import order specified in Twenty's own documentation: Companies first (no dependencies), then People (depend on Companies), then Opportunities (depend on Companies and People), then Notes and Tasks (depend on the records they attach to), then Custom Objects 83151.
Companies
Common source → Twenty Company mapping
- account_name / company_name→name
Required
- website / domain→domainName
Format strictly as
https://acme.com— notacme.comorwww.acme.com3 - industry→industry (or custom Select field)
Map source labels to Twenty internal option names; create the field first
- annual_revenue→annualRecurringRevenue (Currency)
Strip currency symbols; provide value plus currencyCode (USD/EUR)
- employees→employees (Number)
Integer; strip commas
- owner / account_owner→accountOwnerId (relation to Workspace Members)
Map by user email; the user must exist in Twenty first 83
People
Common source → Twenty People mapping
- first_name / last_name→name.firstName / name.lastName
Composite Name field; supply both sub-keys
- email→emails.primaryEmail
Lowercased; recommended unique key
- phone→phones.primaryPhoneNumber + primaryPhoneCountryCode
Normalise to E.164 before import
- job_title→jobTitle
Single-line text
- company / organisation→companyId (relation)
Use
companyDomaincross-reference (https://acme.com) on the People CSV 83 - linkedin / twitter URLs→linkedinLink / xLink (Links)
Composite type — primary URL plus optional label
- owner→createdBy / pointOfContact relation
Use user email; pre-provision users 83
Opportunities and pipelines
Recreate every pipeline-equivalent stage in Twenty before importing Opportunities. Twenty currently models pipeline as the stage Select field on the Opportunity object — Kanban view groups records by stage 153. Multiple pipelines on one object (record types in Salesforce parlance) are an open community request, not native today 153, so teams consolidating multiple source pipelines typically either: (a) keep them as separate Select options on a single Opportunity object, or (b) create one custom object per pipeline for full isolation.
Common source → Twenty Opportunity mapping
- opportunity_name / deal_name→name
Required
- stage / pipeline_stage→stage (Select)
Use internal option name, not display label; create option first 22
- amount→amount (Currency)
Provide amountMicros + currencyCode (USD, EUR)
- close_date→closeDate
ISO-8601 date
- primary_contact→pointOfContactId (relation to People)
Cross-reference by email or
id - account / company→companyId (relation to Companies)
Cross-reference by
domainName(https://acme.com) orid - owner→Workspace Member relation
Map by user email; pre-provision
Custom-field mapping strategy
Resist the urge to map every source custom field one-to-one. Migrate only the custom fields used by an active process, view or report in the last 12 months. Twenty's documentation explicitly endorses this: 'don't bring over clutter — what to leave behind: outdated contacts, duplicate records, test data, unused custom fields' 12.
For Select fields whose source values do not match the destination, either: (1) extend the destination Select with the missing internal option names, (2) collapse adjacent values during transform, or (3) introduce a parallel Text field that holds the legacy value verbatim.
Formula and rollup fields do not import and are not yet supported as a Twenty field type 11 — rebuild the calculation in a workflow that fires on record-write, or compute it in the source layer and store the result in a static Number field.
Historical activities — notes, tasks, emails, calls
Twenty has Notes and Tasks as first-class standard objects 32. Historical free-form notes from a source CRM should be transformed into Notes records, each with a body, a createdAt timestamp, and a relation to the target record (Person, Company or Opportunity). Source activities of type Task become Twenty Tasks with dueAt, assigneeId and the same target-record relation.
Historical emails and calendar events are handled differently. Twenty's email and calendar sync (Google or Microsoft, with SMTP/CalDAV for others) is configured per-workspace-member under Settings → Accounts and runs forward-looking 102. There is no bulk historical-email importer in the way HubSpot ships one; if you need to preserve old email threads as activities, the working pattern is to transform each email into a Note record attached to the matching person, with the email body as the Note body.
Rich-text formatting in source notes is currently lossy — Twenty has an open request for a rich-text field type and the existing Long Text type renders as plain text 103. Convert HTML email bodies to plain text or Markdown before import.
Files and attachments
Attachments do not import via the CSV path. Twenty supports attachments on People, Companies, Notes and Tasks (the Attachments feature on Opportunity standard object is an open issue 121) — files are uploaded through the UI, then linked to the parent record.
For large attachment estates the working pattern is the same as Twenty itself recommends for most file storage: keep originals in S3, Google Drive or your storage provider, write a deep link into a custom Links field on the Twenty record, and only inline-upload the most recent or most-referenced subset. Self-hosted Twenty uses local volume storage by default (STORAGE_LOCAL_PATH=/data/twenty) with S3 configurable as an alternative 100.
Audit trail, ownership and original timestamps
Standard createdAt, updatedAt, createdBy and the internal id UUID are Twenty-managed system fields. The CSV path stamps createdAt to import time; if you need to preserve the original audit trail, the pattern is to create two custom Date & Time fields per object — *Legacy Created At* and *Legacy Updated At* — and populate them from the source export.
Owner assignment during import works only if the Workspace Member email exists at the moment of import; rows whose owner cannot be resolved import without an owner relation set, which silently breaks downstream owner-based workflows 83.
Audit-trail granularity has historically been a community concern — earlier releases lacked a built-in action history visible to admins 132. Newer releases ship a per-record activity log, but for compliance-grade audit trails on a self-host deployment, the durable answer is Postgres-level logging or a downstream warehouse stream rather than reliance on the application UI alone.
CRM-specific: lead scoring, sequences, email/calendar sync
Lead scoring as a first-class feature does not exist in Twenty — there is no scoring rule builder analogous to HubSpot Score or Salesforce Einstein Lead Scoring. The working pattern is a custom Number field (leadScore) updated by a Twenty workflow on record events.
Sequences and cadences are not native. Practitioners migrating from Outreach, Salesloft, HubSpot Sequences or Pipedrive Smart Docs need a different model — the workflow builder can chain wait-steps and task creations but lacks the cadence ergonomics of dedicated tools 30. For teams that depend on sequences, plan to pair Twenty with an external cadence tool, or wait on the workflow roadmap.
Email and calendar sync for ongoing forward-looking activity is configured per Workspace Member under Settings → Accounts with Google, Microsoft, or SMTP/CalDAV 102. Do not enable sync during the import window or you will get a flood of duplicate Notes as the connector backfills against the same people you are loading.
Section 06
The pitfalls that derail Twenty CRM migrations
Failure modes ranked by impact, each tied to the exact Twenty mechanism that breaks.
High impact
Custom fields not created before import
Twenty's CSV import creates records, not fields. Upload a file with a column for a non-existent field and the importer leaves you with no place to map it — the column shows up as unmapped and the data is dropped on confirm. The fix sits in the documentation as a Warning callout: 'Fields must exist before import. Create all custom fields in Settings → Data Model before importing.' Build the destination schema first, validate by downloading the template CSV, then load data 3878. 38
High impact
Owner / assignee users not invited before data lands
If your import references owners, account owners or assignees by email, those users must exist in Twenty before the import runs. Twenty's own Warning: 'Invite users BEFORE importing data. If your data includes user references, those users must exist in Twenty before import. Otherwise, those relations cannot be mapped.' Rows whose owner email cannot be resolved import with no owner set, which silently breaks every owner-filtered view and workflow downstream 83. 83
High impact
Domain format mismatch causes duplicate Companies
Twenty stores Company domains in URL form — https://acme.com. Import a CSV with acme.com or www.acme.com and Twenty does not match against existing records; you get duplicate Companies that have to be merged manually after the fact. The same canonical form must be used everywhere the domain appears (Company domainName, People companyDomain cross-reference column). Twenty's docs flag this as critical because the sync engine for email and calendar uses domain matching too 3. 3
High impact
Select field labels imported instead of internal option names
Twenty Select and Multi-Select fields have an internal option name distinct from the display label — the label is Closed Won, the option name is closedWon. The CSV importer expects the internal name in the column value. Loading display labels can either fail validation or silently miscategorise the row depending on field configuration. Enable Advanced Mode in Settings → Data Model to see the internal name for each option, and build your transform layer against those values 2226. 22
High impact
CSV row cap surprise — 2,000 then 10,000
Twenty's CSV import was historically capped at 2,000 rows per file, raised to 10,000 in later releases via issues #11372 and #11980 68. Teams sizing a one-shot migration off Salesforce or HubSpot row caps will hit this cliff. The fix is to split files (Twenty's own docs recommend splitting at 10,000 records) 3832. 8
Medium impact
Multi-select round-trip overwrites instead of merging
Practitioners hit a multi-select edge case on re-imports: upload a CSV with multiSelect1, then upload the same file with multiSelect2, and the records end up with only multiSelect2 — the previous value is overwritten rather than the two values being merged into a multi-value cell 14. Workaround: include all multi-select values in every row of every re-import. 14
Medium impact
Re-importing with previously defined id is partial
Twenty supports re-importing records with their previously assigned id UUIDs, which is essential if you are bouncing data through a sandbox or fixing a missed column after the fact. But issue #13195 documents that omitted columns in the second import are treated inconsistently — sometimes preserved, sometimes cleared. Build your re-import file as a *full* row replacement, not a partial-column update, and validate against a 10-row sample before the full re-run 33. 33
Medium impact
Views, workflows and permissions do not import
Twenty's documentation says it plainly: 'Views, workflows, and permissions must be recreated manually after migration. Plan time for this configuration work' 12. Teams that scope only the data migration discover post-cutover that every Kanban view, every saved filter, every workflow rule and every permission set is empty. Build a configuration checklist alongside the data mapping spreadsheet and budget one to three days for the rebuild on top of the data load. 12
Medium impact
Self-host scaling: Kanban lag and concurrent-user crashes
Practitioners self-hosting Twenty for 50-user teams have reported the system locking up under high concurrent card-creation load on the Kanban view, with hundreds of cards on screen producing visual bugs 87. The mitigation is right-sizing infrastructure (more than the 2 vCPU / 4 GB RAM minimum), keeping Redis and PostgreSQL on separate workers, and limiting Kanban views to a filtered subset rather than a full pipeline. Track GitHub for the active performance work before betting a large team on self-host. 87
Low impact
Compliance: GDPR / SOC2 attestation depends on deployment
Twenty self-host puts the data under your jurisdiction and your security controls — there is no Twenty SOC 2 audit covering your installation 38. Twenty Cloud handles infrastructure but the security attestation surface is narrower than HubSpot or Salesforce — verify the current SOC 2 / GDPR status with Twenty directly before signing off on a regulated-data migration. EU-residency-sensitive deployments can self-host in an EU region (Frankfurt, Amsterdam) with a $20–50/month VPS and full data sovereignty 38. 38
Section 07
Validation and cutover
What to verify after the import job, in what order — and how to fail safely when something is wrong.
Validation is the bridge between the import finishing and users being allowed in. Practitioners recommend a three-stage validation for Twenty: a test load of 10 percent of records with stakeholder spot-checks, the full load with real-time monitoring of record counts and relation integrity, and a 30-day post-migration audit. The most reliable signal is having department reps verify their own records — they know what right looks like better than any reconciliation script.
Build a reconciliation queries spreadsheet that compares source and destination on each of these counts. Anything outside a 0.5 percent variance gets investigated before users get login access.
- Total People imported vs source — minus deliberately excluded rows (role-based emails, opt-outs, stale 2+ year contacts).
- Total Companies imported vs source — checking that domain-based dedup did not under- or over-merge.
- Total Opportunities per pipeline stage vs source, plus sum of
amount— a non-trivial dollar variance usually signals a stage-mapping error or a Currency precision drop (Twenty stores amounts in micros). - Total Notes and Tasks per parent record type imported vs source — and a date-bucketed comparison to confirm the legacy
createdAtround-tripped into the custom Date field. - Relations per object type — count People→Company, Opportunity→Company and Opportunity→Person relations and compare against the source-derived expected counts.
- Owner distribution — group by
accountOwnerand confirm no record landed unowned that should not have. Cross-check that every distinct owner in the source resolved to a Workspace Member. - Unique-identifier integrity — count distinct emails on People and distinct
domainNamevalues on Companies; duplicates indicate the dedup transform missed cases.
On top of reconciliation, run a manual spot-check protocol: pick 30 random records across objects via the table view filter, open each one, and verify every field against the source UI. Pick five high-value Opportunities and trace the full relation graph — point of contact, company, notes, tasks, attachments. If a non-trivial discrepancy shows up in three or more of the 30, halt the load, fix the root cause, and re-import the affected rows by id.
Rollback in Twenty is not a single button. Twenty 1.3.0 added a Merge Records action that lets you collapse duplicates after the fact, but there is no bulk-undo of an entire import.
The working rollback strategy is: export everything before the import starts (via the table view's export action, or SELECT * FROM against the workspace schema on self-host), stamp every imported row with an *Import Batch ID* custom Text field, and if catastrophe strikes, filter by that batch ID and bulk-delete from the table view, then re-import from the cleaned source.
On self-host, the strongest rollback option is a Postgres pg_dump immediately before cutover — restoring from that snapshot is the closest thing to an atomic undo Twenty offers. Twenty Cloud customers should request a workspace snapshot from Twenty support before the import if rollback is critical.
Cutover sequencing runs in seven steps. (1) Source goes read-only and the team is notified. (2) Final delta export captures everything that changed during the test-import window. (3) Delta is imported in the same Companies → People → Opportunities → Notes/Tasks → Custom Objects order 83.
(4) Reconciliation runs. (5) Views, workflows and permissions are rebuilt. (6) Users get login access and a 48-hour hyper-care window with the migration lead on call. (7) Source decommission is scheduled for 30 to 90 days out, never the same day.
Section 08
Migration partners and tools
Implementation partners, iPaaS vendors, and specialist migration shops — what each is good for and how to choose.
Twenty maintains an Implementation Partners programme listed inside the documentation; partners are referenced by Twenty's own docs as the people to call for very large datasets 38. Certified Twenty partners typically run fixed-scope migration packages — Salesforce-to-Twenty, HubSpot-to-Twenty, custom workflow rebuilds — alongside ongoing managed services that cover schema evolution and version upgrades after cutover.
Managed-deployment providers are a separate but adjacent ecosystem: several PaaS vendors ship one-click Twenty deployments starting around $14/month for small teams, and open-source self-host orchestrators offer documented Twenty configurations in their community discussions 100. These are infrastructure providers, not migration consultancies — they get the server running but the data move is still on you.
On the ETL and iPaaS side, Fivetran, Airbyte, Workato and Stitch can all be used to stage source data into a warehouse, transform it with SQL, then write into Twenty. As of mid-2026 the prebuilt Twenty connectors on these platforms are thin — most teams write a small Node.js or Python script rather than waiting for a managed connector.
Managed-migration cost ranges vary widely. A clean HubSpot- or Pipedrive-to-Twenty move of under 25,000 contacts with no historical activities and standard objects only often lands in the $500–$3,000 range from specialist migration vendors, with 48-hour turnaround. A Salesforce-to-Twenty project with custom objects, historical activities and workflow rebuild typically runs $5,000–$25,000+, with the upper end driven by record count, custom-object complexity, historical-data depth and the number of integrations that need re-pointed.
Self-service is genuinely viable for small teams: Twenty Cloud at $9/user/month plus a weekend of CSV preparation is enough for a 5,000-record consolidation. The cost case for outsourcing rises sharply with custom-object count, historical-activity depth, and Salesforce-Apex-style logic that needs to be rebuilt as Twenty workflows.
For teams that want to outsource the migration end-to-end, FlitStack specialises in Twenty CRM migrations and handles the field mapping, Select option-name conversion, historical-data preservation, custom-object schema setup, and validation work described in Sections 5 and 7 of this guide. Pricing is fixed-fee, based on record count and source platform, with separate line items for custom objects, historical activity depth, and self-host vs. Twenty Cloud delivery so the scope is transparent before signature.
This is one of several legitimate paths — the right choice for any given team depends on whether they want a certified Twenty partner, a self-service approach, an iPaaS-backed pipeline, or a specialist migration vendor. Explore FlitStack →
Section 09
Frequently asked questions
The questions every Twenty CRM migration team works through before they sign the scope.
References
Sources
- 1 Launch HN: Twenty.com (YC S23) — Open-source CRM
- 3 Migrating from Other CRMs — Twenty Documentation
- 6 Allow bigger imports than 2000 lines — twentyhq/twenty Issue
- 8 Data Migration — Twenty Documentation
- 11 Proposal: Computed Fields System — twentyhq/twenty Issue
- 12 Migrating from Other CRMs — Step-by-step audit + plan (Twenty Docs)
- 13 Supported File Formats — Twenty Documentation
- 14 Bulk updating records — Twenty CRM (multi-select round-trip)
- 18 Data Migration — CSV Import Basics (Twenty Docs)
- 22 Error Handling & Validation — Twenty Documentation
- 26 Create Custom Fields — Twenty Documentation
- 28 Zoho CRM is eating my time alive — r/smallbusiness
- 29 Twenty CRM — Sequence Follow-Ups (r/CRM)
- 30 Twenty CRM — Sequencing workaround discussion
- 32 Data Model — Twenty Documentation
- 33 Re-importing data with previously defined id fails — twentyhq/twenty Issue
- 36 Custom Objects (Metadata) — Twenty Documentation
- 38 Data Migration — Recommendations + Implementation Partners
- 41 Feature Request: Expand Standard Fields for People and Companies — twentyhq/twenty
- 42 Twenty Documentation
- 78 Migrating from Other CRMs — Create custom fields first warning
- 83 Migrating from Other CRMs — Invite users + import order warnings
- 87 Twenty self-hosted — concurrent-user concerns (r/selfhosted)
- 100 Twenty (CRM) on Coolify — environment + storage configuration
- 102 Calendar & Emails — Twenty Documentation
- 103 Add rich text field type — twentyhq/twenty Issue
- 121 Enable Attachments feature on Opportunity standard object — twentyhq/twenty
- 132 Twenty self-hosted — audit-trail concerns (r/selfhosted)
- 151 Migrating from Other CRMs — Large Migrations (50,000+) guide
- 153 Support for Multiple Pipelines on One Object (Record Types) — twentyhq/twenty
Need help running this migration?
FlitStack AI runs Twenty CRM migrations end-to-end.
Fixed-fee pricing, a hands-on migration engineer, full field mapping and validation. The work described in this guide — done for you.