Skip to content

Zoho CRM to Monday.com Migration: The CTO's Technical Guide

A technical guide to migrating from Zoho CRM to Monday.com covering API constraints, object mapping, relationship rebuilding, and the edge cases that cause silent data loss.

Raaj Raaj · · 23 min read
Zoho CRM to Monday.com Migration: The CTO's Technical Guide
TALK TO AN EXPERT

Planning a migration?

Get a free 30-min consultation. Our engineers review your setup and map out a custom migration plan — no obligation.

Schedule Free Consultation
  • 1,200+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing

Migrating from Zoho CRM to Monday.com is a data-model translation problem. Zoho CRM is a relational database with enforced module-level relationships — Accounts own Contacts, Contacts own Deals, and custom modules extend the schema with lookup fields. Monday.com is a Work OS where everything is a board, items are rows, columns are fields, and relationships between boards are opt-in via Connect Boards columns.

Every structural gap between these two architectures is where data silently disappears if you don't engineer around it.

If you need a fast decision: CSV export/import works for small, flat datasets where you're willing to manually rebuild relationships. API-based migration is the only safe path when you care about preserving Account → Contact → Deal chains, custom module data, and picklist integrity. Middleware tools like Zapier and Make are designed for ongoing single-record syncing — not bulk historical migration.

This guide covers the exact API constraints on both sides, a concrete object-mapping strategy, a comparison of every realistic migration method, and the edge cases that cause silent data loss.

For a broader perspective on when CSVs make sense versus when they don't, see Using CSVs for SaaS Data Migrations: Pros and Cons.

Zoho CRM's Relational Depth vs. Monday.com's Board Model

Zoho CRM is a traditional relational CRM. Modules (Leads, Contacts, Accounts, Deals, Activities, Products, and custom modules) have defined schemas with enforced field types, validation rules, and lookup relationships. A Contact must belong to an Account. A Deal must reference a Contact. These relationships are enforced at the database level.

Monday.com CRM takes a different approach. As a monday CRM subscriber, your account comes set up with a collection of boards called entities. Entities are boards that are core to the product and were built with the other monday CRM entities in mind. These boards are interconnected in several key ways. Each board contains thoughtful details that make the board uniquely useful for CRM users. These include your Contacts, Leads, Deals, Accounts, and Activities boards.

By default, your Contacts board will have a Connect Boards Column that links to the Accounts boards. Once a new contact is created, you can select the account associated with it. But these connections are not enforced the way Zoho enforces lookup relationships. A Contact can exist without an Account link. A Deal can exist without a Contact. This flexibility is a feature for project management — but it means your migration script must explicitly rebuild every relationship using Connect Boards columns and item IDs.

The architectural differences that affect migration planning:

Concept Zoho CRM Monday.com CRM
Data model Relational modules with enforced lookups Boards with optional Connect Boards columns
Custom objects Native custom modules with full field types Iframe-based apps, not native database tables
Relationships Enforced at DB level (Account → Contact → Deal) Opt-in via Connect Boards, manually or via API
Record limits No practical module-level cap 10,000 items/board (100,000 on Enterprise)
Field types 30+ native types including subforms ~20 column types, no subforms
API style REST with credit-based rate limits GraphQL with complexity-based rate limits

Monday.com CRM's core entity boards cannot be deleted or duplicated. Scale and board design matter early — if you ignore item-per-board limits during schema design, you can paint yourself into a corner before cutover.

The Data Model Shift: Mapping Zoho Modules to Monday Boards

This is where most migrations break. Zoho's module structure does not map 1:1 to Monday's board structure.

Core Object Mapping

Zoho CRM Module Monday.com Board Notes
Accounts Accounts board Company-level records. Keep Zoho record ID in a hidden External ID text column.
Contacts Contacts board Each contact links to Account via Connect Boards column.
Leads Leads board Unqualified prospects. Monday separates Leads from Contacts by board. Since Monday does not have a native lead conversion process like Zoho, you can alternatively use a unified Contacts board with a Status column.
Deals (Opportunities) Deals board Pipeline stages map to Monday's status/stage column. Each deal item represents an opportunity.
Tasks / Calls / Events Activities board Monday uses a unified Activities entity for calls, meetings, and similar logged events.
Notes Item updates or long-text columns Notes are not Activities board records. On Monday CRM, emails and notes are distinct from the Activities board. If you collapse all Zoho history into Activities, users lose the difference between a note, a scheduled activity, and email context.
Custom Modules Additional boards (with limitations) No native custom object equivalent.
Products Separate board Must be linked via Connect Boards.
Attachments File columns Require separate multipart upload via API.

