---
title: "How to Migrate Ivanti Neurons to ServiceNow: ITSM Migration Guide"
slug: how-to-migrate-ivanti-neurons-to-servicenow-itsm-migration-guide
date: 2026-07-17
author: Raaj
categories: [Migration Guide, Ivanti Neurons ITSM, ServiceNow]
excerpt: "Step-by-step guide to migrate Ivanti Neurons to ServiceNow. Covers ITSM object mapping, real API limits, CMDB relationship handling, and load ordering."
tldr: "Migrating Ivanti Neurons to ServiceNow takes 2 to 4 weeks, requires strict CMDB load ordering, and is constrained by Ivanti's 100K daily API call limit and 50K row export cap."
canonical: https://clonepartner.com/blog/how-to-migrate-ivanti-neurons-to-servicenow-itsm-migration-guide/
---

# How to Migrate Ivanti Neurons to ServiceNow: ITSM Migration Guide


# How to Migrate Ivanti Neurons to ServiceNow: ITSM Migration Guide

> [!NOTE]
> **Quick answer:** Migrating from Ivanti Neurons to ServiceNow is a moderate-to-high complexity ITSM migration. It is not a lift-and-shift. Ivanti Neurons uses a flat, endpoint-centric business object model. ServiceNow uses a CMDB-first relational architecture where nearly every record inherits from the `task` table. The biggest risk is breaking CI-to-incident and CI-to-change relationships during load. Ivanti's 50,000-row Excel export cap and 100,000 daily API call limit make native exports unviable for enterprise datasets. Teams with fewer than 10,000 total records and no complex CMDB can run this in-house. Everyone else should use a managed migration service or allocate a dedicated engineer for 3 to 6 weeks.

## Why do enterprise IT teams migrate from Ivanti Neurons to ServiceNow?

The most common driver is workflow breadth. Ivanti Neurons is an endpoint-centric platform that unifies ITSM, UEM, patch management, and security automation. ServiceNow is a CMDB-first enterprise PaaS built for cross-departmental workflow orchestration across IT, HR, SecOps, and facilities. Teams outgrow Ivanti when they need a single data model spanning five or more departments.

For a full architectural comparison, see our [ServiceNow vs Ivanti Neurons (2026) guide](https://clonepartner.com/blog/blog/servicenow-vs-ivanti-neurons-2026-architecture-tco-migration/).

Three architectural differences make this migration non-trivial:

1. **Data model structure.** Ivanti Neurons stores Incidents, Service Requests, Problems, and Changes as independent business objects with `RecId` primary keys and relationship links. ServiceNow inherits them all from a single `task` table, meaning every record shares a common schema with type-specific extensions.
2. **CMDB design.** Ivanti's CMDB is optimized for endpoint and device data fed by passive and active discovery. ServiceNow's CMDB uses a class hierarchy (`cmdb_ci` and dozens of child tables like `cmdb_ci_server`, `cmdb_ci_win_server`) with relationship tables (`cmdb_rel_ci`) that encode upstream/downstream dependencies. You cannot dump flat CI data into ServiceNow's base tables and expect operational value.
3. **API architecture.** Ivanti exposes an OData v4 REST API at `/api/odata/businessobject/{objectname}`. ServiceNow uses a proprietary Table API at `/api/now/table/{tableName}` plus an Import Set API for bulk loads. The pagination, auth, and throttling models are completely different. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/RestAPI-Introduction.htm?Highlight=api))

## Migration load order dependency graph

Load order is the single most important factor in a ServiceNow migration. If you load an Incident before you load the User who created it, the `caller_id` field will be blank. If you load tickets before CIs, every `cmdb_ci` reference field will be empty. There is no native bulk backfill mechanism — you would need a custom fix script.

```
Users (sys_user)
  └─► Groups (sys_user_group) + Membership (sys_user_grmember)
        └─► CMDB CIs (cmdb_ci + child class tables)
              └─► CI Relationships (cmdb_rel_ci)
                    └─► Incidents (incident)
                    └─► Problems (problem)
                    └─► Changes (change_request)
                    └─► Requests (sc_request) → RITMs (sc_req_item)
                          └─► Journal Entries (sys_journal_field)
                                └─► Attachments (sys_attachment)
```

Every arrow represents a `sys_id` foreign key dependency. Loading out of order produces records with null reference fields that pass Import Set validation but break operational workflows, reports, and SLA calculations downstream.

## What is the Ivanti Neurons to ServiceNow object mapping?

Every migration starts with object mapping. Most core records can be migrated, but some must be re-modeled on the way in. The safest migrations preserve source keys, class fidelity, and chronological history instead of forcing everything into flat tables.

