The CTO's Guide to Salesforce to Attio Migration (2026)
A CTO-level guide to migrating from Salesforce to Attio. Covers data model mapping, migration methods, API rate limits, edge cases, and validation.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
Migrating from Salesforce to Attio is a schema translation problem, not a lift-and-shift. Salesforce stores business meaning in record types, validation rules, roll-up summaries, Apex triggers, and deeply nested object hierarchies. Attio stores meaning in objects, attributes, relationship fields, lists, and views. Every object, field, and relationship must be deliberately remapped — and several Salesforce-specific constructs (formula fields, roll-up summaries, Person Accounts) have no direct Attio equivalent.
If your engineering team attempts to export Salesforce data via CSV and push it into Attio without restructuring the schema, you will flatten your data, orphan historical activities, and sever the relationship chains (Account → Contact → Opportunity) that give your CRM its value. (attio.com)
This guide covers the architectural differences, every viable migration method and its trade-offs, concrete object and field mappings, the API constraints on both sides, and the edge cases that silently destroy data integrity. For a deeper look at Attio's data model and workspace configuration, see The Ultimate Guide to Attio CRM (2026).
Why Teams Leave Salesforce for Attio
The migration drivers we see most often:
- Over-engineered orgs. Years of Apex triggers, validation rules, Process Builder flows, and custom objects create a Salesforce org that's expensive to maintain and terrifying to change. Attio's schema is code-free and reconfigurable in minutes.
- Cost. A 10-person team on Salesforce Enterprise pays roughly $1,750/month. The same team on Attio Pro pays $690/month — and gets custom objects, relationship attributes, and AI-native features without admin overhead.
- Relationship intelligence. Attio automatically ingests email and calendar data from connected inboxes and enriches People and Company records without manual entry. Salesforce requires third-party tools or custom Apex to replicate this.
- Data model flexibility. Attio lets you create custom objects, define many-to-many relationships natively, and build lists that separate workflow context from record-level truth — all without writing code.
The Paradigm Shift: Salesforce's Rigid Schema vs. Attio's Graph Model
Understanding the architectural gap is the prerequisite for every migration decision.
Salesforce organizes data around standard objects (Accounts, Contacts, Leads, Opportunities, Cases) connected by lookup and master-detail relationships. Customization happens through metadata: Record Types, Page Layouts, formula fields, roll-up summaries, and Apex code. Every customization adds schema weight. Many-to-many relationships require custom junction objects. (help.salesforce.com)
Attio models data as objects and records with relationship attributes that link any object to any other object. Lists provide workflow context (pipeline stages, status tracking) without modifying the underlying record. There are no junction objects, no Record Types, and no formula fields. (attio.com)
The practical impact: a Salesforce Account with three Record Types (Customer, Partner, Prospect) and a dozen Page Layouts becomes a single Attio Company with different list memberships and status attributes. The data simplifies, but the mapping decisions are non-trivial.
Attio has no equivalent for Salesforce formula fields, roll-up summaries, or Apex triggers. Any computed field values must be flattened to static values during migration or recreated using Attio workflows and AI attributes.
Evaluating Salesforce to Attio Migration Approaches
There are five viable approaches. Pick based on data shape, history depth, and engineering bandwidth — not on which option looks fastest in a demo.
1. Native CSV Export/Import
How it works: Export Salesforce data using Data Loader or the Data Export Service as CSV files. Clean and transform in a spreadsheet or script. Import into Attio using the built-in CSV importer.
When to use it: Small datasets (under 5,000 records), flat structures with minimal cross-object relationships.
Limitations: Attio's CSV importer is capped at 100,000 rows, 100 columns, and 100 MB per file. It does not support importing notes. Deals require three mandatory fields — deal name, deal owner, and deal stage — and any missing value blocks the entire row. Relationships must be expressed through unique identifiers (email for People, domain for Companies), and the importer handles one object type per import. Salesforce's Data Export Service is not supported in sandboxes. (help.salesforce.com)
Complexity: Low | Scalability: Poor for enterprise data
For a deeper analysis of CSV-based migration trade-offs, see Using CSVs for SaaS Data Migrations: Pros and Cons.
2. Import2 (Attio's Built-in Migration Partner)
How it works: Attio offers a built-in migration path via Import2, accessible from Settings → Migrate on Plus, Pro, and Enterprise plans. Import2 connects directly to your Salesforce org and maps standard objects.
Supported objects: Companies, Contacts (Leads imported as Contacts), Deals, Notes, Tasks, Attachments, and Calls (imported as Notes). Emails and Meetings are not supported. Cases are not supported. (attio.com)
Key constraints: Import2 creates new records but will not update existing records. If your team's email sync has already populated Attio with People and Company records, Import2 will create duplicates — it cannot upsert. Objects can only map to Attio objects, not to lists.
Complexity: Low | Scalability: Adequate for small-to-mid orgs with standard objects
For a detailed comparison of Import2's limitations against managed services, see ClonePartner vs. Import2.
3. API-Based Migration (Salesforce Bulk API 2.0 → Attio REST API)
How it works: Extract data from Salesforce using Bulk API 2.0 for high-volume queries and REST API for metadata. Transform in a middleware layer (Python, Node.js, or an ETL tool). Load into Attio via its REST API using the POST /v2/objects/{object}/records endpoint or the assert endpoint for upsert behavior.
When to use it: Any migration with more than 10,000 records, custom objects, multi-level relationships, or data that needs transformation during transit. Salesforce documents REST Query at up to 2,000 records per response with query locators for pagination, and Bulk API 2.0 for large asynchronous result sets. (developer.salesforce.com)
Scalability: This is the only approach that scales to enterprise Salesforce orgs.
Complexity: High — requires engineering resources, error handling, and rate limit management on both sides.
4. Custom ETL Pipeline
How it works: Build a dedicated Extract-Transform-Load pipeline using tools like Airbyte, Fivetran, or custom scripts that stage data in a warehouse (PostgreSQL, BigQuery) before loading to Attio. Attio exposes attribute creation and generic record upsert endpoints, so schema-first loading is practical. (docs.attio.com)
When to use it: Large, complex Salesforce orgs where you need full control over transformation logic, deduplication, audit trails, deterministic ID maps, and repeatable dry runs.
Complexity: High | Scalability: Enterprise-grade
5. Middleware (Zapier, Make)
How it works: Configure triggers and actions to move records between Salesforce and Attio through a visual workflow builder. Zapier and Make both have verified modules for Salesforce and Attio. (zapier.com)
When to use it: Ongoing sync of small record volumes during a phased migration or parallel run. Not suitable for bulk historical migration.
Limitations: Record-by-record execution. Neither platform handles complex relationship chains, dependency ordering, or bulk reconciliation.
Complexity: Medium | Scalability: Poor for historical data
Which Approach Fits Your Scenario
- Small business, <5K records, minimal custom objects: CSV import or Import2.
- Mid-market, 5K–100K records, standard + some custom objects: Import2 for core objects, API scripts for custom objects and notes.
- Enterprise, >100K records, deep Salesforce customization: API-based migration or managed service. CSV and Import2 cannot handle the dependency chains, relationship resolution, or volume.
- Ongoing sync required: API-based with webhook listeners or a managed continuous sync service.
- Low engineering bandwidth: Managed migration service. The hidden cost of a senior engineer spending three weeks debugging rate limits and relationship ordering almost always exceeds the service fee.
If Activities and Cases matter, do not scope the migration around CSV alone. Attio's CSV importer does not import notes, and the Import2 Salesforce path does not migrate Cases.
Pre-Migration Planning
Before writing extraction scripts, baseline your Salesforce org. Complex orgs hide business logic in triggers and flows that dictate data shape.
Take a full Salesforce backup first. The native Data Export Service produces org-wide CSV backups and can include attachments and Files. (help.salesforce.com)
- Data inventory: Quantify Accounts, Contacts, Leads, Opportunities, Cases, Tasks, Events, Campaigns, Attachments/Files, and every custom object that still matters.
- Complexity assessment: Identify Apex triggers, validation rules, record types, and Process Builder/Flow automations. These often populate fields automatically in Salesforce — in Attio, you must migrate the computed values directly. (help.salesforce.com)
- Scope definition: Decide what not to migrate. Orphaned records, stale leads from five years ago, deprecated custom objects, and unused picklist values should be archived, not moved.
- Cutover model: Determine whether you need a big-bang migration, phased approach, or incremental sync.
- Rollback assets: Plan source backups, rerunnable loaders, a source-to-target ID ledger, and a target delete strategy.
For a complete planning framework, review Best Practices for CRM Data Migration in 2026: The Engineer's Guide.
Data Model Mapping: Salesforce Objects to Attio
Attio gives you objects for core entities and lists for workflow context. That distinction is the center of a good migration design. Use objects for records that should exist once. Use lists when the data is specific to a workflow, campaign, or stage. (attio.com)
Core Object Mapping
- Accounts → Companies. Map
Account.Nameto Company name,Account.Websiteto Company domain (Attio uses domain as the unique identifier and enrichment key). Attio natively enriches Companies based on domain names. Account Record Types have no Attio equivalent — use list membership or a custom select attribute to preserve the distinction. Attio documentsdomainsas unique and says Companies cannot have new custom unique attributes. (docs.attio.com) - Contacts → People. Map
Contact.Emailto People email (unique identifier).Contact.AccountIdresolves to a relationship attribute linking People → Companies. Attio documentsemail_addressesas the unique attribute for People upserts, so contacts without reliable email need a separate merge policy. (docs.attio.com) - Leads → People. Attio has no Lead object. Import Leads as People with a status attribute or list membership that preserves lead stage context. Deduplicate against existing Contacts by email before migration to prevent duplicates.
- Opportunities → Deals. Attio's Deals object requires
deal_name,deal_owner, anddeal_stagefor every record. MapOpportunity.StageNameto Attio deal stages — define these in your pipeline list before migration.Opportunity.Amountmaps to a currency attribute. Deals have no unique attribute by default, so add your own if you want upsert behavior via theassertendpoint. (docs.attio.com) - Activities (Tasks, Events) → Notes / Tasks. Attio notes link to a single parent record. If a Salesforce Task relates to both a Contact and an Opportunity, you must choose one parent or create two copies. Closed history usually fits Notes better than Tasks — use Tasks only for open work. (docs.attio.com)
- Cases → Custom Object or Notes. Attio has no Cases equivalent. Simple case history can be flattened to Notes. Complex case management with status tracking requires a custom object with relationship attributes to People and Companies. Import2 will not migrate Salesforce Cases.
- Campaign Members → Lists or Tags. Map campaign membership to Attio list entries or tag attributes.
- Custom Objects → Custom Objects in Attio. Evaluate per-object feasibility. Attio custom object limits vary by plan: 3 (Free), 5 (Plus), 12 (Pro), unlimited (Enterprise).
Field-Level Mapping
Accounts → Companies:
Account.Name → Company name (text). Account.Website → Domains (domain) — critical for enrichment; preserve full URL in a custom text field if needed. Account.Phone → Phone numbers. Account.BillingAddress → Primary location. Account.Industry → Custom select attribute. Account.AnnualRevenue → Custom number/currency attribute. Account.OwnerId → Workspace member via owner attribute. (docs.attio.com)
Contacts → People:
Contact.FirstName / Contact.LastName → Name (personal-name). Contact.Email → Email addresses (unique — Attio stores emails as an array). Contact.Phone → Phone numbers. Contact.Title → Job title. Contact.MailingAddress → Primary location. Contact.AccountId → Company relationship attribute (resolved by domain or record ID). (docs.attio.com)
Opportunities → Deals:
Opportunity.Name → Deal name. Opportunity.StageName → Deal stage (a status attribute, not free text — unknown statuses will error out). Opportunity.Amount → Deal value (ensure currency formatting matches). Opportunity.CloseDate → Custom date attribute. Opportunity.AccountId → Associated company (relationship attribute). (docs.attio.com)
Activities → Notes:
Task/Event.Subject → Note title. Task/Event.Description → Note content. Task/Event.CreatedDate → Note created_at. Task/Event.WhoId/WhatId → Parent record reference. (docs.attio.com)
Salesforce picklist values must be normalized to match exact Attio select option labels before import. Attio will not auto-create unknown select or status values — it rejects them. Multi-select values use commas as delimiters, meaning picklist values containing commas will break the CSV importer. Create all target select options and deal statuses before the first load. (docs.attio.com)
Handling Salesforce-Specific Constructs
- Record Types: Convert to custom single-select attributes in Attio, or use list membership to maintain categorization. (help.salesforce.com)
- Formula Fields & Roll-up Summaries: Attio does not compute historical roll-ups natively. Query the evaluated output of these fields in Salesforce and map them as static values in Attio. Document what's lost. (help.salesforce.com)
- Lookup/Master-Detail Relationships: Become Attio record reference attributes. (docs.attio.com)
- Person Accounts: These combine Account and Contact fields into a single hybrid record. Split deliberately into People plus Companies, or design a B2C-specific pattern. Do not let the mapper guess. (help.salesforce.com)
Migration Architecture: Navigating API Limits
Extracting data from Salesforce and loading it into Attio is a battle against governor limits on both sides.
Salesforce Extraction Constraints
Salesforce Enterprise Edition enforces a 100,000 daily REST/SOAP API request limit plus 1,000 per user license, calculated on a 24-hour rolling window. This allocation is shared across your entire org — naive REST API scripts that query records one-by-one will exhaust the limit and shut down integrations company-wide. (help.salesforce.com)
For large historical extractions, use Salesforce Bulk API 2.0. Query jobs don't consume batch allocations, and data operations support up to 15,000 batches per 24 hours with 10,000 records per batch. Use SOQL for precise field selection — never use FIELDS(ALL) in production extraction.
Authentication requires an OAuth 2.0 Connected App. Salesforce restricted creation of new connected apps in Spring '26 and recommends external client apps for new setups. (developer.salesforce.com)
Attio Loading Constraints
Attio's API enforces 100 read requests/second and 25 write requests/second using a 10-second sliding window. There is no Bulk API equivalent — every record is a single API call. At 25 writes/sec, importing 50,000 records takes a minimum of ~33 minutes of pure write time. HTTP 429 responses include a Retry-After header. (docs.attio.com)
Authentication uses API access tokens generated in Workspace Settings → Developers, scoped per integration. The assert endpoint with matching_attribute enables upsert behavior — critical for avoiding duplicates when re-running migration batches. Attio also supports OAuth 2.0 for integration authentication.
Some Attio endpoints use limit/offset pagination, others use cursor-based pagination with next_cursor. Build your scripts to handle both.
Disable Attio email sync for all workspace members before starting migration. If connected, Attio auto-creates People and Company records from incoming emails, and your migration script will create duplicates. Re-enable sync only after migration validation is complete.
Step-by-Step Migration Process
Step 1 — Pre-Migration Audit. Inventory Salesforce objects. Assess org complexity: count custom objects, active Apex triggers, validation rules, and Flow automations that alter data shape. Identify and exclude stale data.
Step 2 — Design Attio Schema. Define all target objects, attributes, pipeline lists, status stages, and select options in Attio before importing any data. Validate that every Salesforce field has a mapped Attio attribute with the correct type. (attio.com)
Step 3 — Extract from Salesforce. Use Bulk API 2.0 for large objects and REST API for metadata. Extract in dependency order: Users → Accounts → Contacts → Leads → Opportunities → Activities → Custom Objects. Maintain a Salesforce ID → Attio Record ID mapping table.
Step 4 — Transform. Clean duplicates. Normalize picklist values to match Attio select labels exactly. Flatten formula fields to static values. Resolve relationship IDs. Convert Record Types to Attio select attributes or list memberships.
Step 5 — Load into Attio. Import Companies first (matched by domain), then People (matched by email), then Deals (linked to Companies). Use the assert endpoint for upsert behavior. Load Notes and Tasks via API — not CSV. Rebuild cross-object references using the ID mapping table.
Step 6 — Validate. Compare record counts per object. Spot-check 20+ records per object across both systems. Verify relationship integrity. Run UAT with actual sales users. Keep Salesforce read-only for 2–4 weeks as a rollback safety net.
Salesforce Extraction Example (Bulk API 2.0)
POST /services/data/v62.0/jobs/query
Body:
operation: query
query: SELECT Id, Name, Website, OwnerId FROM Account
GET /services/data/v62.0/jobs/query/{job_id}
GET /services/data/v62.0/jobs/query/{job_id}/resultsAttio Load Example (Person Upsert + Note Create)
PUT /v2/objects/people/records?matching_attribute=email_addresses
Body:
data.values.email_addresses: [alice@example.com]
data.values.name.first_name: Alice
data.values.name.last_name: Nguyen
data.values.company.target_object: companies
data.values.company.target_record_id: <attio_company_id>
POST /v2/notes
Body:
data.parent_object: people
data.parent_record_id: <attio_person_id>
data.title: Discovery call
data.content: Flattened Salesforce task/event history
data.created_at: 2025-11-18T14:30:00ZPython Migration Script Outline
import requests
import time
SF_BULK_URL = "https://yourorg.salesforce.com/services/data/v62.0/jobs/query"
ATTIO_BASE = "https://api.attio.com/v2"
ATTIO_TOKEN = "Bearer <your-attio-token>"
ID_MAP = {} # sf_id -> attio_record_id
def extract_salesforce(query, sf_token):
"""Submit Bulk API 2.0 query job and poll for results."""
headers = {"Authorization": f"Bearer {sf_token}", "Content-Type": "application/json"}
job = requests.post(SF_BULK_URL, json={"operation": "query", "query": query}, headers=headers)
job_id = job.json()["id"]
while True:
status = requests.get(f"{SF_BULK_URL}/{job_id}", headers=headers).json()
if status["state"] == "JobComplete":
return requests.get(f"{SF_BULK_URL}/{job_id}/results", headers=headers).text
time.sleep(5)
def load_to_attio(object_slug, records, matching_attr=None):
"""Load records to Attio with rate limit handling."""
endpoint = f"{ATTIO_BASE}/objects/{object_slug}/records"
if matching_attr:
endpoint = f"{endpoint}?matching_attribute={matching_attr}"
for record in records:
while True:
resp = requests.put(
endpoint,
json={"data": {"values": record}},
headers={"Authorization": ATTIO_TOKEN, "Content-Type": "application/json"}
)
if resp.status_code == 429:
wait = int(resp.headers.get("Retry-After", 2))
time.sleep(wait)
continue
resp.raise_for_status()
ID_MAP[record.get("sf_id")] = resp.json()["data"]["id"]["record_id"]
breakFor error handling, log object name, source ID, batch ID, payload hash, target ID, HTTP status, and retry count. Treat Attio 429s as retryable using the Retry-After header. Treat mapping and validation failures as dead-letter records, not silent skips.
Edge Cases That Break Migrations
Migrations fail in the edge cases. Plan for all of these:
- Person Accounts. Salesforce Person Accounts merge Account and Contact fields into a hybrid object. Attio has no equivalent. Split them: create a People record for the individual and optionally a Company record if business context exists. Map Person Account fields across both objects. Define explicit B2B vs. B2C rules — do not let the mapper guess. (help.salesforce.com)
- Duplicate records. Salesforce orgs accumulate years of duplicate Leads and Contacts. Deduplicate before migration. Attio uses email (People) and domain (Companies) as unique identifiers — duplicates in these fields will silently merge or fail. Shared inboxes and alias emails need explicit merge rules. (docs.attio.com)
- Multi-level relationships. A Task in Salesforce might be linked to an Opportunity, which is linked to a Contact, which is linked to an Account. Your script must resolve all three foreign keys and import in strict dependency order. The Attio API will reject a People record with a Company relationship reference if that Company doesn't yet exist.
- Company matching surprises. Attio can auto-generate or match a Company from a Person's email domain. This is helpful for greenfield CRM use, but risky during migration when subsidiaries, agencies, or personal email domains are in the data. Control this behavior during import. (docs.attio.com)
- Formula fields and roll-up summaries. These are computed server-side in Salesforce and have no Attio equivalent. Export the computed values as static data during extraction. Document what's lost. (help.salesforce.com)
- File attachments. Attio's file upload endpoint is in beta with a 50 MB max file size. Very large binaries or complex version history need separate planning — consider exporting files to cloud storage (Google Drive, S3) and linking via URL attributes or Notes. (docs.attio.com)
- Sandbox vs. Production. Always run test migrations against a Salesforce sandbox first. Salesforce's Data Export Service is not supported in sandboxes — use Data Loader or APIs for test runs. Sandbox API limits can differ from production. (help.salesforce.com)
Limitations You Must Accept
Attio is not Salesforce with a better UI. It's a different paradigm, and some capabilities don't translate:
- No Apex-equivalent. Complex server-side logic must be rebuilt as Attio workflows, external automations, or accepted as out of scope. Attio gives you workflows, a REST API, and an App SDK with server functions — but it is not a drop-in replacement for Salesforce Platform behavior. (attio.com)
- No native CPQ or approval chains. If your Salesforce org relies on CPQ or multi-step approvals, Attio won't replace that functionality.
- Reporting differs. Attio's reporting is list- and view-based. Salesforce's report builder, dashboards, and cross-object reports are more mature. Plan to recreate critical reports manually.
- Field history tracking doesn't migrate. Salesforce audit trail and field history data has no Attio equivalent. If compliance requires historical audit logs, export them to a data warehouse rather than trying to force them into Attio.
- Record limits matter. Attio caps records per plan: 50K (Free), 250K (Plus), 1M (Pro). Verify your Salesforce record volume fits the target plan before starting.
Validation, Testing, and Rollback
Never execute a production migration without a sandbox test first. Validation needs to be mechanical, not manual spot checks of random records.
- Record count comparison: Per object, per Salesforce Record Type. Every number must match.
- Field-level validation: Spot-check critical fields — currency values, dates, picklist integrity. Test high-value fields, not random trivia.
- Relationship integrity: Verify all People link to correct Companies. Confirm Deals associate to the right Companies and pipeline stages.
- Edge case sampling: Check merged leads, Person Accounts, missing domains, archived owners.
- UAT: Have actual sales, RevOps, and support users validate their accounts, open deals, and recent activity in Attio.
- Rollback plan: Keep Salesforce org read-only for 2–4 weeks post-migration. If issues surface, the original data is untouched. Maintain source backups, rerunnable loaders, and a cutover ledger.
Post-Migration: Rebuilding the Operating Model
After loading data, rebuild the operating model in Attio. The data model and workflow builder give you the primitives, but they do not recreate old Salesforce behavior by themselves.
- Rebuild automations. Salesforce Flows and Process Builder rules don't transfer. Recreate critical automations as Attio workflows.
- Recreate reports. Start with the 5–10 reports your team actually uses, not every Salesforce dashboard.
- Re-enable email sync. Configure sync settings to match against existing records only — don't let Attio auto-create new People from every email.
- Train users. Salesforce power users need to unlearn Record Types, Page Layouts, and the Lead-to-Contact conversion model. Attio's paradigm is different; invest in training on the object/list split.
- Monitor for at least one full sales cycle. Watch for data inconsistencies, missing relationships, and user-reported gaps.
- Decommission Salesforce. After parallel run validation, archive the Salesforce org. Don't delete it — keep it read-only for compliance and reference.
Best Practices Checklist
- Back up everything. Full Salesforce Data Export before every dry run and before go-live.
- Test in sandbox. Run at least two full-fidelity test migrations before production.
- Design Attio schema first. Define all objects, attributes, lists, select options, and stages before importing a single record.
- Disable email sync. Prevent Attio from auto-creating records during migration.
- Import in dependency order. Companies → People → Deals → Notes → Tasks → List entries.
- Use the assert endpoint. Upsert behavior prevents duplicates when re-running migration batches.
- Validate after each object. Don't wait until the end to check record counts.
- Document every mapping decision. Future you will thank present you.
- Automate repetitive transforms and ID mapping. Manual work at scale is where data loss hides.
When to Use a Managed Migration Service
DIY migrations fail when the org is complex enough that the engineering cost exceeds the service fee. Common failure modes: broken relationship chains, duplicate records from email sync timing, governor limit exhaustion mid-extraction, and formula field data loss.
If your Salesforce org has more than 50K records, custom objects, Person Accounts, or multi-level relationship chains (Account → Contact → Opportunity → Activity), the migration is a full engineering project — not a weekend task. Building a custom ETL pipeline for a one-off migration is an expensive distraction for product engineering teams.
ClonePartner handles Salesforce-to-Attio migrations with complete relationship preservation, Salesforce governor limit management, and Attio rate limit handling built into our pipeline. We migrate Companies, People, Deals, Notes, Tasks, and custom objects with full cross-object reference resolution and record-count parity validation. Zero downtime — your team keeps working in Salesforce until cutover.
If your org is simple, build it yourself. If your org has ten years of history and custom behavior, buying certainty is usually cheaper than learning in production.
Frequently Asked Questions
- Can I migrate Salesforce data to Attio using CSV?
- Yes, but with major limitations. Attio's CSV importer is capped at 100,000 rows, 100 columns, and 100 MB per file, does not support importing notes, and handles one object type per import. It works for small, flat datasets under 5,000 records but breaks down for enterprise orgs with custom objects, multi-level relationships, or activity history.
- What Salesforce objects does Import2 support for Attio migration?
- Import2 supports importing Companies, Contacts (Leads imported as Contacts), Deals, Notes, Tasks, Attachments, and Calls (as Notes) into Attio. It does not support Cases, Emails, or Meetings. Import2 also cannot update existing records or import into Attio lists — it only creates new records.
- What are Attio's API rate limits for migration?
- Attio allows 100 read requests per second and 25 write requests per second, measured on a 10-second sliding window. There is no Bulk API — every record requires a single API call. At 25 writes/sec, importing 50,000 records takes a minimum of ~33 minutes. Exceeding limits returns HTTP 429 with a Retry-After header.
- How do Salesforce Leads map to Attio?
- Attio has no Lead object. Salesforce Leads should be imported as People records, with lead stage context preserved via a status attribute or list membership. Deduplicate Leads against existing Contacts by email before migration to prevent duplicates.
- What Salesforce features have no Attio equivalent?
- Attio has no equivalent for formula fields, roll-up summaries, Record Types, Page Layouts, Apex triggers, CPQ, complex approval chains, or field history tracking. Formula field values must be flattened to static data during extraction. Record Types can be approximated with select attributes or list membership.