The Connect Boards Problem

The Connect Boards Column allows you to easily link a column to the items of another board — or multiple boards. This column is a great way to connect information between different boards and is especially handy when your workflow involves interrelated boards.

To preserve Zoho's Account → Contact → Deal chain in Monday.com, you must:

  1. Import Accounts first and capture the Monday item IDs
  2. Import Contacts second, setting the Connect Boards column to link each contact to its parent Account item ID
  3. Import Deals third, linking each deal to its Contact and Account
  4. Import Activities last, linking to the relevant Contact or Deal

This ordering is non-negotiable. If you import in the wrong sequence, you'll have orphaned records with no way to programmatically reconnect them without a second pass.

You can add up to 60 Connect Boards Columns to any board. CRM Pro users can have up to 100K connected items per board.

Maintain a crosswalk table — a source-to-target ID map — throughout the migration so you can rebuild relationships after item creation. Do not rely on Monday's email-domain account association for migration correctness; use explicit Zoho IDs from your crosswalk instead of domain heuristics.

Handling Custom Modules

Monday.com's custom objects are technically iFrames that can display any HTML content. This is not the same as Zoho's native custom modules, which support full CRUD operations, field validation, workflows, and lookup relationships.

If your Zoho instance relies heavily on custom modules (e.g., "Vehicle Fleet" or "Property Listings"), you'll need to create additional Monday boards and link them using Connect Boards columns. Use subitems only when the source object is truly subordinate to a single parent. Accept that you lose schema enforcement, validation rules, and workflow triggers in the process.

Exporting Data from Zoho CRM: Methods and Limitations

CSV Export

In CSV format, you can export a maximum 200,000 records from a single module in one go. These will be 200,000 of the oldest records that satisfy your export criteria and will be zipped in .CSV format.

For modules exceeding 200K records, set criteria based on Created Time to create and download multiple exports.

Notes export is particularly limited: You can export a maximum of 3,000 notes at a time.

CSV export does not preserve relationships. You get flat files with Record IDs, but no mechanism to automatically map those IDs into Monday's Connect Boards columns during import. For why CSVs are problematic for SaaS data migrations, the short version is: relational integrity is the first casualty.

Zoho CRM REST API

If your requirement is to fetch under 2000 records, use the "page" and "per_page" parameters (page=1 to 10, per_page=200). If you want to paginate for more than 2000 records, use the "page_token" parameter you receive in the first response. Using the page tokens from the consecutive requests, you can navigate and fetch up to 100,000 records.

Zoho also supports COQL (CRM Object Query Language), which provides SQL-like filtering and can pull up to 2,000 records per call and 100,000 per unique criteria set. COQL is useful when you need targeted extractions rather than full module dumps.

Bulk Read API

For anything beyond 100K records per module, use the Bulk Read API: A maximum of two hundred thousand records can be exported in a single export job. The Bulk Read API runs asynchronously and returns a downloadable ZIP containing CSVs with the necessary unique identifiers (Account_ID, Contact_ID) preserved.

If attachments matter, Zoho's Data Backup API can export attachments and splits large outputs into multiple ZIP files up to 1 GB each.

Zoho CRM API Rate Limits

Since the API limits are based on the number of simultaneous active calls, there are no time-based API call restrictions in Zoho CRM. You can make any number of API calls in a minute, provided the number of concurrent calls are within the specified limits.

API Usage in Zoho CRM is calculated based on credits. The credits are deducted from your credit count, based on the type of the API call that you make. Each API call made will result in a reduction of 1 credit. However, for some APIs, credit reduction would be different. For example, for a "Convert Lead API", 5 credits will be reduced for a single API call.

Enterprise/Zoho One editions allow up to 5,000,000 credits in a 24-hour period, but resource-intensive APIs have a sub-concurrency limit of 10 across all editions.

Warning

