How to Migrate from SysAid to ServiceNow: The Complete ITSM Guide
Complete technical guide to SysAid to ServiceNow migration. Covers object mapping, API limits, CMDB migration, Import Set batching, and step-by-step process.
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
A SysAid to ServiceNow migration is a complex, multi-phase data engineering project that requires splitting SysAid's unified Service Record entity into ServiceNow's distinct Incident, Request Item, Change Request, and Problem tables. The realistic timeline for a mid-size enterprise (50,000 to 200,000 records) is 3 to 6 weeks. The single biggest risk is broken relationships: CMDB CI links, parent-child ticket references, and activity history threads that do not survive a naive CSV export.
Quick answer: SysAid stores Incidents, Requests, Changes, and Problems in a single Service Record entity, while ServiceNow requires each type in its own table. Workflow rules, custom fields, and CMDB relationships do not transfer 1-to-1. Teams with fewer than 10,000 records and no CMDB data can manage a CSV-based migration in-house. Anything above that, or with compliance requirements, benefits from a managed migration service. The biggest design risk is routing SysAid Requests to the wrong ServiceNow table and then breaking assignee, CI, and fulfillment relationships.
Why Enterprise IT Teams Move from SysAid to ServiceNow
The most common drivers are scale, platform extensibility, and enterprise integration requirements. SysAid serves mid-market IT teams well, but organizations that outgrow its customization ceiling or need deep integrations with SAP, Workday, or Azure DevOps typically move to ServiceNow.
Three platform-specific reasons come up repeatedly:
- Workflow complexity limits. SysAid's workflow automation is template-driven. ServiceNow's Flow Designer and Business Rules engine supports multi-step, conditional, approval-chain workflows natively, including parallel approval paths, SLA-triggered escalations, and cross-table orchestration.
- CMDB depth. SysAid's CMDB supports CI types, sub-types, and relation types with up to 250 customizable fields per CI type. ServiceNow's CMDB (built on the Common Service Data Model) supports hundreds of CI classes with inheritance, discovery integrations via MID Server and Discovery patterns, and service mapping out of the box.
- Enterprise ecosystem. ServiceNow's IntegrationHub, MID Servers, and scoped application model provide integration depth — including bidirectional connectors for SAP, Workday, Jira, Azure DevOps, and Splunk — that SysAid's Workato-embedded marketplace does not match at scale.
For a deeper comparison of these two platforms, see our ServiceNow vs SysAid architecture guide.
What Are the Architectural Differences Between SysAid and ServiceNow?
The core architectural difference that makes this migration non-trivial is SysAid's unified Service Record model versus ServiceNow's multi-table model.
In SysAid, users create service record forms to record an Incident, Change, Problem, or Request and submit them for resolution. All four record types live in the same entity, differentiated by a type field. The API gives you access to the following SysAid entities: service records, assets, CIs, and users. You access all of them through the same /api/v1/sr endpoint, filtering by type.
ServiceNow stores each ITSM process in its own table:
- Incidents in
incident - Requests in
sc_request, with line items insc_req_item(Requested Items, commonly abbreviated as RITMs) - Change Requests in
change_request - Problems in
problem
Every SysAid Service Record must be classified, split, and routed to the correct ServiceNow table during transformation. A record with type=incident maps to incident. A record with type=change maps to change_request. The tricky one is Requests.
ServiceNow generates a request and discrete requested items when a catalog item is ordered. (servicenow.com) If a SysAid Request truly represents catalog fulfillment, it should decompose into an sc_request parent and one or more sc_req_item children. But many SysAid Requests are generic help desk asks with no real catalog model behind them. For those, many teams map them to incident or a custom task table instead. That decision belongs in design, not in UAT. If you do not decide up front which SysAid Requests become real Service Catalog requests in ServiceNow, you will either create fake RITMs or lose fulfillment reporting.
The second major difference is relationship modeling. SysAid links CIs to Service Records and assets to CIs in a flat relational structure. ServiceNow uses a hierarchical CMDB with class inheritance (e.g., cmdb_ci_server extends cmdb_ci_hardware extends cmdb_ci), and relationships are stored in cmdb_rel_ci with typed relationship records. Migrating SysAid's CI relationships requires mapping each SysAid CI relation type to a ServiceNow cmdb_rel_type record. ServiceNow's CMDB imports are designed to respect identification and reconciliation rules via the IRE (Identification and Reconciliation Engine), so raw CI inserts are a common way to create duplicates. (servicenow.com)
SysAid Cloud vs. On-Premise: Extraction Differences
SysAid is available as both a Cloud (SaaS) and On-Premise deployment. The extraction approach differs significantly:
- SysAid Cloud — API-only extraction. You are limited to the REST API (
/api/v1/) and Connect API (/connect/v1/) endpoints, with the rate limits described below. No direct database access is available. - SysAid On-Premise — In addition to the API, on-premise deployments may allow direct SQL access to the underlying database (typically Microsoft SQL Server or MySQL). Direct DB queries can bypass API rate limits and extract data significantly faster, but require coordination with the DBA team and carry risk if the internal schema is undocumented. SysAid also offers report-based CSV exports from the admin console, which can supplement API extraction for simpler datasets (users, assets, flat ticket lists) but do not capture relationships, activities, or attachments.
The rest of this guide assumes API-based extraction, which applies to both editions. If you have on-premise DB access, you can use direct SQL queries to accelerate the extraction phase, but all transformation and loading guidance still applies.
SysAid to ServiceNow Object and Field Mapping
Map your data model before touching any APIs. The mapping table below covers the core ITSM objects.
| SysAid Object | ServiceNow Table | Notes |
|---|---|---|
| Service Record (type=incident) | incident |
Map SysAid id to a custom u_sysaid_id field for traceability |
| Service Record (type=request) | sc_request + sc_req_item OR incident |
Only use sc_request + sc_req_item when the record represents catalog fulfillment. Generic help desk requests often map better to incident or a custom task table |
| Service Record (type=change) | change_request |
SysAid change types (standard, normal, emergency) must map to ServiceNow's type field values |
| Service Record (type=problem) | problem |
Map to problem, not problem_task. SysAid problems may have linked incidents; rebuild these as task_rel_task records |
| Users (Agents) | sys_user |
Map SysAid admin flag and group memberships to ServiceNow roles (itil, itil_admin) |
| Users (End Users) | sys_user |
Set active=true and appropriate user_name. No role assignment needed |
| Companies | core_company |
SysAid stores company at the user level. ServiceNow has a dedicated company table. Load before users |
| Assets | alm_asset |
SysAid assets and CIs are separate objects. Decide whether each source asset is a business asset, a CI, or both in ServiceNow |
| CIs | cmdb_ci_* (class-specific) |
SysAid CI types must map to the correct ServiceNow CI class. Use IRE or CMDBTransformUtil to enforce identification during import |
| CI Relationships | cmdb_rel_ci |
Each SysAid CI relation type maps to a cmdb_rel_type record. "Installed on" and "Depends on" must be mapped individually |
| Activities / Notes | sys_journal_entry |
SysAid activities become journal entries on the target record. Preserve timestamps and author attribution |
| Attachments | sys_attachment + sys_attachment_doc |
SysAid attachments are linked by Service Record ID. Each must be re-uploaded to the correct ServiceNow table and table_sys_id |
Field-Level Mapping Considerations
- Picklist values. SysAid uses numeric IDs for status, priority, urgency, and impact fields. ServiceNow uses different numeric scales. SysAid priority "1" (highest) may not map to ServiceNow priority "1" (Critical) without an explicit enum crosswalk. Both systems can expose account-specific labels and automation behind these fields, so validate against your actual tenant data. (developers.sysaid.com)
- Custom fields. SysAid custom fields are prefixed with
cust_in the API response. In ServiceNow, custom fields on ITSM tables use theu_prefix. Every custom field requires a matching field creation in ServiceNow before import. Custom fields are not discoverable by guesswork — SysAid requires a separate custom field metadata pull, and list-type custom fields can return indexed values that must be translated through the metadata map before you can load human-readable values or ServiceNow choice values. (developers.sysaid.com) - Date and time formats. SysAid's API uses ISO 8601 (UTC) format, for example
2024-06-10T14:32:00Z. However, some SysAid Service Record fields such ascloseTimeare described as UNIX format (epoch milliseconds) in the API reference. Validate real payloads from your tenant before writing transforms for created, updated, and closed timestamps. ServiceNow stores datetimes in UTC internally but displays them in the user's configured timezone; ensure your transforms output UTC strings inYYYY-MM-DD HH:mm:ssformat for ServiceNow import. (developers.sysaid.com) - HTML vs. plain text. SysAid description and solution fields can contain HTML. ServiceNow journal fields accept HTML, but rendering depends on the UI policy. Strip or sanitize HTML during transformation to avoid broken formatting in the activity stream. Specifically, remove inline
<style>blocks, embedded<img>tags referencing SysAid-hosted URLs, and any JavaScript fragments. - Reference fields. Reference fields in ServiceNow require the exact
sys_idof the related record. You must maintain a translation database (mapping SysAidid→ ServiceNowsys_id) during the migration. Every reference field —caller_id,assigned_to,cmdb_ci,company,assignment_group— must be resolved through this crosswalk.
What Has No Clean Equivalent in ServiceNow?
- SysAid "Journey" tab. The Journey tab is an actionable audit log of all Service Record Events. ServiceNow has no direct equivalent. The closest option is to import journey entries as journal entries (preserving timestamps) or as records in a custom audit table. Some teams create a custom
u_sysaid_journeytable to preserve the full event stream. - SysAid templates. SysAid uses templates as predefined formats for creating service records. ServiceNow uses catalog items, record producers, and form views instead. Templates must be rebuilt manually — there is no automated conversion path.
- SysAid one-step automations and workflow rules. These cannot be exported via API. They must be audited manually in the SysAid admin console and recreated as ServiceNow Business Rules, Flow Designer flows, or Scheduled Jobs. Document each rule's trigger condition, action, and scope before attempting recreation.
- SLA elapsed-time counters. SysAid SLA counters (elapsed time, breach timestamps) are calculated fields. ServiceNow has its own SLA engine (
task_sla). Historical SLA data can be imported as custom fields for reporting, but the ServiceNow SLA engine will not retroactively calculate SLAs for imported records. For compliance reporting, store original SysAid SLA outcomes (met/breached, elapsed time, breach timestamp) asu_fields on the migrated ticket. - Contextual attachment placement. SysAid supports contextual attachments inside rich text fields. ServiceNow attachment loading is file-oriented. The files can migrate, but their exact inline placement within a description or note will not transfer. (documentation.sysaid.com)
How to Extract Data from SysAid: API Limits and Pagination
SysAid exposes its data through two API generations: the legacy REST API (/api/v1/) and the newer Connect API (/connect/v1/). For bulk extraction, the legacy REST API is more commonly used because it supports broader entity access.
Rate Limits
The following request limits apply when using SysAid's REST API: a maximum of two API login requests will be allowed within a five-minute period. Up to 1,000 other API requests will be allowed within a five-minute period. If usage exceeds the framework, an HTTP 429 message appears, and you will be able to continue once that five-minute time period has passed.
At 1,000 requests per 5 minutes, you have a sustained ceiling of roughly 200 requests per minute (3.33 requests per second). The API also exposes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers for pacing. Build your extraction scripts to read these headers and back off before hitting the wall. (developers.sysaid.com)
Pagination
SysAid APIs implement offset-based pagination using two key parameters: limit (optional, default 20, max 500) and offset (optional, used to calculate the starting point for the page of results).
Always set limit=500 to minimize the number of API calls on list endpoints. For a dataset of 100,000 service records, you will need 200 paginated requests, consuming 200 of your 1,000-request budget per 5-minute window.
The Connect API's service record search endpoint (/connect/v1/service-records/search) has a narrower limit of 100 rows per call, while companies, assets, CIs, and activities support up to 500 rows per call with offset pagination. (developers.sysaid.com)
Authentication
Upon a successful login, the API consumer needs to retrieve the JSESSIONID cookie from the Response Header and submit it in all subsequent API Request Headers. For security reasons, each session expires after 24 hours. Build session refresh logic into your extraction scripts to handle long-running exports. The Connect API uses a two-step client credentials flow (OAuth 2.0) instead, which is generally more robust for automated extraction. (developers.sysaid.com)
Key Extraction Endpoints
| Data Type | Endpoint | Notes |
|---|---|---|
| Service Records | GET /api/v1/sr?type={incident|request|change|problem} |
Filter by type to pre-sort records |
| Users | GET /api/v1/users |
Returns agents and end users |
| Assets | GET /api/v1/assets |
Hardware and software assets |
| CIs | GET /api/v1/ci |
CMDB configuration items |
| Activities | GET /connect/v1/activities/sr/search |
Activity history per Service Record |
| Related Items | GET /connect/v1/service-records/{recordId}/related-items |
Linked records |
| Attachments | GET /api/v1/sr/{id}/attachment |
Returns metadata. Binary download requires a separate call per attachment |
| Custom Field Metadata | GET /api/v1/sr/custom-fields |
Required for translating list-type custom field indexed values to human-readable labels |
SysAid's API does not support bulk export of attachments in a single call. Each attachment must be downloaded individually. For a dataset with 50,000 attachments, this alone consumes 50,000 API requests — roughly 250 minutes (4+ hours) of extraction time at the rate limit ceiling. Test attachment export on day 1 and factor this into your timeline.
Extraction Throughput Math
If you have 500,000 Service Records in SysAid, extracting them at 500 items per request requires 1,000 API calls. At the maximum rate of 1,000 requests per 5 minutes, extraction takes a minimum of 5 minutes of pure network time. In practice, response payload size (typical Service Record responses range from 2–8 KB per record) and network latency reduce the effective throughput to roughly 30,000 to 50,000 records per minute. Factor in per-record calls for activities, related items, and attachments, and total extraction time increases significantly.
For a representative mid-size migration (100,000 Service Records, 200,000 activities, 50,000 attachments):
- Service Records: ~200 API calls → ~1 minute
- Activities: ~400 API calls (at 500/page) → ~2 minutes
- Attachments: ~50,000 API calls → ~250 minutes
- Total extraction time: ~4.5 hours minimum, dominated by attachment downloads
import requests
import time
def extract_sysaid_records(session, base_url, offset, record_type="incident"):
url = f"{base_url}/api/v1/sr"
params = {
"limit": 500,
"offset": offset,
"type": record_type,
"fields": "id,title,status,priority,urgency,impact,assignedTo,requestUser,ciId,createDate,closeTime,description"
}
cookies = {"JSESSIONID": session["jsessionid"]}
response = requests.get(url, params=params, cookies=cookies)
remaining = int(response.headers.get("X-RateLimit-Remaining", 100))
reset_time = int(response.headers.get("X-RateLimit-Reset", 0))
if response.status_code == 429:
sleep_seconds = max(reset_time, 300)
time.sleep(sleep_seconds)
return extract_sysaid_records(session, base_url, offset, record_type)
if remaining < 50:
time.sleep(30) # Preemptive backoff
return response.json()Use fields, expand, filters, sort_by, and sort_dir parameters aggressively so you do not overfetch. SysAid's expand support for requestUser, ci, and asset can reduce follow-up lookups. (developers.sysaid.com)
How to Load Data into ServiceNow: Import Sets, Batching, and Semaphores
ServiceNow provides three primary ingest methods: Import Sets with Transform Maps, the Table API, and the Attachment API. For migrations, Import Sets are the recommended path because they provide staging, transformation, and audit trail capabilities. Use the Table API mostly for lookups and limited post-load updates. (servicenow.com)
Deploying Migration Artifacts with Update Sets
Before loading data, deploy your migration infrastructure — Import Set tables, Transform Maps, custom u_ fields, and any supporting Business Rules — using ServiceNow Update Sets. Create a dedicated Update Set (e.g., "SysAid Migration Artifacts") in your sub-production instance, build all migration components there, and promote the Update Set to production after testing. This ensures your migration configuration is version-controlled, auditable, and reversible. If scoped applications are used in your organization, consider packaging the migration artifacts as a scoped app for cleaner lifecycle management.
Import Set API and Batch Sizing
The docs (insertMultiple) suggest using 200 records per operation, and gradually increasing while watching instance performance. This is the recommended starting point for the insertMultiple method on Import Set tables.
The insertMultiple endpoint is asynchronous by default, accepts only string name-value pairs, and can sequence dependent jobs with run_after in async mode. The Import Set batch size for file-based imports defaults to 1,000 records. If neither property is set, use the default batch size of 1000. You can configure this via the glide.import_set_load_batch_size system property.
Semaphore-Based Rate Limiting
ServiceNow does not enforce a fixed requests-per-minute limit. Instead, it uses semaphore-based concurrency control.
Semaphores are internal controls that manage how many transactions can run in parallel. When transactions are long-running or complex, they occupy these resources for longer periods, which can slow down or delay new incoming requests. If the system becomes saturated, it starts queuing transactions. Once the queue reaches its limit, additional requests may be rejected with an HTTP 429 Too Many Requests error.
The REST API semaphore pool (called "API_INT") allows only 4 concurrent requests per node with a queue depth of 50. When all threads are busy and the queue is full, additional requests are rejected with HTTP 429.
Your migration scripts must implement exponential backoff and retry logic. Limit concurrent API calls to 2 to 3 threads and monitor for 429 responses. If you push too many concurrent batches, you will degrade the performance of the entire ServiceNow instance for active users.
Loading 500,000 records in batches of 200 means 2,500 API calls. If each batch takes 3 seconds to process through the Import Set transform maps, the total load time is roughly 125 minutes — assuming you do not block the semaphores. Push too many concurrent threads and ServiceNow throttles the connection, multiplying your load time.
Attachment Loading
The default maximum attachment size is 1024 MB for new base system instances. The REST API has a practical payload limit of approximately 25 MB per request. Attachments larger than 25 MB require chunked upload or the Attachment API's multipart form data method. ServiceNow uploads one file per request, so attachment loading is inherently sequential per record.
CMDB Loading
For CMDB data, route CI imports through ServiceNow's IRE and CMDBTransformUtil so identification and reconciliation rules are enforced during import. Blind inserts into cmdb_ci tables are one of the fastest ways to create duplicates that pollute your CMDB for months. Set up identification rules that match on serial number, name + IP address, or another unique combination from your SysAid CI data before running the first import. (servicenow.com)
For more on ServiceNow's import constraints, see our guide on 10 ServiceNow data migration challenges.
Migration Approaches: Native vs. iPaaS vs. Managed Service
There are four viable approaches to migrating SysAid data into ServiceNow. The right choice depends on volume, CMDB complexity, and internal engineering capacity.
CSV Export and Import Set Upload. Export data from SysAid as CSV files (via built-in admin console reports or API extraction), then upload to ServiceNow Import Set tables with Transform Maps. Works for small datasets under 10,000 records with no CMDB and no attachment requirements. No API development required, but attachments, relationships, and activity history are lost.
API-Based Custom ETL. Build custom scripts that extract from SysAid's REST API, transform in a staging database (PostgreSQL, SQLite, or a dedicated staging schema), and load into ServiceNow via the Import Set API. Full control over transformation logic. Handles attachments, relationships, and activity history. Supports incremental and delta sync. Requires 2 to 4 weeks of engineering time from a developer experienced with both APIs.
iPaaS (Workato, Zapier, Make). Use pre-built connectors to map SysAid events to ServiceNow actions. Good for real-time event-driven sync during a coexistence period. Poor choice for one-time bulk migration. Per-task pricing (typically $0.01–$0.05 per task on Workato/Make) makes bulk migration of 100K+ records expensive ($1,000–$5,000+ in task costs alone). Cannot handle complex CMDB relationship rebuilding or multi-table decomposition of Service Records.
Managed Migration Service. A migration engineering team builds and runs the full ETL pipeline, including extraction, transformation, loading, relationship rebuilding, and validation. No internal engineering burden. Handles edge cases, retries, and validation. Provides audit trail for compliance.
| Criteria | CSV Import | Custom ETL | iPaaS | Managed Service |
|---|---|---|---|---|
| Best for | < 10K records | 10K to 500K+ records | Ongoing sync | Enterprise, compliance |
| Attachments | No | Yes | Limited | Yes |
| CMDB Relationships | No | Yes (manual) | No | Yes |
| Activity History | No | Yes | Partial | Yes |
| Engineering Effort | 1 to 2 days | 2 to 4 weeks | 3 to 5 days setup | 0 (handled externally) |
| Risk of Data Loss | High | Medium | Medium | Low |
If your environment is small and flat, CSV plus Import Sets can work. If you need historical fidelity, CMDB integrity, and controlled cutover, build or buy a real ETL pipeline.
Step-by-Step SysAid to ServiceNow Migration Process
The order of operations matters. Loading records in the wrong sequence creates orphaned references and broken relationships. If you load a ticket before the user who requested it, the caller field will be blank — and fixing that retroactively in a production instance is painful.
Step 1: Audit the source model. Pull sample Service Records, users, companies, assets, CIs, notes, activities, attachments, and custom field metadata from SysAid. Document your record counts, custom field inventory (total count, field types, list-type fields requiring metadata translation), and attachment volume (count and total size in GB) before mapping anything.
Step 2: Freeze the routing rules.
Decide exactly which SysAid Requests become sc_request + sc_req_item, and which become incidents or another task type. This is a design decision that must be locked before you build anything. Document the decision with examples: "SysAid Requests with category 'Software License' become sc_req_item under a 'Software Request' catalog item. All other Requests become incidents."
Step 3: Load reference data.
Insert Companies, then Departments, then Users into ServiceNow. Store the resulting sys_id for every record in a mapping database (a simple table with columns: sysaid_entity, sysaid_id, servicenow_table, servicenow_sys_id). Every subsequent load depends on this mapping.
Step 4: Extract and load CMDB CIs.
Pull CIs from SysAid (/api/v1/ci). Map each SysAid CI type to the correct ServiceNow CI class (cmdb_ci_server, cmdb_ci_computer, cmdb_ci_win_server, cmdb_ci_linux_server, etc.). Load CIs using IRE and store the ID mapping. Then load CI relationships into cmdb_rel_ci, mapping each SysAid relation type to a ServiceNow cmdb_rel_type.
Step 5: Extract and load Assets.
Pull assets from SysAid (/api/v1/assets). Map to alm_asset records in ServiceNow, linking to the correct cmdb_ci record using the mapping table from Step 4.
Step 6: Extract, classify, and transform Service Records. Pull all Service Records from SysAid, filtered by type. Route each to the correct ServiceNow staging table:
type=incident→incidenttype=request→sc_request+sc_req_item(orincident, per your routing decision from Step 2)type=change→change_requesttype=problem→problem
Transform field values: status codes, priority mappings, picklist values. Replace SysAid user IDs and CI IDs with the ServiceNow sys_id values from your mapping tables. Strip or sanitize HTML from description fields. Convert date formats to ServiceNow's expected YYYY-MM-DD HH:mm:ss UTC format.
SYSAID_TO_SNOW_STATUS = {
1: 1, # New → New
2: 2, # In Progress → In Progress
3: 6, # Resolved → Resolved
4: 7, # Closed → Closed
# Add your tenant-specific mappings
}
for sr in sysaid_service_records(limit=100):
target = route_service_record(sr) # Returns 'incident', 'change_request', etc.
staged_row = transform(sr, target, id_map=mapping_db, status_map=SYSAID_TO_SNOW_STATUS)
write_to_import_stage(target, staged_row)
run_import('u_cp_incident_stage')
run_import('u_cp_problem_stage')
run_import('u_cp_change_stage')
run_import('u_cp_request_stage')Step 7: Load Service Records into ServiceNow.
Use Import Set tables with Transform Maps. Keep batch sizes at 200 records for API-based loads using insertMultiple. Process records in chronological order (oldest first) to preserve temporal integrity and ensure parent records exist before children.
Step 8: Load Activity History.
Extract activities and notes from SysAid for each Service Record. Load as sys_journal_entry records, preserving the original timestamp and author attribution. The element_id references the target record's sys_id, and element should be set to work_notes or comments depending on the activity type.
Step 9: Load Attachments.
Download each attachment binary from SysAid individually. Upload to ServiceNow's Attachment API, linking to the correct table and sys_id. This is the most time-consuming step due to SysAid's per-attachment API call requirement. Implement parallel download (2–3 threads on SysAid side) and sequential upload (1 thread on ServiceNow side to avoid semaphore saturation).
Step 10: Rebuild cross-record relationships and validate.
Parent-child links between incidents and problems, linked incidents on change requests, and any custom relationships must be re-established using the ID mapping tables. Load these as task_rel_task records. Run record-count reconciliation and field-level spot checks (detailed in the Validation section below).
Do not load attachments before the parent ticket mapping is final. Reattaching thousands of files by hand is the kind of cleanup that turns a two-week project into a two-month one.
Retry rules should differ by platform. On SysAid, back off to the X-RateLimit-Reset header value when you hit 429. On ServiceNow, honor Retry-After for REST rate limits, cut concurrency when API_INT semaphore depth rises, and keep a durable map of source ID to target sys_id so replays are idempotent (check-before-insert or use coalesce fields in Transform Maps).
For a broader look at data sequencing, review our Help Desk Data Migration Playbook.
How Long Does a SysAid to ServiceNow Migration Take?
A realistic timeline depends on record volume, CMDB complexity, and the number of custom fields.
| Phase | Duration | Exit Criteria |
|---|---|---|
| Discovery and audit | 3 to 5 days | Record counts, custom fields, attachment volume (count + GB), and request routing rules are documented |
| Field mapping and transform design | 3 to 5 days | Approved mapping document, ServiceNow Import Set tables and Transform Maps created, Update Set promoted to sub-prod |
| Script development and testing | 5 to 10 days | Extraction, transformation, and load scripts built and tested against sub-production instance |
| Trial migration (rehearsal) | 2 to 3 days | Full migration on sandbox, counts reconciled within 0.1%, relationships validated, stakeholder review |
| Production migration | 1 to 3 days | Final migration executed. Larger datasets with attachments take longer |
| Validation and UAT | 2 to 3 days | Stakeholder sign-off, agent testing with migrated data, SLA field verification |
| Total | 3 to 6 weeks | For 50,000 to 200,000 records with CMDB |
Smaller migrations (under 10,000 records, no CMDB) can complete in 1 to 2 weeks. Enterprise migrations with 500,000+ records and deep CMDB hierarchies may extend to 8 to 10 weeks.
Phased vs. Big-Bang vs. Incremental
- Big-bang works when the organization can tolerate a weekend cutover window and the dataset is manageable (under 100,000 records total). All data moves at once; SysAid is decommissioned Monday morning.
- Phased is better for organizations that need to migrate by department or process (incidents first, then changes, then CMDB). Reduces risk but extends the coexistence period and requires channel routing during overlap.
- Incremental (with ongoing delta sync) is required when both platforms must run in parallel for weeks or months. Requires a delta detection mechanism (comparing SysAid
modifyDateagainst last sync timestamp) and idempotent upsert logic on the ServiceNow side. Adds 1–2 weeks of engineering complexity but eliminates downtime.
Key Risks
| Risk | Likelihood | Mitigation |
|---|---|---|
| Wrong table routing for Requests | High | Freeze request routing rules before build. Test with real fulfillers using 50+ sample records |
| Duplicate CIs from blind inserts | High | Use IRE and identity rules, not direct table inserts. Set identification rules before first CI import |
| API rate limiting (SysAid) | High | Implement token bucket rate limiter. Read X-RateLimit-* headers. Budget 250+ minutes for attachment extraction |
| Broken caller or assignee references | Medium | Preload users and maintain immutable external ID mapping. Validate with a query for null caller_id post-load |
| Attachment backlog | Medium | Test export and upload speed on day 1. Parallelize SysAid downloads (2–3 threads), serialize ServiceNow uploads |
| Semaphore saturation (ServiceNow) | Medium | Start with 1 thread, monitor 429 responses, cap concurrent threads at 2 to 3. Schedule loads during off-hours |
| Data truncation | Medium | Audit field lengths in ServiceNow before test load. ServiceNow short_description is 160 chars; SysAid title may be longer |
| Reporting drift after go-live | Medium | Rebuild dashboards against new tables before cutover. Verify key metrics (open incident count, MTTR) match between systems |
| Import Set auto-cleanup | Medium | ServiceNow deletes import sets older than 7 days by default. Export transform logs before they age out |
Edge Cases and Known Limitations
These are the failure modes that generic guides skip.
Duplicate users. SysAid may have duplicate user records (same email, different id values). ServiceNow enforces unique user_name. Deduplicate before loading — merge duplicate SysAid users in your staging database and map all source IDs to the single canonical ServiceNow sys_id. Otherwise your import will fail on unique constraint violations.
Orphaned attachments. SysAid attachments linked to deleted Service Records will fail to load because the parent record does not exist in ServiceNow. Decide in advance whether to skip, archive to a separate table, or load to a catch-all record.
Multi-level CMDB relationships. SysAid supports CI-to-CI relationships but does not enforce a hierarchy. ServiceNow's CMDB expects relationships to follow the Common Service Data Model. Flat SysAid relationships may need restructuring. Migrating a server and its installed software requires creating records in cmdb_ci_server, cmdb_ci_spkg, and linking them in cmdb_rel_ci with a cmdb_rel_type of "Runs on::Runs" or similar. A simple CSV import cannot handle this logic.
Custom fields exceeding ServiceNow limits. ServiceNow allows up to 500 custom fields per table (a soft limit; exceeding it degrades form load performance). The CMDB allows you to create as many item types as you like, and you have 250 customizable fields to record any information you need about each of your items. If your SysAid instance has 250 custom CI fields, they will fit, but plan field types carefully in ServiceNow. Consider whether some SysAid custom fields should become ServiceNow Extended Attributes or entries in a related list rather than direct columns.
Attachment size via API. ServiceNow's REST API has a practical payload limit of approximately 25 MB per request. Attachments larger than this require the multipart upload method or chunking. SysAid caps file attachments at 50 MB and blocks certain executable and HTML-like file types (.exe, .bat, .htm). (documentation.sysaid.com)
Webhook limitations for custom fields. If a SysAid service record was created through the API, custom fields are not included in the creation webhook payload. This matters if you are using webhooks for incremental sync during a coexistence period — you will need a follow-up GET call to retrieve custom field values for webhook-triggered records. (developers.sysaid.com)
SLA data. SysAid SLA counters are calculated values. ServiceNow's SLA engine (task_sla) will not retroactively compute SLAs for imported records. Historical SLA outcomes are better stored as migrated custom field values (u_sysaid_sla_met, u_sysaid_sla_elapsed_minutes, u_sysaid_sla_breach_time) or archived reports than replayed through the live SLA engine.
Import Set cleanup. ServiceNow has a default cleanup job (Import Set Deleter) that removes import sets older than 7 days along with associated staging records. Export your transform logs and error records before they age out if you need a durable audit trail from rehearsal runs. You can extend the retention by modifying the glide.import_set_cleanup_age property, but do so intentionally and revert after migration. (servicenow.com)
SysAid workflow and automation rules. These cannot be exported via API. They must be manually audited in the SysAid admin console (under Settings → Workflow) and recreated in ServiceNow as Business Rules, Flows, or Scheduled Jobs. Document trigger conditions, filter criteria, and actions for each rule before attempting recreation.
Data privacy and masking. For GDPR, HIPAA, or SOX-regulated environments, ensure that PII (names, email addresses, phone numbers in ticket descriptions) is handled appropriately during extraction and staging. If your staging database is not within the same compliance boundary as your production systems, apply field-level masking or encryption during extraction and decrypt only during the ServiceNow load phase. Maintain a data processing agreement with any third-party migration vendor.
How to Validate a SysAid to ServiceNow Migration
Do not trust API success codes blindly. Validate the data inside the ServiceNow instance using a structured approach.
-
Record-count reconciliation. Compare total counts per object type: incidents, requests, changes, problems, users, CIs, assets, attachments. Source counts should match destination counts within 0.1% (accounting for intentional exclusions like orphaned records or deduplicated users). Run this query in ServiceNow:
incident.list?sysparm_query=u_sysaid_idISNOTEMPTYand compare against your source count. -
Field-level spot checks. Sample 50 to 100 records per object type across different categories — open tickets, closed tickets, high-priority, reassigned, and attachment-heavy cases. Verify that status, priority, assigned_to, created_date, and resolved_date match between source and target. Use a spreadsheet with side-by-side comparison columns.
-
Null reference audit. Run queries for records with null values in critical reference fields that should be populated:
incident.list?sysparm_query=caller_idISEMPTY^u_sysaid_idISNOTEMPTY. Any results indicate broken reference mappings. -
Relationship integrity. Verify that CI-to-incident links, parent-child ticket references, company assignments, and user assignments resolve correctly in ServiceNow. Spot-check 20+ CMDB relationships by navigating the CI record and confirming related items appear.
-
Attachment verification. Confirm that attachments are accessible and renderable on their target records. Check file sizes against the source system. Run:
sys_attachment.list?sysparm_query=table_name=incident^ORtable_name=change_requestand compare counts. -
Timestamp accuracy. Verify that created, updated, and resolved timestamps match the source system. Timezone shifts are a common failure mode — SysAid may return timestamps in the account's local timezone despite documenting UTC, so compare a sample of 10+ records with known timestamps.
-
UAT with real agents. Have 3 to 5 IT agents work in ServiceNow using migrated data for 1 to 2 days before go-live. Ask them to search for old SysAid IDs (using the
u_sysaid_idfield), open records, verify activity history, and confirm attachments are accessible. Agents find issues — missing categories, wrong assignment groups, truncated descriptions — that automated checks miss.
Rollback Plan
Your rollback plan should include these concrete elements:
- Keep SysAid readable in read-only mode for at least 30 days post-cutover
- Preserve the ID crosswalk mapping database indefinitely — it is your Rosetta Stone for any post-migration corrections
- Do not destroy source data until validation is complete and stakeholders have signed off
- Script a ServiceNow cleanup that can delete all records with
u_sysaid_id IS NOT EMPTYfrom each target table, effectively reverting the import - Switch inbound channels (email routing, portal URLs, agent bookmarks) only after validation passes
- Document the rollback trigger criteria: e.g., "If record count variance exceeds 1% or more than 5% of spot-checked records have incorrect field values, execute rollback"
For a complete post-migration validation framework, see our help desk migration QA checklist.
Build In-House or Use a Managed Migration Service?
Build in-house when:
- Your dataset is under 10,000 records with no CMDB
- You have a ServiceNow developer with Import Set and Transform Map experience on staff
- You can tolerate a multi-day cutover window
- Compliance and audit requirements are minimal
- Your SysAid Requests map cleanly to either incidents or a well-defined catalog model
Use a managed service when:
- Your dataset exceeds 50,000 records or includes CMDB data
- You need zero-downtime migration with delta sync
- Compliance requirements (SOX, HIPAA, GDPR) mandate a documented audit trail and chain of custody
- Your SysAid Requests do not map cleanly to Service Catalog and require case-by-case routing logic
- Your engineering team cannot absorb 2 to 4 weeks of migration work alongside existing priorities
- You have significant attachment volume (50,000+ files) that requires optimized extraction scheduling
The hidden cost of in-house migration is not the initial build — it is the re-work. Broken relationships, missed attachments, and incorrect field mappings typically surface 1 to 2 weeks after go-live, requiring a second or third corrective pass. This re-work compounds quickly when agents are already using ServiceNow in production and new records are being created alongside corrective imports. The internal engineering cost of a DIY migration (2 to 4 weeks of a senior developer's time at $80–$120/hour fully loaded = $25,000–$75,000 in labor) often approaches or exceeds the cost of a managed service.
ClonePartner handles the complex ETL logic required to split SysAid's unified Service Records into ServiceNow's distinct tables automatically. We manage SysAid's 1,000-request-per-5-minute rate limit and ServiceNow's semaphore queues with built-in retry logic and record-level audit trails. We preserve exact sys_id mappings and CMDB relationships that generic iPaaS tools and CSV exports break.
For a broader perspective on the build-vs-buy decision, see our in-house vs. outsourced migration analysis.
Frequently Asked Questions
- How long does a SysAid to ServiceNow migration take?
- A typical mid-size enterprise migration (50,000 to 200,000 records) takes 3 to 6 weeks from discovery to go-live. Smaller migrations with under 10,000 records and no CMDB can complete in 1 to 2 weeks. Enterprise migrations with 500,000+ records and deep CMDB hierarchies may extend to 8 to 10 weeks. The largest variable is attachment volume, because each SysAid attachment requires an individual API call to download.
- What data cannot be migrated from SysAid to ServiceNow?
- SysAid workflow automations, routing rules, notification templates, and dashboard configurations cannot be exported via API and must be rebuilt in ServiceNow. SLA elapsed-time counters are calculated values that ServiceNow's SLA engine will not retroactively compute for imported records. Contextual attachment placement inside rich text fields also does not transfer 1-to-1.
- Can SysAid CMDB data be preserved in ServiceNow?
- Yes, but not as a 1-to-1 copy. SysAid CI types must be mapped to ServiceNow's class-based CMDB hierarchy. CI relationships must be individually mapped from SysAid's relation types to ServiceNow's cmdb_rel_type records. Use ServiceNow's IRE (Identification and Reconciliation Engine) during import to avoid creating duplicate CIs.
- Can SysAid ticket history be preserved in ServiceNow?
- Yes. SysAid activity history (notes, status changes, assignment changes) can be migrated as sys_journal_entry records in ServiceNow. Each journal entry preserves the original author and timestamp. Native ServiceNow audit and history behavior is not a 1-to-1 copy target, but human-readable history is fully preservable for compliance and operational purposes.
- Is there downtime during a SysAid to ServiceNow migration?
- A big-bang migration requires a freeze window of 4 to 24 hours where no new tickets should be created in SysAid. An incremental migration with delta sync can reduce this to under 1 hour. The bulk of historical data is migrated while SysAid is still active, and only the delta (new and modified records since the bulk load) is migrated during the cutover window.