| Ivanti Neurons Object | ServiceNow Object | Table Name | Notes |
|---|---|---|---|
| Incidents | Incidents | `incident` | Map state values carefully. ServiceNow uses numeric codes: 1=New, 2=In Progress, 3=On Hold, 6=Resolved, 7=Closed. Keep Ivanti `RecId` in a trace field. |
| Service Requests | Requested Items (RITMs) | `sc_req_item` | Not 1-to-1. ServiceNow creates a parent request (`sc_request`) and one or more RITMs per catalog item. |
| Problems | Problems | `problem` | Direct mapping. Watch for custom problem categories that need picklist translation. |
| Changes | Change Requests | `change_request` | Ivanti Change types must map to ServiceNow's Normal, Standard, or Emergency types. Rebuild planned dates, risk, approvals, and linked CIs explicitly. |
| Configuration Items | CMDB CIs | `cmdb_ci` + child tables | The hardest mapping. Ivanti CIs must be classified into the correct ServiceNow CI class. Load CIs before tickets. |
| Employees | Users | `sys_user` | Ivanti uses `RecId` as primary key. ServiceNow uses `sys_id`. Build a crosswalk table. |
| Teams | Groups | `sys_user_group` | Map Ivanti Team membership to `sys_user_grmember` records. |
| Notes / Journals | Journal Entries | `sys_journal_field` | Must be inserted as `work_notes` or `comments` on the parent record. Differentiate between customer-visible comments and internal work notes. |
| Attachments | Attachments | `sys_attachment` | Use ServiceNow's dedicated Attachment API. REST payload limit defaults to 10MB. |
| Knowledge Articles | Knowledge Articles | `kb_knowledge` | Requires mapping to ServiceNow Knowledge Base and Category structures. |
| Approval Records | Approvals | `sysapproval_approver` | Map Ivanti approval chain entries to ServiceNow approval records linked to the parent change or request. |
| SLA Records | Task SLA | `task_sla` | Active SLA clocks cannot be migrated with accurate elapsed time. Historical SLA data can only be preserved as static fields. Recreate SLA definitions natively. |
| Catalog Categories | Catalog Categories | `sc_category` | Map Ivanti service catalog structure to ServiceNow categories before loading RITMs. |
| Cost Centers | Cost Centers | `cmn_cost_center` | Map before loading users if cost center is a required field on `sys_user`. |

### Field-level mapping details

Ivanti Neurons field names are not standardized across deployments. The internal business object name and the fields it exposes vary by tenant configuration and product version. Note that some API features and export capabilities differ between Ivanti Neurons for ITSM Standard vs. Premium tiers — verify your licensing before assuming API access. Always retrieve `/api/odata/businessobject/{objectname}/$metadata` to confirm the actual field surface for a specific tenant before building mappings. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Metadata.htm))

Key transformations:

- **Store the source key.** Keep Ivanti `RecId` on every target table as a unique external key (e.g., `u_ivanti_recid`). This is your crosswalk anchor for every reference resolution and your audit trail after go-live.
- **Map lookups from the key field, not the label.** Ivanti responses expose pairs such as `Category` and `Category_Valid`, `OwnerTeam` and `OwnerTeam_Valid`, plus user links like `ProfileLink_RecID`. Use the `_Valid` ID side for deterministic transforms, not the display label. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Get-Business-Object-by-Filter.htm))
- **Picklist and enum values.** Ivanti stores picklist values as display strings. ServiceNow often stores them as integers or `sys_id` references to `sys_choice` records. Every picklist field needs a value map. If an Ivanti Incident references a priority level that does not exist in your ServiceNow dictionary, the Import Set will either reject the record or insert a blank value.
- **Normalize timestamps.** Ivanti metadata exposes date fields as `Edm.DateTimeOffset`. ServiceNow expects `yyyy-MM-dd HH:mm:ss` in UTC or the instance timezone. Handle timezone conversion explicitly before load. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Metadata.htm))
- **Preserve original timestamps.** Without explicit handling, all migrated records will show the import timestamp as their `sys_created_on` and `sys_updated_on` values. To preserve original dates, set the system property `glide.sys.date_format` appropriately and use Import Set field mapping to explicitly set `sys_created_on` to the original Ivanti timestamp. Alternatively, use a `sys_import_set_row` onBefore transform script to override system date fields. This is critical for audit trails and compliance reporting.
- **Discover relationships from metadata.** Ivanti publishes `NavigationProperty` metadata including incident-to-CI and incident-to-journal relationships. Use these to build your extraction graph before writing transforms.

> [!WARNING]
> **Service requests are the most common false 1-to-1 mapping.** Ivanti's service request model is subscription-and-parameter driven with its own `subscriptionId`, `serviceReqData`, and parameter RecIDs. ServiceNow generates a parent `sc_request` plus one or more `sc_req_item` records. If you only load RITMs, you lose the request wrapper and variable context. Design this mapping explicitly. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Create-a-Service-Request.htm?Highlight=service+request))

### What has no clean equivalent on ServiceNow?