Watch your credit burn rate. A full extraction of 500K records across modules can consume tens of thousands of credits. Run extractions during off-peak hours, monitor your API dashboard at Setup → Developer Hub → APIs & SDKs, and prefer Bulk Read or wide COQL windows over thousands of chatty single-page calls.

Monday.com API Constraints: Navigating Complexity Limits

Monday.com uses a GraphQL API at https://api.monday.com/v2. Unlike REST, every query has a computed complexity cost based on the depth and breadth of the fields requested.

Complexity defines the load that each call puts on the API. This limit restricts the heaviness of each query to help prevent excessive load and maintain optimal performance. You will receive a ComplexityException error if you hit the limit.

The API rate limits are based on the complexity level, which is limited to 10,000,000 per minute per account.

Rate limit errors will now return a 429 HTTP error code. Errors will now include the Retry-After header to indicate how long you need to wait before making another request. Monday has introduced per-minute request limits and a concurrency limit.

Practical Impact on Migration

Creating items via the API is where you'll hit limits fastest. Each create_item mutation carries a complexity cost, and when you're loading tens of thousands of records, you burn through the per-minute budget quickly. Monday's own developer guidance recommends queueing mutations rather than hammering the same board in parallel.

Pagination divides your results into smaller sets of data called pages. Use cursor-based pagination to return data in smaller batches. Example: Instead of returning 10,000 items in your call, use cursor-based pagination to return 200 items over 50 calls.

Consider evaluating whether the monday.com platform API is the right tool for your use case. Keep in mind that monday.com excels as a work management tool, not as a high-frequency database.

Info

Always include the complexity field in your mutations to track your remaining budget in real-time. This prevents blind retries that waste your quota.

Monday.com CSV Import Limits

If you're considering CSV import as a fallback:

Your imported file must have fewer than 50 columns and 8,000 rows. Your imported file must be 10 MB or less. You can only upload 100 files per account per hour.

Monday.com does not support importing subitems from CSV. Every row becomes a top-level item.

Monday's file import only loads the first sheet or tab and cannot import directly into the Updates section. These constraints make CSV viable only for small, flat datasets.

The limit stands at 10,000 items per board for all plan types except the Enterprise plan, which allows for 100,000 items. If your Zoho Contacts module has 200K records, you'll need to split across multiple Monday boards or archive aggressively before migration.

Formula Column Restrictions

Monday.com's Formula Column has API restrictions: the API only supports calculating up to 10,000 formula values per minute with at most five formula columns per request, and formulas containing mirror or connect-board columns are unsupported via the API. The Formula Column now supports Mirror in the UI, but the API's display_value for formula fields still does not return results for those formulas. If your Zoho CRM relies heavily on cross-module formula fields, calculate these values in your ETL middleware and push them to Monday as static text or number columns.

API Version Pinning

Danger

Do not trust old Monday migration snippets. On API versions 2025-04 and later, the raw value field for Connect Boards (board_relation) returns null. Read linked_item_ids or query the linked_items field instead. Use items_page and next_items_page — the old boards { items } pattern was removed from newer versions. Pin an API-Version header in production because Monday ships new API versions quarterly. This is exactly the kind of outdated example that breaks AI-generated migration scripts. See Why DIY AI Scripts Fail.

Migration Approaches Compared

Method 1: Native CSV Export → CSV Import

How it works: Export each Zoho module as CSV. Clean and reformat. Import into corresponding Monday boards via the UI import wizard.

When to use it: Fewer than 5,000 records total, no complex relationships, no custom modules.

Risks: CSV import cannot populate Connect Boards columns. You'll need to manually link every Contact to its Account — one by one in the Monday UI, or via a follow-up API script. For anything beyond a few hundred records, this is untenable.

Method 2: API-Based Migration (Zoho REST → Monday GraphQL)

How it works: Extract data from Zoho CRM via REST/Bulk API. Transform into Monday's column_values JSON format. Create items via Monday's create_item mutation, capturing returned item IDs to rebuild relationships.

When to use it: Any dataset where relationships matter, custom fields exist, or record counts exceed a few thousand.

Risks: Monday's complexity limits can throttle ingestion. Without proper retry logic and complexity tracking, you'll get partial loads and orphaned records. The engineering overhead to handle pagination, rate limits, and error logging is significant — this is exactly why DIY AI migration scripts fail when teams underestimate the work.

