---
title: "Migrate from Jira Service Management to ServiceNow: Technical Guide"
slug: migrate-from-jira-service-management-to-servicenow-technical-guide
date: 2026-07-08
author: Raaj
categories: [Jira Service Management, ServiceNow, Migration Guide]
excerpt: "A technical guide to migrating from Jira Service Management to ServiceNow — covering data mapping, SLA migration, Confluence KB transfer, and common pitfalls."
tldr: "JSM-to-ServiceNow migration is a data-model translation: map issue types to ITSM tables, convert semantic statuses to numeric states, preserve SLA timestamps via task_sla, and rebuild automations in Flow Designer."
canonical: https://clonepartner.com/blog/migrate-from-jira-service-management-to-servicenow-technical-guide/
---

# Migrate from Jira Service Management to ServiceNow: Technical Guide


# Migrate from Jira Service Management to ServiceNow: Technical Guide

> [!NOTE]
> **Quick Answer:** A Jira Service Management (JSM) to ServiceNow migration is a data-model translation, not a file transfer. JSM uses semantic, project-specific statuses on an issue-centric engine; ServiceNow uses numeric state machines on ITIL-aligned tables. No native migration path exists. The biggest risks are broken SLA history, lost Confluence KB formatting, status values that don't map 1:1, and internal comments exposed to customers.

## Why Do Companies Outgrow Jira Service Management for ServiceNow?

Most teams don't leave JSM because it's bad. They leave because their organization has outgrown what a project-based ITSM can do. JSM is built on Jira's core issue-tracking engine — flexible by design, effective for engineering-led teams that prioritize speed and tight integration with the Atlassian stack. ([support.atlassian.com](https://support.atlassian.com/jira-service-management-cloud/docs/whats-the-difference-between-request-types-and-issue-types/))

The trigger is usually one of these:

- **ITIL governance requirements.** JSM supports ITIL practices, but ServiceNow enforces them structurally. ServiceNow's out-of-box incident module ships with ITIL-aligned workflows, impact-urgency matrices (a 3×3 priority lookup that auto-calculates priority from impact and urgency fields), and major incident management processes with dedicated `major_incident_state` tracking. JSM gives you flexibility; ServiceNow gives you compliance guardrails. Organizations subject to SOX, HIPAA, or FedRAMP audits frequently cite this as the primary driver.
- **CMDB as the source of truth.** JSM's Assets feature (Premium/Enterprise tiers, ~$44.27+/agent/month) provides a schema-free configuration database. ServiceNow's CMDB — backed by the Common Service Data Model (CSDM) — is a normalized, relationship-driven system with over 400 out-of-box CI classes organized across five CSDM domains (Foundation, Design, Build/Manage, Sell/Consume, Detect/Correct). It powers service mapping, impact analysis, and change risk scoring across the enterprise. JSM Assets has no equivalent to ServiceNow's Discovery or Service Mapping modules for automated CI population.
- **Enterprise-wide service management.** JSM can extend to HR and facilities via project templates, but ServiceNow was built to unify IT, HR, SecOps, legal, and facilities on a single platform with shared workflows. ServiceNow's domain separation feature allows multi-tenant configurations that JSM cannot replicate.
- **Automation depth.** JSM's no-code "when-if-then" rules cover common scenarios and support up to 500 rules per project in Premium plans. ServiceNow's Flow Designer, Business Rules, and IntegrationHub provide multi-layer automation that can span departments and integrate with SAP, Salesforce, Slack, and custom systems. IntegrationHub ships with 900+ pre-built spokes, compared to JSM's reliance on Forge apps and webhooks.

