CRM migration
Field-level mapping, validation, and rollback between Fat Free CRM and Twenty CRM. We move data and schema; workflows are rebuilt natively in Twenty CRM.
Fat Free CRM
Source
Twenty CRM
Destination
Compatibility
10 of 11
objects map 1:1 between Fat Free CRM and Twenty CRM.
Complexity
BStandard
Timeline
3-5 weeks
Overview
Moving from Fat Free CRM to Twenty CRM is a structural migration from a Rails-era open-source platform with no API to a modern TypeScript-and-PostgreSQL self-hosted CRM with a documented REST API. The primary technical constraint is that Fat Free CRM exposes no public API, so all extraction goes through a read-only connection to its underlying MySQL, PostgreSQL, or SQLite database. We begin every migration with a schema discovery pass to capture core tables, plugin-extended columns, join tables (account-contact, opportunity-contact, campaign membership), and any custom field definitions before extracting a single record. We then map Fat Free CRM's distinct Leads and Opportunities objects to Twenty CRM's Persons and Opportunities, preserving the contact-opportunity join table to keep deal associations intact. User ownership from Fat Free CRM carries forward as a reference roster; Twenty CRM user provisioning happens in your environment and we map by email. Attachments stored on the Fat Free CRM filesystem are enumerated but not migrated as binary content. Workflows, group permissions, and custom plugins do not migrate; we deliver a written inventory of these for your admin to rebuild in Twenty CRM's settings UI.
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 Fat Free CRM 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.
Fat Free CRM
Account
Twenty CRM
Company
1:1Fat Free CRM Account records map directly to Twenty CRM Company records. The Account name becomes Company name, website maps to the website field, and phone maps to the phone field. Billing address columns in the accounts table map to company address fields. The account's assigned user_id maps to the owner field in Twenty CRM by email lookup against the Twenty CRM user roster. Accounts with no assigned user default to the migration user until the customer remaps ownership post-migration.
Fat Free CRM
Contact
Twenty CRM
Person
1:1Fat Free CRM Contact records map to Twenty CRM Person records. The contact's first name, last name, email, phone, and title transfer directly. The contact_accounts join table preserves the many-to-one link to the Account; we resolve the Account ID first (or create the Company in Twenty CRM) so that the contact-company relationship is established at import time. Contacts without an associated account import as Persons with no company link.
Fat Free CRM
Lead
Twenty CRM
Person (with lead context)
1:1Fat Free CRM Leads are distinct from Contacts in the source schema and carry status, source, rating, and assigned user fields that have no direct Twenty CRM equivalent. We import Leads as Persons and append a custom text field or tag capturing the original lead status (new, contacted, qualified, converted) and lead source. The customer's admin reviews and sets the appropriate Person type in Twenty CRM after migration.
Fat Free CRM
Opportunity
Twenty CRM
Opportunity
1:1Fat Free CRM Opportunity records map to Twenty CRM Opportunity records. Stage, amount, probability, and close date transfer directly. The opportunity_contacts join table is critical — we resolve each linked Contact's new Twenty CRM Person ID and attach it to the Opportunity. Without join table resolution, opportunities in Twenty CRM appear disconnected from the people working them.
Fat Free CRM
Task
Twenty CRM
Task
1:1Fat Free CRM Task records map to Twenty CRM Task records. Title, body, due date, category, and completion status transfer. Assigned user_id resolves via email to the Twenty CRM user roster. Tasks linked to a Contact or Opportunity carry the resolved Person or Opportunity ID in the Twenty CRM target object field. Open and completed tasks both migrate; the status field preserves completion state.
Fat Free CRM
Campaign
Twenty CRM
Target List
1:1Fat Free CRM Campaign records (name, status, budget, target metrics) map to Twenty CRM Target List records. Contact-campaign membership is stored in the tag_subscriptions or contacts_tags join table depending on Fat Free CRM version; we reconstruct the membership by resolving each contact's new Twenty CRM Person ID and associating it with the corresponding Target List. Status mapping: active campaigns become active target lists, completed campaigns become archived.
Fat Free CRM
Tag
Twenty CRM
Custom text field or tag
lossyFat Free CRM's global tagging system (acts_as_taggable) stores tags across Contacts, Accounts, Opportunities, and Leads in a separate tagging table. We extract the full tag set per record and decide with the customer whether to map tags to a single multi-value custom field in Twenty CRM or to a tagging implementation in the target object's notes. This decision depends on how heavily the customer uses tagging for segmentation.
Fat Free CRM
User
Twenty CRM
User (reference roster)
1:1Fat Free CRM Users (name, email, role, team membership) export as a reference roster keyed by email. Twenty CRM manages its own user directory, so we cannot provision users or reassign ownership automatically. The roster is delivered as a CSV mapping source user_id to email, and the customer creates corresponding users in Twenty CRM before the final migration pass. Ownership assignments on migrated records reference the roster for manual remapping.
Fat Free CRM
Group
Twenty CRM
Team
1:1Fat Free CRM Groups represent organisational units used for access control. Twenty CRM does not have an equivalent Group concept as a first-class CRM object. We export group membership as part of the user roster and document which Fat Free CRM users belonged to which groups. The customer maps these to Twenty CRM team structures or user roles post-migration.
Fat Free CRM
Custom Field
Twenty CRM
Custom Field
1:1Fat Free CRM custom fields on Accounts, Contacts, Leads, and Opportunities are stored as extended columns in the core tables (plugin-extended schema) or in a separate custom_fields table depending on version. We run schema discovery first, enumerate every custom column, and create matching custom fields in Twenty CRM before data import. All custom field values transfer as text for maximum compatibility; the customer validates type conversion in the Twenty CRM settings UI post-migration.
Fat Free CRM
Attachment metadata
Twenty CRM
File inventory document
1:1Fat Free CRM stores uploaded files on the host server's filesystem or a configured S3 bucket, not in the database. We enumerate every attachment record (filename, path, associated record type and ID) and deliver a file inventory CSV. The customer copies files to Twenty CRM's storage layer manually. Binary attachment content cannot be extracted through our standard database connection and is explicitly excluded from migration scope.
| Fat Free CRM | Twenty CRM | Compatibility | |
|---|---|---|---|
| Account | Company1:1 | Fully supported | |
| Contact | Person1:1 | Fully supported | |
| Lead | Person (with lead context)1:1 | Fully supported | |
| Opportunity | Opportunity1:1 | Fully supported | |
| Task | Task1:1 | Fully supported | |
| Campaign | Target List1:1 | Fully supported | |
| Tag | Custom text field or taglossy | Fully supported | |
| User | User (reference roster)1:1 | Fully supported | |
| Group | Team1:1 | Fully supported | |
| Custom Field | Custom Field1:1 | Fully supported | |
| Attachment metadata | File inventory document1: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.
Fat Free CRM gotchas
No public REST API forces direct database extraction
Plugin-extended schema may alter core tables
Attachment files live on the host filesystem
Users and groups must be manually remapped in the destination
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 database profiling
We begin with a read-only database connection to the customer's Fat Free CRM instance (MySQL, PostgreSQL, or SQLite). We run a schema discovery query that enumerates all tables, columns, data types, and any plugin-extended columns added to core tables. We also query the join tables (contact_accounts, opportunity_contacts, taggings, tag_subscriptions) and identify the database version. The discovery output is a schema map that we share with the customer, along with a record count estimate for each object so we can confirm migration scope and timeline before any data moves.
Schema design and custom field pre-creation
We design the Twenty CRM target schema based on the schema map. This includes creating any custom fields in Twenty CRM that correspond to Fat Free CRM custom columns and plugin-extended fields before data import begins. We map Fat Free CRM campaign membership to Twenty CRM Target Lists, resolve tag handling strategy (multi-value field vs. tagging note), and document the user roster mapping. The customer provisions Twenty CRM users and we confirm the user roster is complete before proceeding.
Test migration in Twenty CRM sandbox
We run a full migration into a Twenty CRM sandbox or staging instance using a snapshot of the production database. The customer reconciles record counts across all objects, spot-checks 25-50 records for field-level accuracy, and validates that join table relationships (contact-company, opportunity-contact, campaign membership) are intact. Any mapping corrections happen in this phase. The customer signs off on the test migration before production extraction begins.
Production database extraction
We connect read-only to the production Fat Free CRM database and extract all records in dependency order: Companies (from Accounts), Persons (from Contacts and Leads), Tasks, Opportunities with contact associations resolved, Campaigns with contact memberships rebuilt from join tables, and custom field values. Each extraction phase emits a row-count reconciliation report. The production Fat Free CRM instance remains writable throughout; the customer freezes new record creation in the final 48 hours before cutover.
Production import into Twenty CRM
We import data into Twenty CRM using its REST API in dependency order: Companies first (required for Person-Company lookups), then Persons, then Opportunities with resolved Person associations, then Tasks, then Target Lists with membership rebuilt from the join table data. Custom field values import after the base object migration is validated. Each phase is reconciled against the extraction row counts before the next phase begins.
Cutover, validation, and automation inventory delivery
We freeze Fat Free CRM writes during the cutover window, run a final delta pass for any records modified during migration, and enable Twenty CRM as the system of record. We deliver the file inventory for manual attachment migration, the user and group roster mapping, and a written inventory of any Fat Free CRM plugins or custom controllers that require admin review in Twenty CRM. We support a one-week hypercare window for reconciliation issues. We do not rebuild Fat Free CRM automations or custom Rails code as Twenty CRM configurations; that work is documented for the customer's admin.
Platform deep dives
Fat Free CRM
Source
Strengths
Weaknesses
Twenty CRM
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 Fat Free CRM and Twenty CRM.
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
Fat Free CRM: Not applicable — self-hosted database has no API rate limiting.
Data volume sensitivity
Fat Free CRM 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 Fat Free CRM to Twenty CRM migration scoping. Not seeing yours? Book a call.
Walk through your Fat Free CRM 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 Fat Free CRM
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.