Method 3: Middleware (Zapier / Make)

How it works: Configure triggers and actions to sync records between Zoho and Monday. Typically trigger on "New Record" in Zoho, create item in Monday.

When to use it: Ongoing sync of new records going forward. Not for bulk historical migration.

Risks: Your monday.com plan's automation/integration limits apply (250/month on Standard, 25,000/month on Pro). Migrating 50K historical records through Zapier is neither practical nor cost-effective. These tools are trigger-action flows, not bulk migration engines.

Method 4: Third-Party ETL / Integration Platforms

How it works: Cloud-based mapping interface connects to both Zoho and Monday APIs, provides field-level mapping, and executes the transfer. Platforms like Skyvia support one-way import, bi-directional sync, transformations, lookups, and upsert.

When to use it: Mid-size datasets where you want a visual mapping UI but can accept some limitations on custom objects and relationships.

Risks: Most third-party tools struggle with Monday's Board/Item/Column architecture when translating deeply nested Zoho subforms and custom modules. You'll likely need manual post-migration cleanup for relationships.

Method 5: Managed Migration Service

How it works: A dedicated migration team handles extraction, transformation, loading, and relationship rebuilding end-to-end.

When to use it: Enterprise datasets, complex custom modules, zero tolerance for data loss, limited internal engineering bandwidth.

Comparison Table

Method Complexity Relationships Preserved Scalability Best For
CSV Export/Import Low ❌ No Small only < 5K records, flat data
API-Based (DIY) High ✅ Yes Large Dedicated dev team
Zapier / Make Low ❌ No Poor for bulk Ongoing sync only
Third-Party ETL Medium ⚠️ Partial Moderate Mid-size, basic relationships
Managed Service Handled ✅ Yes Excellent Enterprise, complex data

Pre-Migration Planning

Before extracting a single record:

  • Inventory every module in Zoho. Pull module metadata and field metadata first via the API. Count records per module, identify custom modules, list all custom fields and subforms.
  • Identify stale data. Inactive leads, closed-lost deals older than 2 years, duplicate contacts. Do not migrate what you don't need.
  • Document all relationships. Which modules have lookup fields? Which custom modules reference standard modules?
  • Map picklist values. Zoho's dropdown values must match Monday's label/status values exactly, or the import will default to blank.
  • Plan board sharding. If any Zoho module exceeds Monday's item-per-board limit, decide how to split — by business unit, region, or archive year.
  • Choose your cutover pattern. A big bang works for small orgs with a short freeze window. Phased works when business units or pipelines can move separately. Delta syncs between Zoho and Monday are exceptionally difficult due to the lack of parity in webhook structures — plan for a clean freeze window when possible.
  • Export a full backup of your Zoho org before touching anything.
Tip

Separate the migration from the implementation. Your team configuring Monday.com workflows, automations, and dashboards should be a different workstream from the team extracting and loading data. This reduces moving parts during go-live. See Why Data Migration Isn't Implementation for the rationale.

Step-by-Step Migration Process

Phase 1: Extract from Zoho CRM

For datasets under 100K records per module, use the REST API with pagination:

import requests
import time
 
ZOHO_BASE = "https://www.zohoapis.com/crm/v8"
ACCESS_TOKEN = "your_oauth_token"
 
def extract_module(module_name):
    records = []
    page = 1
    page_token = None
    
    while True:
        params = {"per_page": 200, "fields": "Last_Name,Email,Account_Name,Phone"}
        if page_token:
            params["page_token"] = page_token
        else:
            params["page"] = page
        
        resp = requests.get(
            f"{ZOHO_BASE}/{module_name}",
            headers={"Authorization": f"Zoho-oauthtoken {ACCESS_TOKEN}"},
            params=params
        )
        data = resp.json()
        
        if "data" in data:
            records.extend(data["data"])
        
        info = data.get("info", {})
        if not info.get("more_records", False):
            break
        
        page_token = info.get("next_page_token")
        if not page_token:
            page += 1
            if page > 10:  # page param limited to 10
                break
        
        time.sleep(0.1)  # respect concurrency
    
    return records
 
accounts = extract_module("Accounts")
contacts = extract_module("Contacts")
deals = extract_module("Deals")