Ivanti Neurons for Discovery feeds endpoint data — installed software, vulnerabilities, compliance state — directly into the Ivanti CMDB. ServiceNow's equivalent is ITOM Visibility, a separately licensed module. Discovery data from Ivanti cannot be migrated into ServiceNow's CMDB without ITOM Visibility or a third-party Service Graph Connector. Plan to re-discover endpoints after go-live or accept that this data will not transfer.

The Ivanti ServiceNow connector also does not help here. Ivanti documents that connector as gathering users, devices, and related incidents **from ServiceNow into Ivanti Neurons**. It does not support the reverse direction for a full ITSM migration. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/CLOUD/vNow/Connectors/connector-ServiceNow.htm))

## How do you extract data from Ivanti Neurons? Migration approaches compared

There are three viable extraction methods. Each has hard constraints that dictate which one fits your scenario.

### Native CSV or Excel export

Ivanti Neurons limits Excel and CSV exports to **50,000 records per export** by default. On-premise customers can change this value in the `web.config` file by modifying `MaximumRowsForExcelExport`. Cloud tenants cannot change this limit. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_us/ism/2025/admin-user/content/configure/QuickActions/Classical%20Action%20Designer/templates/Export%20to%20Excel.htm))

For any dataset exceeding 50,000 rows, native export requires splitting into multiple filtered batches, which makes it impractical for historical ticket data or large CMDBs. CSV exports also strip relationship data between objects, so you lose CI links, journal associations, and request hierarchies.

### REST API extraction

Ivanti Neurons for ITSM exposes an OData v4 REST API under `/api/odata/businessobject/`. Ivanti supports session keys, REST API keys, or OIDC authorization depending on your tenant configuration. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2026/admin-user/Content/Configure/API/Authentication_of_APIs.htm))

Pagination uses `$top` and `$skip` parameters. OData reads default to **25 records per request**, with a configurable maximum of **100 per call**. Ivanti supports eight filter operators: `eq`, `ne`, `lt`, `le`, `gt`, `ge`, `or`, and `and`. Use `$select` to reduce payload size by requesting only the fields you need. ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Get-Business-Object-by-Number-of-Records.htm))

Ivanti throttles API access after **100,000 API calls in a 24-hour period**. Exceeding that rate causes responses to be intentionally slowed.

> [!TIP]
> **Throughput math matters.** At 100 records per call and a throttle point of 100,000 API calls per 24 hours, a flat extract tops out at 10,000,000 rows per day on paper. Real ITSM migrations run far below that because journals, attachments, and relationship calls consume the same daily budget. A naive pull of 100,000 incidents plus one journal call per incident already burns about 101,000 calls before you touch attachments. Pre-calculate your total API call count before starting extraction.

### Managed migration service