The decision to migrate is usually driven by audit requirements, M&A integration, or scaling beyond a few hundred agents — not by dissatisfaction with JSM itself. For a deeper look at the architectural differences, see our [ServiceNow vs Jira Service Management Architecture Guide (2026)](https://clonepartner.com/blog/blog/servicenow-vs-jira-service-management-architecture-guide-2026/).

## How Do Jira Issue Types Map to ServiceNow Tables?

This is where the data-model gap hits hardest. In JSM, everything is a Jira issue with an issue type label. Atlassian layers **request types** on top of **work types**: one request type maps to one work type, and one work type can support many request types. Work items created without a request type lose some JSM behavior (e.g., SLA tracking, customer portal visibility, queue eligibility). ([support.atlassian.com](https://support.atlassian.com/jira-service-management-cloud/docs/whats-the-difference-between-request-types-and-issue-types/))

In ServiceNow, each ITSM process lives on a separate table that extends the base `task` table. There is no equivalent of Atlassian's customer-facing request type wrapper — you must decide during design whether the request type determines the target table, survives as metadata on a custom field, or both.

| JSM Concept | ServiceNow Equivalent | Key Difference |
|---|---|---|
| Issue Type: Incident | `incident` table | ServiceNow separates incidents from service requests; incidents have `caller_id`, service requests have `requested_for` |
| Issue Type: Service Request | `sc_req_item` (catalog item) | JSM request types are presentation layers; ServiceNow catalog items are full workflow objects with variables, execution plans, and approval policies |
| Issue Type: Problem | `problem` table | ServiceNow links problems to incidents via `problem_id` reference field; supports root cause analysis with `rca_cause_ci` |
| Issue Type: Change | `change_request` table | ServiceNow enforces change types (Normal, Standard, Emergency) with distinct approval flows; Standard changes use pre-approved templates |
| Issue (generic) | `task` (base table) | ServiceNow uses `task` as the parent; all ITSM tables inherit from it. The `task` table contains ~130 base fields inherited by all child tables |
| Project | Assignment Group + Category | No direct equivalent — ServiceNow uses category/subcategory on the task table plus assignment groups |
| JSM Assets (CI) | `cmdb_ci` and child classes | JSM uses a flat, schema-free object model; ServiceNow CMDB uses a normalized class hierarchy with enforced relationships |

> [!WARNING]
> **Critical edge case:** One JSM project may contain mixed issue types (incidents, changes, problems) in a single backlog. You need to split these into separate ServiceNow tables during migration. Any script that dumps everything into the `incident` table will corrupt your ITSM process data — and will break ServiceNow reports, dashboards, and Performance Analytics indicators that assume table-level process separation. ([support.atlassian.com](https://support.atlassian.com/jira-service-management-cloud/docs/what-are-compatible-and-incompatible-issue-types/))

### Extraction Script Pseudocode: Issue Type Routing

```python
# Pseudocode: Route JSM issues to correct ServiceNow tables
TABLE_MAP = {
    "Incident": "incident",
    "Service Request": "sc_req_item",
    "Service Request with Approvals": "sc_req_item",
    "Problem": "problem",
    "Change": "change_request",
    "Post-Incident Review": "problem",  # Map PIRs to problem table
}

for issue in jira_issues:
    issue_type = issue["fields"]["issuetype"]["name"]
    target_table = TABLE_MAP.get(issue_type)
    if target_table is None:
        log_warning(f"Unmapped issue type: {issue_type} on {issue['key']}")
        target_table = "task"  # Fallback to base table, flag for review
    route_to_servicenow(issue, target_table)
```

## How Do Jira Statuses Map to ServiceNow State Values?

This is the single most misunderstood mapping in JSM-to-ServiceNow migrations. JSM uses semantic, human-readable statuses that are project-specific and workflow-configurable. ServiceNow uses deterministic, numeric state integers. ([support.atlassian.com](https://support.atlassian.com/jira-cloud-administration/docs/what-are-issue-statuses-priorities-and-resolutions/))

ServiceNow's out-of-box **incident** states:

| Integer Value | Label | Category |
|---|---|---|
| 1 | New | Open |
| 2 | In Progress | Work in Progress |
| 3 | On Hold | Work in Progress |
| 6 | Resolved | Terminal |
| 7 | Closed | Terminal |

These values are not sequential — 4 and 5 are intentionally skipped in modern ServiceNow releases (they were used in legacy Fuji/Geneva instances for "Awaiting User Info" and "Awaiting Evidence"). Custom states can be added, but active states must have values below 6, since the platform treats 6+ as terminal states that trigger SLA completion and prevent re-assignment without explicit reopen logic.

**State models differ by table.** The `problem` table defaults to:

| Integer Value | Label |
|---|---|
| 1 | Open |
| 2 | Known Error |
| 3 | Pending Change |
| 4 | Closed/Resolved |

The `change_request` table uses an entirely different range:

| Integer Value | Label |
|---|---|
| -5 | New |
| -4 | Assess |
| -3 | Authorize |
| -2 | Scheduled |
| -1 | Implement |
| 0 | Review |
| 3 | Closed |
| 4 | Canceled |

You cannot push a string like "Waiting on Customer" into ServiceNow's state field — your migration script must evaluate each Jira status string, map it to the correct ServiceNow integer on the correct table, and ensure the target state is valid according to ServiceNow's state transition rules.

### Example State Mapping Table

```python
# Incident state mapping from JSM to ServiceNow
INCIDENT_STATE_MAP = {
    "Open": 1,
    "To Do": 1,
    "In Progress": 2,
    "Working": 2,
    "Waiting for Support": 3,      # On Hold
    "Waiting for Customer": 3,     # On Hold - set hold_reason = "Awaiting Caller"
    "Pending": 3,
    "Resolved": 6,
    "Done": 7,
    "Closed": 7,
    "Cancelled": 7,                # Set close_code = "Cancelled"
}
```

> [!WARNING]
> **Watch out:** The base `task` table may define different labels for the same integer. For example, state `3` on the incident table means "On Hold," but on the base task table, `3` = "Closed Complete." If you run reports at the task level, incidents with state 3 appear in the wrong bucket. Always validate state mappings at the specific table level, not the task level. Use the `sys_choice` table query `name=incident^element=state` to verify the active state values on any target table.

## How Do JSM Queues Map to ServiceNow Assignment Groups?

They don't — at least not directly. This is a fundamental model mismatch.

**JSM queues** are JQL filters. A queue is a saved query like `project = SUPPORT AND status = Open AND priority = High`. Tickets aren't "assigned" to a queue; they appear in a queue if they match the JQL at that moment. One ticket can appear in multiple queues simultaneously. ([support.atlassian.com](https://support.atlassian.com/jira/kb/project-queues-in-jira-service-management-are-empty-and-not-showing-any-open-tickets/))

**ServiceNow Assignment Groups** are strict user-membership entities stored in the `sys_user_group` table. A ticket's `assignment_group` field is a reference to a single group. Routing is handled by assignment rules, not filters.

The migration approach:

1. **Audit your JSM queues.** Export each queue's underlying JQL and document the intent (e.g., "Tier 1 Support — all P1/P2 incidents").
2. **Create corresponding Assignment Groups** in ServiceNow with the appropriate members. By default, `task.assignment_group` is filtered to groups of type `itil`. If you create new groups during migration and miss the type or membership model, records may load successfully but be unassignable in the UI or ignored by assignment rules. ([servicenow.com](https://www.servicenow.com/docs/r/platform-administration/user-administration/c_ConfigGroupTypesForAssignGroups.html))
3. **Build assignment rules or Flow Designer flows** that replicate the queue logic as routing rules. ServiceNow's Assignment Lookup Rules (`sla_assignment`) evaluate category, subcategory, and configuration item to route to groups.
4. **Set the `assignment_group` field** on each migrated record based on which queue the ticket was primarily associated with in JSM.

Write queue mappings explicitly. Do not let them live only in an admin's memory. A small spec like this exposes the hidden logic before you build assignment rules:

```yaml
queue: P1 - Network Unassigned
jql: project = ITSM AND priority = Highest AND component = Network AND assignee is EMPTY AND statusCategory != Done
targetAssignmentGroup: Network Support
servicenowGroupSysId: "a1b2c3d4e5f6..."
routingRule: incident.category = network AND priority = 1
groupType: itil
members:
  - network-admin@company.com
  - network-engineer@company.com
```

You'll lose the "ticket appears in multiple views" behavior. ServiceNow's equivalent is saved list filters or Service Operations Workspace (SOW) Agent Queues — but those are presentation-layer, not data-layer concepts. SOW Queues use Advanced Work Assignment (AWA) conditions, which are closer to JSM's model but require the ITSM Professional license tier.

## How Do You Migrate Jira Custom Fields to ServiceNow?

JSM custom fields live on the Jira issue and are configured per project or globally. ServiceNow custom fields are columns on specific tables (`incident`, `problem`, `change_request`) or on the base `task` table. Custom fields in ServiceNow are prefixed with `u_` by convention (e.g., `u_business_justification`).

| JSM Field Type | ServiceNow Equivalent | Notes |
|---|---|---|
| Text (single line) | String field (max 255 chars default) | Direct map; adjust max length in dictionary if needed |
| Text (multi-line) | String field (max 4000 chars) or Journal field | Journal fields (`journal_input`) for audit-tracked entries; journal entries are stored in `sys_journal_field`, not on the record itself |
| Select List (single) | Choice field | Must pre-populate choice values in `sys_choice` table before import |
| Select List (multi) | List collector or Glide List | Different storage model — Glide List stores comma-separated `sys_id`s |
| Date / DateTime | Date / Date/Time field | Timezone conversion required; ServiceNow stores all datetimes in UTC internally |
| Number | Integer / Decimal / Float | Match precision; Jira numbers are IEEE 754 doubles |
| User Picker | Reference to `sys_user` | Must resolve by email or employee ID, not by display name |
| Checkbox | True/False field | Direct map |
| URL | URL field | Direct map |
| Labels | Tags (via `label` table) | Different tagging architecture; ServiceNow labels are per-table |
| Cascading Select | Dependent choice fields | Requires parent-child choice configuration in `sys_choice` with `dependent_value` |
| Components | Reference to `cmdb_ci_service` or choice field | No direct equivalent — map to category/subcategory or CI reference |
| Sprint / Story Points | No equivalent | Drop or store in custom fields for historical reference |

Before migration, export your JSM custom field definitions via the Jira REST API (`GET /rest/api/3/field`) and map each one to a ServiceNow dictionary entry. Fields that don't exist on the target table must be created via the `sys_dictionary` table or the Table & Column editor before import.

### User Mapping

**User mapping deserves special attention.** ServiceNow links all records to a user via a 32-character GUID called a `sys_id`. Jira Cloud identifies users by their Atlassian Account ID (a UUID like `5b10ac8d14c05b22cc7d4ef5`). Before migrating tickets, extract all Jira users via `GET /rest/api/3/users/search`, map their email addresses to the `sys_user` table in ServiceNow, and store the resulting `sys_id`s in a lookup table.

```python
# Pseudocode: Build user lookup table
user_map = {}
jira_users = jira_api.get("/rest/api/3/users/search?maxResults=1000")
for jira_user in jira_users:
    email = jira_user["emailAddress"]
    sn_user = servicenow_api.get(
        f"/api/now/table/sys_user?sysparm_query=email={email}&sysparm_fields=sys_id"
    )
    if sn_user["result"]:
        user_map[jira_user["accountId"]] = sn_user["result"][0]["sys_id"]
    else:
        log_warning(f"No ServiceNow user found for {email}")
        user_map[jira_user["accountId"]] = DEFAULT_INTEGRATION_USER_SYS_ID
```

If your script attempts to assign an incident to an email address instead of a `sys_id`, ServiceNow will either reject the payload (if the field is a strict reference) or assign the ticket to the API integration user, destroying your historical audit trail.

### Permission Mapping

ServiceNow handles permissions differently from JSM. JSM uses project roles (Administrator, Agent, Customer); ServiceNow uses groups and roles on the `sys_user_has_role` table. Key role mappings:

| JSM Role | ServiceNow Role |
|---|---|
| Project Administrator | `itil_admin` |
| Agent | `itil` |
| Customer | No role — access via Service Portal + user criteria |
| Approver | `approver_user` |

Permission mapping must be planned separately from data migration.

## How Do You Migrate JSM SLAs to ServiceNow's task_sla Table?

SLA migration is where most DIY efforts break down. JSM tracks SLAs as time-based goals attached to issues with start, pause, and stop timestamps. ServiceNow stores SLA data in the `task_sla` table, with each record tracking elapsed time (`business_time_left`), pause duration (`business_pause_duration`), percentage complete (`business_percentage`), and breach datetime (`planned_end_time`). You cannot simply import a final "SLA met/breached" value — ServiceNow calculates SLAs dynamically based on schedules, conditions, and timestamps.

The `task_sla` table key fields:

| Field | Type | Purpose |
|---|---|---|
| `task` | Reference to `task` | Links SLA record to the incident/request |
| `sla` | Reference to `contract_sla` | Links to the SLA Definition |
| `stage` | Choice | `starting`, `in_progress`, `paused`, `achieved`, `breached` |
| `start_time` | Date/Time | When the SLA clock started |
| `end_time` | Date/Time | When the SLA clock stopped |
| `pause_time` | Date/Time | When the SLA was last paused |
| `pause_duration` | Duration | Total time SLA spent paused |
| `business_time_left` | Duration | Remaining business time before breach |
| `has_breached` | True/False | Whether the SLA breached |
| `original_breach_time` | Date/Time | Calculated breach deadline |

The migration process:

1. **Extract JSM SLA cycle data** via the REST API (`GET /rest/servicedeskapi/request/{issueIdOrKey}/sla`). You need the full lifecycle: `startedAt`, `stoppedAt`, `elapsedTime`, `remainingTime`, `breached`, and `paused` values — not just the screen value. If you have Atlassian Analytics, the JSM SLA schema (`jsm_sla` dataset) exposes this normalized cycle data with millisecond precision. ([support.atlassian.com](https://support.atlassian.com/analytics/docs/schema-for-jira-service-management/))
2. **Create SLA Definitions** in ServiceNow (`contract_sla` table) that match your JSM SLA policies (e.g., "P1 Response: 1 hour," "P2 Resolution: 8 business hours"). Ensure the associated schedule (`cmn_schedule`) matches your JSM business hours calendar.
3. **Insert records into `task_sla`** with the historical timestamps in ISO 8601 datetime format (UTC), associating them with the correct incident `sys_id` and `contract_sla` `sys_id`. ([servicenow.com](https://www.servicenow.com/docs/r/it-service-management/service-level-management/r_TaskSLATable.html))
4. **Run the SLA Repair utility.** This is the step most teams miss. ServiceNow's SLA engine uses a History Walker to reconstruct SLA records from the task's audit history (`sys_audit` table). After importing historical `task_sla` records, SLA Repair recalculates elapsed times and breach indicators based on the imported data rather than the current system time.

> [!CAUTION]
> **Failure mode:** If you import tickets without their SLA history, ServiceNow's SLA engine will attach new SLA records based on current SLA definitions — starting the clock from import time, not from the original creation date. This makes all historical SLA compliance data meaningless. A 50,000-ticket migration without SLA preservation will show 0% historical SLA compliance in ServiceNow dashboards.

For large datasets, batch the SLA Repair operation — running it on 10,000+ records at once can cause significant performance degradation (expect 2–4 hours per 10,000 records depending on audit history depth). Avoid dot-walk-heavy pause logic where possible, because SLA Repair only sees the final state of dot-walk fields, not their full historical progression.

**A practical decision point:** if you only need historical SLA data for reporting, keep Jira SLA outcomes in custom audit fields (`u_original_sla_met`, `u_original_breach_time`) and let native ServiceNow SLAs start fresh at cutover. If you need historical SLAs to behave like native ServiceNow records — e.g., for continuous improvement trend analysis or contractual SLA reporting — map Jira cycle timestamps into a `task_sla`-compatible model and test SLA Repair thoroughly in a sub-production instance before touching production.

## How Do You Migrate JSM Assets to ServiceNow CMDB?

If you're using JSM's Assets feature (formerly Insight), migrating to ServiceNow's CMDB requires translating a schema-free, object-type model into ServiceNow's normalized class hierarchy.

**Key structural differences:**

| JSM Assets Concept | ServiceNow CMDB Equivalent | Gap |
|---|---|---|
| Object Schema | CMDB class hierarchy | JSM schemas are flat; CMDB uses deep inheritance from `cmdb_ci` |
| Object Type | CI Class (e.g., `cmdb_ci_server`, `cmdb_ci_win_server`) | ServiceNow has 400+ OOTB classes; JSM has user-defined types |
| Attribute | CI attribute (column on class table) | ServiceNow attributes are typed and validated; JSM attributes are freeform |
| Object Link | CI Relationship (`cmdb_rel_ci` table) | ServiceNow relationships have defined types (`Runs on::Runs`, `Used by::Uses`) via `cmdb_rel_type` |
| AQL (Assets Query Language) | CMDB Query Builder or `cmdb_ci` list filters | Different query syntax |

**Migration approach:**

1. **Map JSM Object Types to CMDB classes.** Use ServiceNow's CSDM as the guide. JSM's "Server" object type → `cmdb_ci_server`. JSM's "Application" → `cmdb_ci_appl`. Document types that have no CMDB equivalent and decide whether to extend the CMDB schema or map to a generic class.
2. **Export JSM Assets** via the Assets REST API (`GET /jsm/assets/workspace/{workspaceId}/v1/object/list`).
3. **Transform attributes** to match CMDB field types. Freeform text fields that contain IP addresses must map to validated `ip_address` fields. Serial numbers must map to `serial_number` on the correct hardware class.
4. **Import CIs** via the ServiceNow CMDB Identification and Reconciliation Engine (IRE) rather than direct table inserts. IRE uses identification rules to prevent duplicates and maintain CI integrity. Direct inserts bypass IRE and can create orphaned or duplicate CIs.
5. **Rebuild relationships** in the `cmdb_rel_ci` table with the correct `cmdb_rel_type` references.

> [!WARNING]
> **License consideration:** ServiceNow's CMDB is included in ITSM Professional and Enterprise tiers. ITSM Standard includes basic CI storage but not Discovery, Service Mapping, or the full CSDM framework. Verify your ServiceNow license tier supports the CMDB features you need before designing the migration.

## How Do You Translate Jira Automation Rules to ServiceNow Flow Designer?

Automation cannot be migrated programmatically. Jira's "when-if-then" rules and ServiceNow's Flow Designer share a broad structural similarity — trigger, conditions, actions — but the implementation paradigms are too different for automated conversion. Do not attempt to write a script that converts Jira automation JSON into ServiceNow Flow Designer XML. ([support.atlassian.com](https://support.atlassian.com/jira-service-management-cloud/docs/how-do-when-if-and-then-statements-work-for-automation/))

| JSM Automation Component | ServiceNow Equivalent | Implementation Detail |
|---|---|---|
| Trigger (e.g., "Issue Created") | Flow Designer trigger or Business Rule ("after insert") | Business Rules fire synchronously; Flow triggers queue asynchronously |
| Condition (e.g., "Priority = High") | Flow Designer condition or Business Rule condition | BR conditions use `current.priority == 1`; Flow uses GUI condition builder |
| Action (e.g., "Assign to group") | Flow Designer action, Subflow, or Script Action | Flow actions are reusable across flows |
| Scheduled trigger | Scheduled Flow or Scheduled Job (`sysauto_script`) | Scheduled Jobs offer cron-level control |
| Branch rule (if/else) | Flow Designer decision step | Flow supports unlimited branches; BRs use `if/else` in script |
| Smart value (e.g., `{{issue.reporter}}`) | Flow Designer data pills or dot-walk notation (`current.caller_id.email`) | Dot-walk traverses reference fields up to 10 levels |
| Webhook action | IntegrationHub REST step or REST Message (`sys_rest_message`) | IntegrationHub requires a separate subscription on some tiers |

Not every Jira rule belongs in Flow Designer. ServiceNow's Flow Designer queues execution asynchronously when trigger conditions occur, while Business Rules remain the better fit for tight server-side validation, pre-insert guards, or immediate state enforcement tied directly to record operations. ServiceNow documents a default limit of 50 actions per flow unless you change the `com.glide.hub.flow_engine.max_flow_actions` system property. ([servicenow.com](https://www.servicenow.com/docs/r/build-workflows/workflow-studio/flow-designer-arch-overview.html))

**Decision matrix for where to rebuild each rule:**

| Scenario | Use Business Rule | Use Flow Designer |
|---|---|---|
| Field validation before save | ✓ | |
| Auto-populate field on insert | ✓ | |
| Multi-step approval workflow | | ✓ |
| Cross-table record creation | | ✓ |
| Notification with conditions | | ✓ |
| Prevent state transition | ✓ | |
| Integration with external system | | ✓ (via IntegrationHub) |
| Simple field update on condition | ✓ | |

**Practical approach:**

1. Export your JSM automation rules (there's no bulk API — screenshot or document each rule manually, including the rule's audit log showing execution frequency).
2. Categorize rules by complexity and execution frequency. Simple routing and field-update rules can become Business Rules; multi-step approval workflows and cross-table orchestration belong in Flow Designer.
3. Rebuild in ServiceNow. For simple field-update rules, a Business Rule with a script is faster to build than a Flow Designer flow. For anything involving approvals, notifications, or cross-platform integrations, use Flow Designer.
4. Test each rebuilt rule in a sub-production instance before go-live. Use ServiceNow's Flow Designer test mode, which allows you to run flows with test records without affecting production data.

ServiceNow's Flow Designer also integrates with IntegrationHub for cross-platform orchestration — something JSM automation can't do natively. Take the migration as an opportunity to consolidate scattered webhook-based automations into proper IntegrationHub spokes.

## How Do You Migrate Confluence Knowledge Base to ServiceNow Knowledge?

This is consistently the most painful part of a JSM-to-ServiceNow migration. The native options are poor on both sides.

**ServiceNow's built-in import tools don't work well for Confluence:**

- **Import from External Knowledge Sources:** Expects a publicly reachable WebDAV endpoint, supports only Basic auth, and creates a blank knowledge article with the source file attached for each imported file. That's document harvesting, not article migration. ([servicenow.com](https://www.servicenow.com/docs/r/servicenow-platform/knowledge-management/define-an-external-knowledge-source.html))
- **Easy Import:** Loses all images and formatting. Designed for CSV with plain text content.
- **Import from Word:** Numerous formatting issues with complex tables, embedded images, and Confluence macros. Maximum file size of 5 MB per document.

One ServiceNow community user who evaluated all available options for migrating 2,000 articles from Confluence concluded that none of the native tools worked and opted to hire contractors for manual migration.

**Confluence Cloud's export options are also limited.** Confluence Cloud can export spaces as HTML, CSV, PDF, or XML, but Atlassian notes that page comments are not exported in HTML. More significantly, Atlassian says Confluence Cloud XML site and space export reaches end of life on **December 1, 2026** — the feature continues to work, but Atlassian will no longer fix bugs or provide SLAs for it. ([support.atlassian.com](https://support.atlassian.com/confluence-cloud/docs/export-content-to-word-pdf-html-and-xml/))

**The proper approach is API-driven:**

1. **Extract Confluence content as HTML** via the REST API (`GET /wiki/api/v2/pages/{id}?body-format=storage`). This gives you the full HTML body with inline image references in Confluence's XHTML-based storage format. ([developer.atlassian.com](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/))
2. **Download all attachments** separately (`GET /wiki/api/v2/pages/{id}/attachments`) and re-upload them to ServiceNow as `sys_attachment` records on the corresponding `kb_knowledge` article. Rewrite the HTML body to replace Confluence image URLs with new ServiceNow attachment URLs (`/sys_attachment.do?sys_id=...`).
3. **Transform the HTML.** Strip Confluence-specific CSS and macros. Confluence's storage format includes custom macros (`<ac:structured-macro>`) that ServiceNow won't render. Build a **macro register** during discovery: decide for each macro type whether to render to HTML, replace with static text, attach a file, or drop the element.

**Common macro handling decisions:**

| Confluence Macro | Recommended ServiceNow Treatment |
|---|---|
| `<ac:structured-macro ac:name="code">` | Convert to `<pre><code>` block |
| `<ac:structured-macro ac:name="info">` / `warning` / `note` | Convert to styled `<div>` with background color |
| `<ac:structured-macro ac:name="toc">` | Drop (ServiceNow KB has no ToC widget) or generate static HTML ToC |
| `<ac:structured-macro ac:name="expand">` | Convert to `<details><summary>` HTML5 element or flatten |
| `<ac:structured-macro ac:name="jira">` | Replace with static text showing the issue key and summary |
| `<ac:structured-macro ac:name="status">` | Convert to styled `<span>` with appropriate color |
| `<ac:link>` | Convert to standard `<a href>` with updated ServiceNow URLs |
| `<ac:image>` | Convert to `<img>` with re-hosted ServiceNow attachment URL |
| `<ac:emoticon>` | Drop or convert to Unicode emoji |

4. **Insert articles via the ServiceNow Table API** (`POST /api/now/table/kb_knowledge`), setting fields like `kb_knowledge_base`, `kb_category`, `workflow_state` (set to `published` for active articles), `short_description`, and `text` (the transformed HTML body).
5. **Rewrite internal links.** Any Confluence page-to-page links must be updated to point to the new ServiceNow KB article URLs. Build a redirect map: `{confluence_page_id: servicenow_kb_sys_id}` and do a find-replace across all article bodies after import.
6. **Migrate page metadata.** Map Confluence labels to ServiceNow KB article tags. Map Confluence space keys to ServiceNow Knowledge Bases. Map Confluence page hierarchy (parent/child) to ServiceNow KB categories.

For more on Confluence migration complexity, see our [Confluence import guide](https://clonepartner.com/blog/blog/how-to-import-data-into-confluence-methods-api-limits-mapping/).

## Pre-Migration Preparation

### Audit Your JSM Data Model

- Export all issue types, custom fields, workflows, and statuses via the Jira REST API (`GET /rest/api/3/field`, `GET /rest/api/3/workflow/search`, `GET /rest/api/3/status`).
- Document every JQL-based queue and its member agents.
- Map every request type to its underlying work type and fields. ([support.atlassian.com](https://support.atlassian.com/jira-service-management-cloud/docs/whats-the-difference-between-request-types-and-issue-types/))
- Export your automation rules (there's no bulk export — document each rule manually, noting trigger frequency from the rule audit log).
- If you have Atlassian Analytics, `jsm_issue`, `jsm_incident`, `jsm_change`, and `jsm_sla` schemas are useful for count reconciliation and historical validation.
- Record total counts per issue type per project — these are your reconciliation baselines.

### Clean Your Data Before Export

- Archive or delete test tickets, spam, and duplicate issues. In a typical JSM instance, 5–15% of tickets are test data or duplicates.
- Standardize status values across projects — if "Completed" and "Done" mean the same thing, unify them before migration rather than maintaining two mappings.
- Verify that all user accounts have valid email addresses (ServiceNow resolves users by email). Deactivated Jira users should still be mapped to ServiceNow for historical record integrity.
- Tag every comment stream as public or internal before load. JSM's `GET /rest/servicedeskapi/request/{issueIdOrKey}/comment` endpoint returns a `public` boolean on each comment — use this to separate `work_notes` from `comments` during import.

### Account for API Rate Limits on Both Sides

Jira Cloud enforces points-based rate limiting on REST APIs, with burst limits per second and per-hour quotas. Atlassian's current guidance says app-based integrations are subject to points-based quotas starting **March 2, 2026**, while API-token traffic still hits burst limits (typically 100 requests per 10-second window for standard tenants). ([developer.atlassian.com](https://developer.atlassian.com/cloud/jira/service-desk/rest/intro/))

On the ServiceNow side, inbound REST API rate limits are governed by `sys_rate_limit_rules` and enforced per user per hour (default: no limit, but many organizations set 1,000–10,000 requests/hour per integration user). Plan your extraction and loading scripts to handle `429 Too Many Requests` responses with exponential backoff on both sides.

```python
# Pseudocode: Exponential backoff for rate-limited API calls
def api_call_with_retry(url, max_retries=5):
    for attempt in range(max_retries):
        response = http_get(url)
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
            sleep(retry_after)
            continue
        return response
    raise Exception(f"Max retries exceeded for {url}")
```

### Handle Attachments Separately

Jira attachments are stored per-issue and must be downloaded individually via the REST API (`GET /rest/api/3/attachment/content/{id}`). ServiceNow Import Sets have per-processor size constraints — oversized rows can be skipped silently, and large file uploads can fail with partial data loads. ServiceNow's default attachment size limit is 24 MB per file (configurable via `com.glide.attachment.max_size`). Large attachment-heavy migrations should be batched and loaded via the ServiceNow Attachment API (`POST /api/now/attachment/file`) rather than Import Sets. ([servicenow.com](https://www.servicenow.com/docs/r/api-reference/rest-apis/c_ImportSetAPI.html))

### Prepare Your ServiceNow Instance

- Create all Assignment Groups (with the correct `itil` group type), SLA Definitions (`contract_sla` records), and Service Catalog items before importing any data.
- Configure dictionary entries for custom fields on each target table.
- Set up a dedicated integration user with `rest_api_explorer`, `import_set_loader`, `import_transformer`, and table-specific write roles. Allocate rate limit headroom.
- Configure business schedules (`cmn_schedule`) to match your JSM business hours before SLA import.
- Freeze new request types, queue edits, and automation changes during the final validation window.
- Take a snapshot of the sub-production instance before test loads so you can roll back cleanly.

### Consider Your Tooling Options

Native ServiceNow Import Sets and the Table API are the DIY path. Tools like Exalate and Getint position themselves as bidirectional sync layers between Jira and ServiceNow. Precision Bridge positions itself as a template-driven migration platform for ITSM data. These tools can reduce plumbing, but they do not solve target-state design: queue ownership, change models, KB fidelity, and SLA semantics still need deliberate human decisions.

### Plan Your Rollback Strategy

If migration fails mid-flight:

1. **Before migration:** Export a full baseline of ServiceNow target tables using `sys_export_set` or Update Sets for configuration changes.
2. **During migration:** Use a `u_migration_batch_id` field on all imported records so you can identify and delete a failed batch without affecting pre-existing ServiceNow data.
3. **After failed migration:** Delete records by batch ID, restore configuration from Update Sets, and re-run from the failed batch.
4. **JSM remains operational** throughout — never decommission JSM until ServiceNow is fully validated and in production.

## Migration Timeline

| Phase | Duration | What Affects It |
|---|---|---|
| Discovery & field mapping | 3–5 days | Number of custom fields, JSM projects, SLA complexity |
| ServiceNow instance configuration | 5–10 days | Assignment groups, SLA definitions, catalog items, Flow Designer rebuilds |
| Script development & testing | 5–10 days | Volume of records, attachment count, custom field types |
| Data migration (execution) | 1–3 days | Record count, API rate limits, attachment sizes |
| Knowledge base migration | 3–7 days | Article count, image density, macro complexity |
| CMDB/Assets migration | 2–5 days | Number of CIs, relationship complexity, CSDM mapping decisions |
| UAT & SLA validation | 3–5 days | Stakeholder availability, number of SLA policies to verify |
| **Total** | **3–7 weeks** | |

The biggest timeline variables are Confluence KB complexity, the number of JSM automation rules that need to be rebuilt in Flow Designer, and SLA behavior requirements. A JSM instance with 50 automation rules and 2,000 KB articles takes significantly longer than one with 10 rules and no KB. Simple migrations with under 10,000 tickets and no KB can finish in under 2 weeks.

We recommend a **parallel run strategy** rather than a hard cutover. Use a delta migration approach: sync historical data in the background while your team continues working in JSM, followed by a final weekend sync to capture the latest updates. The delta sync identifies records modified since the last extraction using JSM's `updated` JQL field and ServiceNow's `sys_updated_on` timestamp. For broader context on migration planning, see our [Help Desk Data Migration Timeline guide](https://clonepartner.com/blog/blog/help-desk-data-migration-timeline/).

## Common Pitfalls and How to Avoid Them

**1. Mapping all JSM issues to the incident table.**
JSM projects often contain mixed issue types. Dumping everything into `incident` breaks ServiceNow's ITIL process separation and corrupts reporting. Split by issue type during extraction, not after import. Use the routing pseudocode above.

**2. Ignoring the internal/public comment distinction.**
JSM has internal comments (visible to agents only) and customer-visible comments. ServiceNow uses `work_notes` (internal) and `comments` (customer-visible, called "Additional comments") on the task record. If your migration script doesn't distinguish between these, internal notes become visible to end users in the Service Portal. This is a **privacy and compliance issue**, not a formatting issue — it can expose PII, internal troubleshooting notes, or security-sensitive information. ([developer.atlassian.com](https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/))

**3. Losing SLA history by skipping the SLA Repair step.**
Importing tickets without running SLA Repair means ServiceNow applies current SLA definitions from import time. Historical compliance data is gone. Always import SLA timestamps and run repair in batches of 5,000–10,000 records.

**4. Treating Confluence macros as HTML.**
Confluence macros (status labels, expand blocks, table-of-contents, JIRA issue links) are not standard HTML. They render as broken markup or raw XML tags in ServiceNow KB. Use the macro register approach described above to handle each macro type explicitly during transformation.

**5. Not testing state transitions.**
ServiceNow enforces state transition rules — you can't always jump from state 1 (New) to state 7 (Closed) without passing through intermediate states. If your import script sets a closed state on a record that never transitioned through "In Progress" and "Resolved," Business Rules or Flow Designer flows tied to those transitions won't fire, and audit trails will be incomplete. **Workaround:** Temporarily disable state transition Business Rules during import (specifically `incident_state_transition_validation`), then re-enable after migration.

**6. Silent failures on large Import Set loads.**
ServiceNow Import Sets can skip oversized rows or fail to process large files without clear error messages. The import appears to complete but only processes a fraction of records. Always validate row counts after each import batch: compare `SELECT COUNT(*) FROM import_set_row WHERE import_set = '{sys_id}' AND sys_import_state = 'error'` against your source count.

**7. Phantom ownership from queue-to-group mapping.**
Copying queue names as assignment groups without setting the correct group types, memberships, or routing rules means records load successfully but are unassignable in the UI or ignored by assignment rules. Design the ownership model explicitly, including the `type` field on `sys_user_group`.

**8. Timezone mismatches on datetime fields.**
JSM stores and displays datetimes in the user's configured timezone. ServiceNow stores all datetimes internally in UTC. If your extraction script doesn't normalize to UTC before import, timestamps will be off by the offset of whatever timezone the Jira admin account uses. Always convert to ISO 8601 UTC (`2025-06-15T14:30:00Z`) before loading.

**9. Missing Service Catalog design.**
JSM request types map to ServiceNow catalog items, but catalog items require variables (form fields), variable sets, execution plans, and approval policies. Simply creating a catalog item with a matching name but no variables means end users see a blank form. Design catalog items with the same fields that existed on the JSM request type forms.

If a migration has already gone sideways, our [migration rescue guide](https://clonepartner.com/blog/blog/help-desk-data-migration-failed-the-engineers-rescue-guide/) covers recovery strategies.

## How ClonePartner Handles JSM-to-ServiceNow Migrations

We've completed 1,500+ data migrations across ITSM, CRM, and ERP platforms. JSM-to-ServiceNow is a migration we've executed repeatedly, and we know where the failure modes hide.

Our approach:

- **API-first extraction and loading.** We don't rely on CSV exports or Import Sets for anything beyond simple reference data. Custom scripts extract from Jira's REST API and load directly into ServiceNow's Table API with proper batching, retry logic, and rate limit handling.
- **SLA timestamp preservation.** We map historical SLA data to `task_sla` with full start/pause/stop timestamps and run SLA Repair in controlled batches — preserving your compliance history.
- **CMDB migration with IRE.** We use ServiceNow's Identification and Reconciliation Engine for CI imports, preventing duplicate or orphaned CIs that plague direct-insert approaches.
- **Confluence KB migration with formatting intact.** We parse Confluence storage format, strip macros per a documented macro register, re-host images as ServiceNow attachments, and rewrite internal links. No manual copy-paste.
- **Zero-downtime execution.** Both platforms stay operational during migration. We run delta syncs to capture records created during the migration window. See our [zero-downtime migration approach](https://clonepartner.com/blog/blog/zero-downtime-help-desk-data-migration/) for how this works.
- **Compliance-ready.** SOC 2 Type II, ISO 27001, HIPAA, and GDPR compliant. Your data never touches an uncontrolled environment.

If your JSM instance is small — few request types, no KB, no SLA backfill — an in-house script can be reasonable. Once you need audit-grade history or a weekend cutover with little tolerance for rework, it usually stops being a side project.

> Planning a JSM-to-ServiceNow migration? We'll map your data model, preserve SLA history, migrate your Confluence KB, and keep your desk live during cutover.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### How long does a Jira Service Management to ServiceNow migration take?

Most migrations take 3–6 weeks covering discovery, ServiceNow configuration, data migration, Confluence KB transfer, and UAT. Simple environments with under 10K tickets and no knowledge base can complete in under 2 weeks. The main variables are KB article count, SLA complexity, and number of automation rules to rebuild.

### Can I migrate SLA history from JSM to ServiceNow?

Yes, by extracting SLA cycle timestamps from Jira's API, inserting them into ServiceNow's task_sla table with ISO 8601 datetime values, and running the SLA Repair utility. Skipping the Repair step means ServiceNow creates new SLA records from import time, destroying historical compliance data.

### Will Confluence articles keep their formatting in ServiceNow Knowledge Base?

Not with native tools. ServiceNow's Easy Import loses images and formatting; Import from External Sources brings content as attachments. The proper method is API-based: extract Confluence HTML, strip macros, re-host images as ServiceNow attachments, and insert into kb_knowledge via the Table API.

### Do Jira automation rules transfer to ServiceNow Flow Designer automatically?

No. There is no automated conversion path. Each JSM automation rule must be manually documented and rebuilt in ServiceNow — as a Business Rule for simple field updates, or as a Flow Designer flow for multi-step workflows involving approvals, notifications, or cross-table logic.

### How do Jira queues map to ServiceNow assignment groups?

They don't map directly. JSM queues are JQL-based filters where one ticket can appear in multiple queues. ServiceNow assignment groups are strict user-membership entities with a single assignment per ticket. Migration requires translating queue filter logic into assignment groups with the correct itil group type, plus routing rules or Flow Designer flows.