For modules exceeding 100K records, switch to the Bulk Read API which supports up to 200,000 records per job and runs asynchronously.

You can also use a simple cURL call for quick verification:

curl 'https://www.zohoapis.com/crm/v8/Deals?fields=Deal_Name,Stage,Amount,Account_Name,Contact_Name&per_page=200&page=1' \
  -H 'Authorization: Zoho-oauthtoken $ZOHO_TOKEN'

Phase 2: Transform

Transformation is where most DIY migrations fail. You must:

  1. Build a crosswalk table: {zoho_account_id: monday_account_item_id} — this is your source-to-target ID map for rebuilding relationships
  2. Convert field types: Zoho date formats → Monday ISO format (YYYY-MM-DD), Zoho multi-select → Monday dropdown JSON, URLs → {"url": "...", "text": "..."} format
  3. Flatten subforms: Monday has no subform equivalent. Subform rows become either subitems (API-only, requires a separate GraphQL mutation after parent item creation) or separate board items
  4. Map picklist values: Every Zoho picklist value must have an exact match in Monday's dropdown/status column, or you need to create it first via the API
  5. Stamp every record with an immutable external_id column so you can rerun the migration safely and debug issues post-load
  6. Handle name fields: Zoho separates First_Name and Last_Name. Monday uses a single Item Name. Concatenate them, but preserve first/last in separate text columns if reporting requires it

Phase 3: Load into Monday.com

Load order is strict: Accounts → Contacts → Deals → Activities → Notes/Attachments

Disable all board automations before loading. This is critical — otherwise you'll trigger assignment rules, notification emails, and status changes on every imported record.

import requests
import json
import time
 
MONDAY_API = "https://api.monday.com/v2"
MONDAY_TOKEN = "your_api_token"
ACCOUNTS_BOARD_ID = "123456789"
 
def create_monday_item(board_id, item_name, column_values):
    query = '''
    mutation ($boardId: ID!, $itemName: String!, $columnValues: JSON!) {
        create_item(
            board_id: $boardId,
            item_name: $itemName,
            column_values: $columnValues
        ) { id }
    }
    '''
    variables = {
        "boardId": board_id,
        "itemName": item_name,
        "columnValues": json.dumps(column_values)
    }
    
    resp = requests.post(
        MONDAY_API,
        headers={
            "Authorization": MONDAY_TOKEN,
            "Content-Type": "application/json",
            "API-Version": "2024-10"
        },
        json={"query": query, "variables": variables}
    )
    
    result = resp.json()
    
    if "errors" in result:
        for error in result["errors"]:
            if "ComplexityException" in str(error):
                retry_after = error.get("extensions", {}).get("retry_in_seconds", 60)
                time.sleep(retry_after)
                return create_monday_item(board_id, item_name, column_values)
    
    return result.get("data", {}).get("create_item", {}).get("id")
 
# Build crosswalk table as you load
zoho_to_monday_accounts = {}
 
for account in accounts:
    monday_id = create_monday_item(
        ACCOUNTS_BOARD_ID,
        account["Account_Name"],
        {
            "text": account.get("Phone", ""),
            "email": {"email": account.get("Email", ""), "text": account.get("Email", "")}
        }
    )
    zoho_to_monday_accounts[account["id"]] = monday_id
    time.sleep(0.2)  # throttle to respect complexity budget

For JavaScript/Node.js teams, here's the equivalent mutation handler:

const axios = require('axios');
 
async function createMondayItem(boardId, itemName, columnValues) {
  const query = `
    mutation ($boardId: ID!, $itemName: String!, $columnValues: JSON!) {
      create_item (board_id: $boardId, item_name: $itemName, column_values: $columnValues) {
        id
      }
    }
  `;
 
  const variables = {
    boardId: boardId,
    itemName: itemName,
    columnValues: JSON.stringify(columnValues)
  };
 
  try {
    const response = await axios.post('https://api.monday.com/v2', {
      query: query,
      variables: variables
    }, {
      headers: {
        'Authorization': process.env.MONDAY_API_TOKEN,
        'Content-Type': 'application/json',
        'API-Version': '2024-10'
      }
    });
 
    if (response.data.errors) {
      if (response.data.errors[0].message.includes('ComplexityException')) {
        const retryAfter = response.data.errors[0]?.extensions?.retry_in_seconds || 60;
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        return createMondayItem(boardId, itemName, columnValues);
      }
      throw new Error(response.data.errors[0].message);
    }
 
    return response.data.data.create_item.id;
  } catch (error) {
    console.error('Migration failed for item:', itemName, error.message);
  }
}