A managed service handles extraction, transformation, and load as a turnkey operation. The service typically uses optimized concurrent extraction scripts that batch requests efficiently, handle auth token rotation, implement retry logic with exponential backoff, and manage the crosswalk table automatically. This is the only reliable method for achieving a [zero-downtime help desk data migration](https://clonepartner.com/blog/blog/zero-downtime-help-desk-data-migration/).

**On-premise Ivanti instances:** If your Ivanti Neurons deployment is on-premise and your ServiceNow instance needs to pull data from it, you will need a ServiceNow MID Server deployed in your network to bridge the connection. The MID Server handles authentication, encryption, and firewall traversal for inbound REST calls. Factor MID Server setup into your timeline — it typically requires 1 to 2 days for installation, configuration, and validation.

| Approach | Best For | Max Volume | Complexity | Risk |
|---|---|---|---|---|
| CSV/Excel Export | Under 50K records, simple structure | 50,000 rows per export | Low | Data loss on large sets, broken relationships |
| REST API (DIY) | 50K–500K records, dedicated dev team | Bound by 100K API calls/day | High | Broken relationships, session expiry, rate limits |
| Managed Service | Any volume, complex CMDB | Unlimited (parallelized) | Low (for your team) | Lowest — but verify vendor handles coalesce, rollback, and timestamp preservation |

Review our [Help Desk Data Migration Playbook](https://clonepartner.com/blog/blog/help-desk-data-migration-playbook/) to understand what data you should move and what you should leave behind.

## What are the real API limits for loading data into ServiceNow?

ServiceNow provides two primary inbound APIs for migration: the **Table API** and the **Import Set API**.

The **Table API** writes directly to target tables. Each record requires a separate POST request. ServiceNow uses semaphore pools to manage concurrent API transactions. The default `API_INT` semaphore pool allows 4 simultaneous threads per node. When the queue is full, the platform returns HTTP 429 errors with a `Retry-After` header. You cannot simply blast data into the Table API. ([servicenow.com](https://www.servicenow.com/docs/r/api-reference/rest-api-explorer/inbound-REST-API-rate-limiting.html))

The **Import Set API** stages data into a temporary import table, then processes it through transform maps into the target table. Use the `insertMultiple` endpoint for batched loads. The default maximum batch size for `insertMultiple` is **100 records per call** in some configurations (controlled by the `com.glide.import.max_import_set_insert_count` property). For large migrations, break datasets into jobs of under **100,000 records each** to maintain predictable transform behavior and easier restart logic. ([servicenow.com](https://www.servicenow.com/docs/r/api-reference/rest-apis/c_ImportSetAPI.html))

### Coalesce fields: preventing duplicates on re-runs

Every Import Set transform map requires **coalesce field** configuration. A coalesce field tells ServiceNow how to determine whether an incoming record should create a new row or update an existing one. For migration:

- **Users (`sys_user`):** Coalesce on `email` or `user_name`, not `sys_id`. This prevents duplicate user records on re-runs.
- **CIs (`cmdb_ci` child tables):** Coalesce on the Ivanti `RecId` field you stored as `u_ivanti_recid`, or use ServiceNow's Identification and Reconciliation Engine (IRE) rules which match on fields like `serial_number` + `name`.
- **Incidents, Changes, Problems:** Coalesce on the Ivanti `RecId` trace field.

If you do not set coalesce fields and re-run an import batch, ServiceNow will create duplicate records. This is the single most common error in DIY migrations and the reason test-and-re-run cycles produce data quality issues that compound over time.

One critical gotcha: the Import Set API returns **HTTP 200 even when the transform logic fails**. Your migration scripts must check the `status` key in the response body, not just the HTTP status code.

ServiceNow's inbound REST payload size defaults to **10MB** (controlled by `glide.rest.max_content_length`). Attachments larger than 10MB must be sent through the dedicated Attachment API, which stores binary content in `sys_attachment` and `sys_attachment_doc` chunk tables. The Attachment API uploads one file per request.

ServiceNow does not publish a universal records-per-hour number for inbound REST. Throughput depends on your rate limit rules, instance tier, node count, and semaphore configuration. Build in exponential backoff and checkpointing from the start.

### Scoped apps vs. global scope for migration artifacts

Build your migration staging tables, transform maps, and migration scripts inside a **scoped application** rather than global scope. This isolates migration artifacts from your production ServiceNow configuration, makes cleanup straightforward (delete the scoped app after migration), and prevents naming collisions with existing global business rules or transform maps. Use the naming convention `x_yourcompany_migration` for the scope.

For a deeper look at ServiceNow-specific migration pitfalls, see [10 ServiceNow Data Migration Challenges](https://clonepartner.com/blog/blog/10-servicenow-data-migration-challenges-how-to-overcome-them/).

## What is the correct step-by-step migration process?

### Step 1: Freeze scope and extract metadata

Lock the migration scope and stop schema drift before you start mapping. Pull Ivanti field and relationship metadata from the OData `$metadata` endpoint. Build crosswalk tables for users, groups, CIs, and tasks. Identify which Ivanti custom fields exist and map them to ServiceNow dictionary entries. Clean up inactive users and obsolete configuration items now — they are cheaper to exclude than to migrate and delete later.

**Handle edge cases during scoping:**
- **Deleted or merged users.** If an Ivanti `ProfileLink_RecID` references a user that was deleted or merged before extraction, decide now: map the reference to a placeholder "Migrated User" account in ServiceNow, or null the field. Nulling it loses assignment history. A placeholder preserves the audit trail without creating a real login.
- **Decommissioned CIs.** CIs marked as retired or decommissioned in Ivanti should be migrated into ServiceNow with an `install_status` of "Retired" (7) rather than excluded entirely. Historical tickets reference these CIs, and excluding them creates orphaned `cmdb_ci` references.
- **Deactivated groups.** Import inactive Ivanti Teams as inactive ServiceNow groups (`active=false`). Historical tickets assigned to these groups retain valid references.

### Step 2: Load Users and Groups

Extract all Employees and Teams from Ivanti via the OData API. Transform these into ServiceNow `sys_user` and `sys_user_group` records. Load them first because every subsequent record — incidents, CIs, changes — will reference these `sys_id` values. Store the resulting Ivanti `RecId` → ServiceNow `sys_id` mapping in your crosswalk table.

Set coalesce on `email` or `user_name` for users and on `name` for groups to prevent duplicates on re-runs.

### Step 3: Migrate and classify CMDB Configuration Items

Export all CIs and their types from Ivanti. Classify each into the correct ServiceNow CI class table (`cmdb_ci_computer`, `cmdb_ci_server`, `cmdb_ci_win_server`, etc.). Load CIs via Import Sets with transform maps targeting the correct child table for each CI class. Use the **ServiceNow Identification and Reconciliation Engine (IRE)** to evaluate incoming CIs against existing records and prevent duplicates — configure IRE identifier rules with match criteria such as `serial_number` + `name` or `u_ivanti_recid`.

After all CIs exist with valid `sys_id` values, load the `cmdb_rel_ci` relationship records to establish upstream/downstream links. See the dedicated CMDB section below for details.

### Step 4: Load ITSM ticket records

Query the Ivanti API for Incidents, Service Requests, Problems, and Changes. Use your crosswalk table to replace every Ivanti `RecId` reference with the corresponding ServiceNow `sys_id` for `assigned_to`, `caller_id`, `assignment_group`, and `cmdb_ci` fields. Map Ivanti Service Requests to a parent `sc_request` plus child `sc_req_item` records.

Push the transformed tickets into ServiceNow Import Sets. Use Transform Maps to move the data from staging tables into the final target tables. **Disable business rules and email notifications during this step** to prevent ServiceNow from triggering SLA evaluations and emailing users about old ticket updates. Specifically:

- Set the system property `glide.email.outbound.active` to `false` during migration loads.
- Use `current.setWorkflow(false)` in transform scripts to skip business rules on each record.
- After the load completes, re-enable both before proceeding to validation.

### Step 5: Migrate Journal Entries and Attachments

Insert Ivanti Notes as `work_notes` or `comments` entries on the parent ServiceNow ticket record. These depend on the parent ticket existing, so they must come after Step 4. Replay journals in chronological order to preserve a readable activity stream. Preserve original timestamps using Import Set field mapping rules that set `sys_created_on` to the original Ivanti timestamp — this requires the `sys_import_set_row` manipulation approach or the `glide.importset.preserve.sys_created_on` property.

Load attachments last using ServiceNow's dedicated Attachment API. Each attachment links to a parent record via `table_name` and `table_sys_id`. Files over 10MB must be chunked.

### Step 6: Validate and reconcile

See the dedicated Validation and Testing section below. Run all three validation layers before declaring the migration complete.

Here are the key API calls that form the migration pipeline:

```text
# Ivanti extraction
GET  /api/odata/businessobject/Incidents?$select=RecId,IncidentNumber,Status,OwnerTeam_Valid,ProfileLink_RecID&$filter=LastModDateTime ge 2026-07-01T00:00:00Z&$top=100&$skip=0
GET  /api/odata/businessobject/incidents('<RecId>')/IncidentContainsJournal
GET  /api/rest/Attachment?ID=<RecId>

# ServiceNow load
POST /api/now/import/u_ivanti_incident_stg/insertMultiple
POST /api/now/attachment/file?table_name=incident&table_sys_id=<sys_id>&file_name=<name>
```

And a Python example for paginated Ivanti extraction with rate limit handling, exponential backoff, and session re-authentication:

```python
import requests
import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

IVANTI_BASE = "https://your-tenant.ivanti.cloud"
MAX_RETRIES = 5
CHECKPOINT_FILE = "extraction_checkpoint.json"

def get_session_token(username, password, tenant):
    resp = requests.post(f"{IVANTI_BASE}/api/rest/authentication/login",
        json={"UserName": username, "Password": password, "tenant": tenant})
    resp.raise_for_status()
    return resp.json()["access_token"]

def save_checkpoint(object_name, skip_value):
    import json
    with open(CHECKPOINT_FILE, "w") as f:
        json.dump({"object": object_name, "skip": skip_value}, f)

def load_checkpoint(object_name):
    import json, os
    if os.path.exists(CHECKPOINT_FILE):
        with open(CHECKPOINT_FILE) as f:
            data = json.load(f)
            if data.get("object") == object_name:
                return data["skip"]
    return 0

def fetch_all_records(username, password, tenant, object_name, page_size=100):
    token = get_session_token(username, password, tenant)
    records = []
    skip = load_checkpoint(object_name)
    token_refresh_interval = 500  # re-auth every 500 requests
    request_count = 0

    while True:
        # Re-authenticate periodically to avoid session expiry
        if request_count > 0 and request_count % token_refresh_interval == 0:
            try:
                requests.delete(f"{IVANTI_BASE}/api/rest/authentication/logout",
                    headers={"Authorization": f"Bearer {token}"})
            except Exception:
                pass
            token = get_session_token(username, password, tenant)
            logger.info(f"Re-authenticated at request {request_count}")

        retries = 0
        while retries < MAX_RETRIES:
            try:
                resp = requests.get(
                    f"{IVANTI_BASE}/api/odata/businessobject/{object_name}",
                    headers={"Authorization": f"Bearer {token}"},
                    params={"$top": page_size, "$skip": skip},
                    timeout=30)

                if resp.status_code == 429:
                    wait_time = min(60 * (2 ** retries), 3600)
                    logger.warning(f"Rate limited. Waiting {wait_time}s")
                    time.sleep(wait_time)
                    retries += 1
                    continue
                elif resp.status_code == 401:
                    logger.warning("Auth expired. Re-authenticating.")
                    token = get_session_token(username, password, tenant)
                    retries += 1
                    continue

                resp.raise_for_status()
                break
            except requests.exceptions.RequestException as e:
                wait_time = min(10 * (2 ** retries), 300)
                logger.error(f"Request failed: {e}. Retrying in {wait_time}s")
                time.sleep(wait_time)
                retries += 1

        if retries >= MAX_RETRIES:
            logger.error(f"Max retries exceeded at skip={skip}. Saving checkpoint.")
            save_checkpoint(object_name, skip)
            raise RuntimeError(f"Extraction failed at skip={skip}")

        batch = resp.json().get("value", [])
        if not batch:
            break
        records.extend(batch)
        skip += page_size
        request_count += 1
        save_checkpoint(object_name, skip)
        logger.info(f"Extracted {len(records)} records so far")

    return records
```

> [!WARNING]
> For long-running extractions, re-authenticate before each major batch. If you are using session-based auth rather than API keys or OIDC, Ivanti session tokens expire based on tenant timeout settings with no refresh mechanism. Call the logout endpoint after completing each session to avoid exhausting concurrent session capacity.

## How to migrate CMDB CIs without breaking relationships

CMDB migration is the highest-risk phase. Ivanti stores CI data in a relatively flat structure with group business objects like `CI.Server`. ServiceNow's CMDB uses a deep class hierarchy where a Windows Server is stored in `cmdb_ci_win_server` (which inherits from `cmdb_ci_server` → `cmdb_ci_hardware` → `cmdb_ci`). ([help.ivanti.com](https://help.ivanti.com/ht/help/en_US/ISM/2023/admin/Content/Configure/API/Get-Business-Objects.htm))

If you flatten Ivanti CI group objects into generic `cmdb_ci`, the record count may look fine while the operational value of the CMDB drops fast. ServiceNow uses the `cmdb_rel_ci` table to understand how assets interact. If a router goes down, ServiceNow uses these relationships to flag which servers will lose connectivity.

The CMDB migration process:

1. **Export all CIs and their types from Ivanti.** Use the OData API to pull CI records. The exact business object name varies by tenant. Ivanti's API metadata exposes CI group objects that you should use to determine classification.
2. **Classify each CI.** Map each Ivanti CI type to a ServiceNow CI class. A "Laptop" maps to `cmdb_ci_computer`. A "Network Switch" maps to `cmdb_ci_ip_switch`. There is no automatic classification — this mapping is manual and tenant-specific. Common mappings:
   - Laptop / Desktop → `cmdb_ci_computer`
   - Physical Server → `cmdb_ci_server` or `cmdb_ci_win_server` / `cmdb_ci_linux_server`
   - Virtual Machine → `cmdb_ci_vm_instance`
   - Network Switch → `cmdb_ci_ip_switch`
   - Router → `cmdb_ci_ip_router`
   - Printer → `cmdb_ci_printer`
   - Software Instance → `cmdb_ci_spkg` (software package)
   - Storage Device → `cmdb_ci_storage_device`
3. **Load CIs via Import Sets.** Use ServiceNow Import Sets with transform maps that target the correct child table for each CI class. Configure the **Identification and Reconciliation Engine (IRE)** with identifier rules to evaluate incoming CIs against existing records and prevent duplicates. Set coalesce on `u_ivanti_recid` or use IRE matching on `serial_number` + `name`.
4. **Load CI relationships.** After all CIs exist with valid `sys_id` values, load the `cmdb_rel_ci` table. Each row needs a `parent` sys_id, a `child` sys_id, and a `type` reference (e.g., "Runs on::Runs", "Depends on::Used by"). The `type` field references `cmdb_rel_type` — verify that your relationship type names match ServiceNow's out-of-box values or create custom types before loading.

If you load tickets before CIs, every `cmdb_ci` reference field on incidents and changes will be empty or fail validation. There is no way to backfill these in bulk without a custom fix script. ([servicenow.com](https://www.servicenow.com/docs/r/servicenow-platform/configuration-management-database-cmdb/c_ConfigurationManagementDatabase.html))

## How long does an Ivanti Neurons to ServiceNow migration take?

Timeline depends on three variables: total record count, CMDB complexity, and the number of custom business objects. The data transfer window is usually shorter than the preparation and testing window.

| Phase | Duration | Depends On |
|---|---|---|
| Discovery and data audit | 2 to 5 days | Number of custom objects, CMDB depth |
| Field mapping and transform rules | 3 to 7 days | Picklist count, reference field density |
| Sandbox migration and UAT | 2 to 5 days | Stakeholder availability, remediation cycles |
| Full migration run | 1 to 3 days | Record volume, API throughput |
| Post-migration validation | 1 to 2 days | Testing rigor |
| **Total** | **9 to 22 days** | |

A **big-bang migration** works when total record volume is under 200,000 and you can schedule a weekend cutover. Agents log out of Ivanti on Friday and log into ServiceNow on Monday with their open tickets waiting for them.

A **phased migration** works better for enterprises with 500,000+ records, active SLAs, or compliance requirements that prevent any gap in ticket continuity. The fastest successful cutovers preload closed history ahead of time — since it consumes the most Ivanti API calls — and reserve go-live for the final delta sync, agent acceptance, and rollback checkpoints.

Because Ivanti throttles by daily API call volume and ServiceNow can throttle per user or route, phased or incremental cutover is usually safer than a single full-history weekend push.

For strategies on keeping support running during the move, see [Zero-Downtime Help Desk Data Migration](https://clonepartner.com/blog/blog/zero-downtime-help-desk-data-migration/).

### Risk register

| Risk | Likelihood | Mitigation |
|---|---|---|
| Broken CMDB relationships | High | Enforce strict load order. Validate CI reference integrity before loading tickets. |
| Ivanti API daily quota exhausted mid-extraction | Medium | Pre-calculate total API calls. Split extraction across multiple days if needed. |
| ServiceNow HTTP 429 during load | Medium | Implement exponential backoff. Check `Retry-After` header. Use multiple integration user accounts if permitted by licensing. |
| Session token expiry during extraction | High | Re-authenticate before each major batch. Prefer API keys or OIDC over session tokens. |
| Attachment migration failures | Medium | Use dedicated Attachment API. Chunk files over 10MB. Log every file and compare counts. |
| Enum and lookup drift | Medium | Map from Ivanti `_Valid` IDs, not display labels. |
| Duplicate records on re-runs | High | Configure coalesce fields on every Import Set transform map. Use IRE for CMDB. |
| Orphaned references from deleted Ivanti users/CIs | Medium | Map deleted users to a placeholder account. Migrate decommissioned CIs with `install_status=Retired`. |
| `sys_created_on` overwritten with import timestamp | High | Explicitly map original timestamps in transform. Set `glide.importset.preserve.sys_created_on` or use onBefore transform scripts. |
| Field truncation on long text fields | Medium | Audit source field lengths against ServiceNow dictionary max lengths before load. |

## What data cannot be migrated from Ivanti Neurons to ServiceNow?

Be clear about what does not transfer:

- **Ivanti Discovery data.** Endpoint compliance state, installed software inventory, and vulnerability scan results from Ivanti Neurons for Discovery do not have an equivalent import target in ServiceNow without ITOM Visibility licensing.
- **Workflow and automation rules.** Ivanti Business Rules and Workflow Designer configurations cannot be exported to ServiceNow Flow Designer or Business Rules. These must be rebuilt manually.
- **Dashboard and report configurations.** These are platform-specific and must be recreated in ServiceNow.
- **SLA clocks and active timers.** Active SLA records with running clocks cannot be migrated with accurate elapsed time. SLA definitions must be recreated in ServiceNow, and historical SLA data can only be preserved as static fields on migrated tickets (e.g., `u_original_sla_breach_time`).
- **Audit trail entries.** Ivanti's internal audit logs are system-generated and typically cannot be extracted via the REST API.
- **Encrypted fields.** Passwords and encrypted secure notes stored in Ivanti cannot be exported via the standard API in plain text. These will not migrate.
- **Custom objects without a ServiceNow equivalent.** If you built a custom application inside Ivanti Neurons with no matching table in ServiceNow, you must build a custom scoped application in ServiceNow before you can migrate that data.
- **Field truncation.** If an Ivanti text field contains 4,000 characters but the destination ServiceNow string field is capped at fewer characters (e.g., `short_description` defaults to 160 characters), ServiceNow will truncate the data silently. Audit field lengths before the load phase and remap oversized content to `description` or custom fields.

## Validation and testing

Do not rely on visual spot checks. Every ITSM migration needs three layers of programmatic validation:

1. **Record count reconciliation.** Compare total record counts per object type between Ivanti and ServiceNow. Tolerance should be zero for Incidents, CIs, and Users. Break counts down by open vs. closed status, and by records with attachments and linked CIs.
2. **Field-level spot checks.** Sample 2% to 5% of migrated records (minimum 50 records per object type). Verify that picklist values, date fields, reference fields, and free-text fields match the source. Sample across incidents, changes, problems, and service requests — not just one table. Pay special attention to `sys_created_on` values matching original Ivanti timestamps rather than showing the import date.
3. **Relationship integrity.** Run these specific queries in ServiceNow:
   - Incidents where `cmdb_ci` is empty but the source Ivanti record had a CI link
   - RITMs where the parent `sc_request` reference is null
   - Tickets where `assigned_to` or `caller_id` is empty but the source had valid user references
   - `cmdb_rel_ci` records where `parent` or `child` references resolve to null
   - Journal entries where `element_id` does not match a valid parent record

Run UAT with 3 to 5 IT agents who are familiar with specific high-profile incidents. Ask them to locate known tickets, verify the journal history is intact and in readable chronological order, and confirm that CI links are correct and attachment counts match the source.

**Automated validation with ATF:** If your ServiceNow instance has the Automated Test Framework (ATF) enabled, create test cases that programmatically verify record counts, spot-check field values on known records, and validate relationship integrity. ATF tests can be re-run after each migration iteration, reducing manual validation effort on re-runs.

Preserving incident resolution history matters heavily for compliance and auditing. Healthcare (HIPAA) and financial organizations (SOX, PCI-DSS) must prove that historical access requests and security incidents were handled correctly. By migrating Journal Entries intact with original timestamps, auditors can review the exact timestamp and agent notes for any historical ticket directly within ServiceNow.

## Rollback procedure

Do not decommission your Ivanti Neurons instance until at least 30 days after the ServiceNow go-live. Maintain Ivanti as the system of record until count reconciliation, spot checks, and agent UAT pass.

If the migration fails validation, the rollback process on the ServiceNow side is:

1. **Delete imported records by import set reference.** Every record loaded through the Import Set API retains a reference to its `sys_import_set` row. Run a background script or scheduled job to delete all records in the target table where `sys_import_set` matches your migration import sets. Process deletions in reverse load order: attachments → journals → tickets → CI relationships → CIs → groups → users.
2. **Remove migration configuration artifacts.** If you built migration artifacts in a scoped app, delete the scoped app. This removes staging tables, transform maps, and migration scripts in one operation. If you used global scope (not recommended), manually delete each artifact.
3. **Revert configuration changes via Update Sets.** If you modified ServiceNow dictionary entries, business rules, or system properties for the migration, capture those changes in a dedicated Update Set before migration. To rollback, back out the Update Set or apply a pre-migration baseline Update Set.
4. **Handle the case where agents have started working in ServiceNow.** If agents created new tickets or updated migrated tickets in ServiceNow before rollback is triggered, those records will be lost on rollback. Mitigate this by keeping Ivanti active as a parallel system during the validation window and establishing a clear cutover decision point (e.g., "no rollback after agents have worked 100+ tickets in ServiceNow").

## Should you build in-house or use a managed migration service?

Build in-house if **all** of the following are true:

- Your total record count is under 50,000 across all object types
- You have no CMDB or a very flat CMDB with no multi-level relationships
- You have a developer who can dedicate 3 to 6 weeks and has experience with both OData APIs and ServiceNow Import Sets
- You can tolerate a weekend of downtime

Use a managed service if **any** of the following are true:

- Your CMDB has multi-level CI relationships
- You have more than 100,000 records across all object types
- You need zero downtime during cutover
- You cannot dedicate an engineer for a month
- You need to preserve historical journals, attachments, and service request parameters
- You have compliance requirements (HIPAA, SOX, PCI-DSS) that mandate verifiable data integrity during migration

The hidden cost of DIY is not the initial build — it is the re-migration. Teams that build their own ETL scripts spend the majority of their time debugging broken relationships, handling API edge cases, and re-running failed batches. The scripts work on the sample dataset but break at scale when they hit rate limits, session timeouts, duplicate records from missing coalesce configuration, or unexpected field values in production data.

> Planning an Ivanti Neurons to ServiceNow migration? Our engineers can scope your data model, map your CMDB relationships, and give you a realistic timeline in a 30-minute call.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### How long does an Ivanti Neurons to ServiceNow migration take?

Most migrations take 2 to 4 weeks from discovery through post-migration validation. The actual data transfer typically runs 1 to 3 days depending on record volume and API throughput constraints. Small datasets under 50,000 records can complete in a single weekend.

### Can I migrate Ivanti Neurons to ServiceNow without losing CMDB data?

Yes, but only if you enforce strict load ordering: Users first, then CIs and CI relationships, then tickets, then journals and attachments. Loading tickets before CIs exist causes empty reference fields that are difficult to backfill without a custom script.

### What is the biggest risk in an Ivanti Neurons to ServiceNow migration?

Broken CMDB relationships. Ivanti's flat CI model must be classified into ServiceNow's deep class hierarchy, and every CI-to-ticket link must resolve to a valid sys_id. Incorrect load ordering or failed CI classification causes cascading reference failures across incidents, changes, and service requests.

### Is there a native Ivanti Neurons to ServiceNow migration tool?

No. Ivanti provides a ServiceNow connector that pulls data from ServiceNow into Ivanti Neurons. It does not support the reverse direction for a full ITSM migration. The migration must use API extraction, CSV export, or a third-party service.

### Does migrating Ivanti Neurons to ServiceNow require downtime?

Not necessarily. A phased migration approach migrates historical data while both systems run, then performs a final delta sync of records created during the migration window. IT agents can continue working in Ivanti until the cutover.