Phase 4: Rebuild Relationships

After loading Contacts, link each one to its Account using the Connect Boards column:

def link_contact_to_account(contact_item_id, account_item_id, board_id, connect_column_id):
    query = '''
    mutation ($boardId: ID!, $itemId: ID!, $columnId: String!, $value: JSON!) {
        change_column_value(
            board_id: $boardId,
            item_id: $itemId,
            column_id: $columnId,
            value: $value
        ) { id }
    }
    '''
    variables = {
        "boardId": board_id,
        "itemId": contact_item_id,
        "columnId": connect_column_id,
        "value": json.dumps({"item_ids": [int(account_item_id)]})
    }
    
    resp = requests.post(
        MONDAY_API,
        headers={"Authorization": MONDAY_TOKEN, "Content-Type": "application/json"},
        json={"query": query, "variables": variables}
    )
    return resp.json()

Do not rely on Monday's email-domain account association for migration correctness. It's helpful for day-to-day CRM use but not reliable enough as a migration join rule. Use explicit Zoho IDs from your crosswalk table to connect Contacts to Accounts and Deals to both Contacts and Accounts.

Phase 5: Migrate Notes and Attachments

Migrate notes and files after the core items exist. Zoho exposes Notes as a related API. On Monday, notes should become item updates — not Activities board records.

From Monday API version 2025-10 onward, you can preserve the original update creation date, which is critical for maintaining accurate historical timelines.

Attachments require multipart file uploads to Monday's file columns — a separate and significantly slower process from item creation. Plan for attachment migration to take considerably longer than the core data load.

Phase 6: Validate

Run the full migration against a Monday.com sandbox (a separate workspace or test board) first. Validate everything before touching production.

Validation checklist:

  • Record count per board matches source module count (minus intentionally excluded records)
  • Spot-check 50 records per board: field values, picklist values, dates
  • Verify Connect Boards links on 100% of Contacts (every Contact should link to an Account)
  • Verify Deal → Contact → Account chain on a sample of 20 deals
  • Check for empty fields that should have data (common: phone numbers, addresses)
  • Verify no automations fired incorrectly during import
  • Confirm picklist/dropdown values rendered correctly — no blank defaults

Zoho exposes record counts by module via the API, which is useful for automated reconciliation. Use those counts as your source of truth.

Edge Cases That Cause Silent Data Loss

Duplicate Records

Zoho's deduplication rules don't transfer. Run deduplication before extraction, or build matching logic (email + company name) into your transform step. Do not let a target-side import wizard invent dedupe rules for you.

Multi-Level Relationships

Account → Contact → Deal → Activity is a four-level chain. If any link in the chain fails to import, downstream records become orphaned. Always validate parent records exist before loading children.

Attachments and Files

Zoho stores attachments per record via the Related Records API. Monday.com supports file columns, but uploading files via API requires multipart requests — a separate and slower process from item creation. Files belong in file columns or linked storage, not buried in free text.

Subforms

Zoho subforms (e.g., line items on a Deal) have no Monday equivalent. Options:

  • Flatten into a long-text column (simplest, loses structure)
  • Create subitems via API (requires a separate GraphQL mutation after the parent item exists)
  • Create a separate linked board (most flexible, highest effort)

Notes vs. Activities

On Monday CRM, emails and standard notes are not the same thing as Activities board records. The Activities board is for calls, meetings, and similar logged events. If you collapse all Zoho history into Activities, users lose the difference between a note, a scheduled activity, and email context. Map accordingly.

Automations Firing During Import

Disable all board automations before running a CRM import. Turn them back on after you've verified the data. Otherwise, you'll trigger assignment rules, notification emails, and status changes on every imported record.

API Failures and Partial Loads

All requests count towards the stated limits, even those that fail or return an error. You can prevent unnecessary API usage by waiting for the time indicated in the retry_in_seconds field before retrying the call.

Build an error log that captures every failed record with its Zoho ID, the error message, and the payload. After the main load completes, run a retry pass on failures only. At minimum, log: source_module, source_id, target_board_id, target_item_id, phase, retry_count, and the vendor request ID when available. That turns a failed row from a mystery into a repair task.

Missing Owners and Stale Picklist Values

Zoho record owners may not have Monday user accounts yet. Map owner fields to a text column during migration, then reassign after user provisioning is complete. Stale picklist labels in Zoho that don't exist in Monday's dropdown configuration will import as blank — audit your picklists before extraction.

Limitations You Must Accept

Constraint Zoho CRM Monday.com
Custom objects Full native modules with CRUD, lookups, workflows Iframe-based apps — not queryable via standard API
Subforms Supported with parent-child relationships Not supported — flatten or use subitems
Record cap per container No practical limit 10K items/board (100K Enterprise)
CSV import cap N/A 8,000 rows, 50 columns per file
API pagination 200 records/request, up to 100K via page tokens Cursor-based, complexity-throttled
Formula columns Full formula support No mirror/connect-board column support in formulas via API
Notes Standalone module, linked to records Embedded as item updates — no standalone module

Sample Data Mapping Table

Zoho CRM Field Zoho Type Monday.com Column Monday Type Transform Notes
Account_Name Text Item Name Name (primary) Direct map
Account ID (Zoho) System ID External ID Text (Hidden) Used for crosswalk during ETL
Phone Phone Phone Phone Include country code
Website URL Website Link Map as {"url": "...", "text": "..."}
Industry Picklist Industry Dropdown Match picklist values exactly
Annual_Revenue Currency Revenue Numbers Strip currency symbol
Contact.First + Last Name Text Item Name Name Concatenate; preserve in separate text columns if needed
Contact.Email Email Email Email Map as {"email": "...", "text": "..."}
Contact.Account_Name Lookup Account Connect Boards Use Account item_id from crosswalk
Deal.Deal_Name Text Item Name Name Direct map
Deal.Stage Picklist Stage Status Map each stage to a Monday status label
Deal.Amount Currency Deal Value Numbers Strip formatting
Deal.Closing_Date Date Close Date Date Convert to ISO YYYY-MM-DD
Deal.Contact_Name Lookup Contact Connect Boards Use Contact item_id from crosswalk
Lead.Lead_Source Picklist Source Dropdown Match values exactly
Lead.Lead_Status Picklist Status Status Map to Monday status labels
Task.Subject Text Item Name Name Direct map
Task.Due_Date Date Date Date Convert to ISO
Task.Related_To Lookup Connected Item Connect Boards Use parent item_id
Subform Rows Subform Subitems Subitem Requires separate GraphQL mutation

Post-Migration Tasks

  1. Re-enable board automations after verifying imported data looks correct.
  2. Rebuild automations in Monday.com. Zoho workflows, blueprint processes, and assignment rules do not transfer. Rebuild them using Monday's automation recipes. Do not attempt to migrate Zoho Workflows programmatically.
  3. Configure Emails & Activities. Integrate Gmail or Outlook with Monday CRM to resume email tracking on the new platform. The Emails & Activities feature is preinstalled on entity boards.
  4. Train your team. Monday's board-based interface is fundamentally different from Zoho's module-based navigation. Budget time for onboarding — especially for sales reps who are used to Zoho's record-centric views.
  5. Run UAT. Give 3–5 sales reps access to the populated Monday boards for 48 hours. Ask them to:
    • Find a specific deal and verify the contact and account are linked
    • Check that historical notes/activities appear on the correct records
    • Confirm pipeline stages match what they see in Zoho
  6. Monitor for 2 weeks. Watch for data inconsistencies, broken links, and missing records that surface during daily use.
  7. Keep Zoho active for 30 days post-migration as a rollback safety net. Do not cancel your Zoho subscription until UAT is complete and stakeholders sign off.

If you need a temporary coexistence period, keep the sync narrow. Move only the fields required for business continuity, monitor drift daily, and retire the bridge once users stop working in Zoho.

Best Practices Summary

  • Back up everything first. Full Zoho CRM backup before any extraction.
  • Run a test migration on a subset (top 50 accounts + related contacts and deals) before committing to a full load.
  • Load in dependency order: Accounts → Contacts → Deals → Activities.
  • Keep external_id on every target board for reruns and debugging.
  • Track complexity budget in real-time by including the complexity field in every Monday API mutation.
  • Pin your Monday API version to avoid breaking changes during the migration window.
  • Disable Monday automations before import, re-enable after validation.
  • Build an error log — every failed record gets logged with its Zoho ID, error code, and payload.
  • Validate relationships, not just record counts. A migration with 100% record counts but 50% broken links is a failed migration.
  • Batch writes and honor Retry-After or retry_in_seconds.
  • Shard large datasets before you hit board or linkage caps.
  • Rebuild automations after the data model is stable, not during initial load.

When to Use a Managed Migration Service

Build in-house when:

  • Your dataset is under 10K total records
  • You have no custom modules
  • Your engineering team has GraphQL experience and bandwidth
  • You're comfortable with a 2–4 week timeline including debugging

Don't build in-house when:

  • You have complex multi-level relationships (Account → Contact → Deal → Activity)
  • Custom modules with subforms are involved
  • Your dataset exceeds 50K records
  • You need zero downtime and a guaranteed timeline
  • Your engineering team's time is better spent configuring Monday.com workflows

The hidden costs of DIY migration are real: engineering hours debugging Monday's complexity limits, data cleanup passes for broken relationships, and the opportunity cost of engineers not building product. The hidden work is not calling two APIs — it is schema design, batch control, retry handling, crosswalk management, UAT, rollback planning, and rebuilding links without text-based guesswork. For an honest comparison of build vs. buy, see In-House vs. Outsourced Data Migration: A Realistic Cost & Risk Analysis.

ClonePartner handles the translation of Zoho's relational modules into Monday.com's Board and Connect Boards architecture without losing links. We bypass the 200K CSV export limit via direct API extraction with automated pagination, calculate and respect Monday's complexity limits to prevent throttling, and handle the transformation of subforms and unsupported formula fields into Monday-compatible structures. We take the risk off your engineering team so they can focus on configuring Monday.com workflows — not debugging GraphQL pagination at 2am.

For a look at how we approach migrations operationally, see How We Run Migrations at ClonePartner.

Frequently Asked Questions

Can I migrate Zoho CRM data to Monday.com using CSV export?
You can, but CSV import into Monday.com is capped at 8,000 rows and 50 columns per file, cannot populate Connect Boards columns, and does not support subitems. All Account-to-Contact and Contact-to-Deal relationships are lost and must be rebuilt manually or via a follow-up API script. CSV is only practical for small, flat datasets under 5,000 records.
What are the Monday.com API rate limits for data migration?
Monday.com enforces a complexity limit of 10,000,000 per minute per account. Each API call has a computed complexity cost based on query depth. Rate limit errors return a 429 HTTP code with a Retry-After header. Include the complexity field in your mutations to track your remaining budget in real-time.
How do I map Zoho CRM modules to Monday.com boards?
Zoho Accounts map to Monday's Accounts board, Contacts to the Contacts board, Deals to the Deals board, and Leads to the Leads board. Relationships are preserved via Connect Boards columns, but you must import in dependency order (Accounts first, then Contacts, then Deals) and programmatically set connections using Monday item IDs from a crosswalk table.
Does Monday.com support custom objects like Zoho CRM?
No. Monday.com's custom objects are iframe-based app views — not native database tables with CRUD operations and lookup relationships like Zoho's custom modules. You'll need to create additional boards for custom module data, but you lose schema enforcement, validation rules, and workflow triggers.
How many records can a Monday.com board hold?
Monday.com limits boards to 10,000 items on all plans except Enterprise, which allows 100,000 items. CRM Pro users get 100K connected items on up to five boards. If your Zoho module has more records than this limit, you'll need to split data across multiple boards or archive stale records before migration.

More from our Blog

In-House vs. Outsourced Data Migration: A Realistic Cost & Risk Analysis
General

In-House vs. Outsourced Data Migration: A Realistic Cost & Risk Analysis

Choosing between in-house and outsourced data migration? The sticker price is deceptive. An internal team might seem free, but hidden risks like data loss, project delays, and engineer burnout can create massive opportunity costs. This realistic analysis compares the true ROI, security implications, and hidden factors of both approaches, giving you a clear framework to make the right decision for your project.

Raaj Raaj · · 8 min read