---
title: "Dynamics NAV to IFS Migration: The Technical Guide"
slug: dynamics-nav-to-ifs-migration-the-technical-guide
date: 2026-07-31
author: Roopi
categories: [Migration Guide]
excerpt: "A technical guide to migrating from Dynamics NAV to IFS Cloud. Covers data extraction, entity mapping, API constraints, and ETL architecture for zero-loss ERP transitions."
tldr: "There's no migration wizard between NAV and IFS. Every migration is a custom ETL project — extract from NAV's SQL Server, transform against IFS's entity model, and load through its business-logic-enforced API layer."
canonical: https://clonepartner.com/blog/dynamics-nav-to-ifs-migration-the-technical-guide/
---

# Dynamics NAV to IFS Migration: The Technical Guide


Migrating from Microsoft Dynamics NAV to IFS Cloud is an architectural translation — from a SQL Server-backed, C/AL-customized ERP into an Oracle-based, OData-first platform built for asset-intensive industries. There is no vendor-provided migration wizard between these two systems. Every NAV-to-IFS migration is a custom ETL project that demands deep understanding of both data models, deliberate scoping of what transactional history to carry forward, and respect for IFS's business-logic-enforced import layer.

If you treat this as a bulk data copy, you will spend cutover week fixing rejected records, broken parent-child relationships, and state machine violations. The safer approach is to decide early which objects move through file loads, which through APIs, which through IFS Data Migration jobs, and which should be archived rather than forced into the target. ([docs.ifs.com](https://docs.ifs.com/techdocs/25R2/030_administration/050_data_management/050_data_migration/))

This guide covers extraction strategies from NAV, the IFS Cloud import architecture, entity-level data mapping, API constraints on both sides, and the edge cases that derail ERP migrations at the data layer.

For a broader look at common ERP migration failure patterns, see [Why ERP Migrations Fail at the Data Layer: 9 Core Patterns](https://clonepartner.com/blog/blog/why-erp-migrations-fail-at-the-data-layer-9-core-patterns/).

## Why Companies Move from Dynamics NAV to IFS Cloud

The migration wave is driven by three converging pressures.

**End-of-support deadlines are closing fast.** NAV 2016's extended support ended on April 14, 2026. NAV 2017 exits extended support on January 11, 2027, and NAV 2018 — the final NAV release — loses all Microsoft support on January 11, 2028. After those dates: no security patches, no compliance updates, no regulatory fixes. ([learn.microsoft.com](https://learn.microsoft.com/en-us/lifecycle/products/dynamics-nav-2016))

**Operational fit.** NAV was built as a generalist SMB ERP. Companies in manufacturing, aerospace, energy, and utilities outgrow it because NAV lacks native Enterprise Asset Management (EAM) and Field Service Management (FSM). IFS Cloud unifies ERP, EAM, and FSM on a single data model, eliminating the bolt-on integrations that NAV environments accumulate over time.

**Customization debt.** Long-running NAV instances accumulate C/AL modifications, custom tables in the 50000–99999 range, and ISV add-ons. At a certain threshold — typically when annual maintenance cost on unsupported custom code exceeds 30–40% of the migration investment — migration becomes the cheaper path.

**Important scope note:** Many organizations that started on Dynamics NAV have since upgraded to Dynamics 365 Business Central. Business Central uses AL (not C/AL), runs on Azure SQL, exposes a different API surface (v2.0 REST APIs with built-in pagination and webhooks), and uses different table naming conventions. This guide is scoped to on-premises Dynamics NAV (2009–2018). If your environment has already been upgraded to Business Central, the extraction strategies — particularly the OData and SQL sections — require adjustment.

## Core Architectural Differences: NAV vs IFS Cloud

Before touching data, understand what you're translating between.

| Dimension | Dynamics NAV | IFS Cloud |
|---|---|---|
| **Database** | SQL Server | Oracle |
| **Development language** | C/AL (legacy) / AL (Business Central era) | PL/SQL + composable extensions |
| **API model** | OData v4, SOAP web services | OData REST (API-first, all entities exposed via projections) |
| **Data import** | XMLports, RapidStart, direct SQL | Data Migration (FNDMIG), Excel Add-in, REST API, Entity Service APIs (24R2+) |
| **Multi-company** | Separate company databases within single instance | Multi-site, multi-company with shared data model |
| **Customization model** | Direct table modifications, C/AL codeunits | Composable extensions, custom logical units |
| **Asset management** | Basic or via ISV add-ons | Native EAM with full lifecycle management |
| **Deployment** | On-premises only | Cloud, on-premises, or hybrid |

The core tension: NAV lets you modify tables directly and insert records via SQL — and most long-running instances have done exactly that. IFS enforces business logic through its API layer. You cannot bypass it with direct SQL inserts into IFS's Oracle database. Every record imported into IFS must pass through business logic validators, which means your data must be clean *before* it reaches IFS.

IFS operates on a **strict state machine model**. You cannot insert an order with a "Closed" or "Invoiced" status. The record must pass through the correct state transitions via the API, or be loaded into specific historical archive tables. This is the single most common failure point in NAV-to-IFS migrations. When you violate a state transition, IFS returns errors like `STATE_NOT_ALLOWED` or `TRANSITION_NOT_PERMITTED` — these indicate the record's lifecycle state is incompatible with the operation you're attempting.

## Migration Approaches

There is no single correct method. The approach depends on data volume, customization complexity, and whether you need a one-time cutover or ongoing synchronization.

### 1. Direct SQL Extraction + IFS Data Migration (FNDMIG)

**How it works:** Query NAV's SQL Server database directly to extract master and transactional data into flat files. Transform the data offline, then load it into IFS using the built-in Data Migration framework (FNDMIG) or the IFS Data Migration Excel Add-in. ([docs.ifs.com](https://docs.ifs.com/techdocs/25R2/030_administration/050_data_management/050_data_migration/))

**When to use it:** One-time migrations with moderate data volumes. Best when your team has SQL expertise and direct access to NAV's database.

**Pros:**
- Full access to every table, including custom tables and historical transactions
- No API rate limits on the extraction side
- FNDMIG loads data through IFS business logic, ensuring referential integrity

**Cons:**
- Requires understanding NAV's internal table naming conventions (company-prefixed names that vary per installation)
- FNDMIG jobs require projection-level permissions in IFS Cloud
- No real-time capability

**Complexity:** Medium

### 2. API-to-API Migration (NAV OData → IFS REST)

**How it works:** Use NAV's OData v4 or SOAP web services to extract data programmatically, transform in-flight, and POST to IFS Cloud's OData REST endpoints. ([learn.microsoft.com](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v1.0/enabling-apis-for-dynamics-nav))

**When to use it:** When you lack direct SQL access to NAV (common in hosted or partner-managed environments), or when you need incremental/delta migrations during a parallel-run period.

**Pros:**
- No direct database access required
- Both platforms speak OData, reducing protocol translation overhead
- Supports incremental extraction using `$filter` on timestamps

**Cons:**
- NAV OData services must be explicitly published for each page/entity — requires admin access to NAV's web services configuration
- NAV's OData layer is slow for large datasets — no bulk endpoint, and a default page size limit of 20,000 records
- IFS REST API enforces business logic validation on every POST — malformed data is rejected at the API boundary
- Authentication differs: NAV uses NTLM/Negotiate, IFS uses OAuth 2.0 client credentials

**Complexity:** High

### 3. Custom ETL Pipeline

**How it works:** Build a dedicated extraction-transformation-loading pipeline using Python, Node.js, or a tool like Apache NiFi. Extract from NAV via SQL or OData, transform data in a staging database, and load into IFS via REST API or FNDMIG.

**When to use it:** Enterprise migrations with complex transformations — chart of accounts restructuring, multi-company consolidation, or when NAV carries heavy customization in the 50000-range tables.

**Pros:**
- Full control over transformation logic, error handling, and retry mechanisms
- Can handle millions of records with batching and parallelization
- Staging database enables iterative validation before loading

**Cons:**
- Requires development investment (typically 4–8 weeks for build + test)
- Must maintain the pipeline through UAT cycles and the cutover window
- Requires engineers who understand both NAV semantics and IFS target behavior

**Complexity:** High

### 4. Middleware / iPaaS Platforms (Boomi, MuleSoft, Zapier)

**How it works:** Use an integration platform with connectors for NAV and IFS Cloud. Configure data flows visually with built-in mapping and transformation tools.

**When to use it:** Post-migration ongoing sync, or organizations already invested in an iPaaS platform with connectors for both systems. Not suitable as the primary historical migration engine.

**Pros:**
- Visual mapping tools reduce development time
- Built-in error handling and monitoring
- Can be repurposed for post-migration integrations

**Cons:**
- Connector quality varies — many "NAV connectors" are thin OData wrappers with no bulk support
- Zapier's documented support is centered on Business Central; community guidance notes no direct support for Dynamics on-prem ([help.zapier.com](https://help.zapier.com/hc/en-us/articles/20255464575757-How-to-get-started-with-Microsoft-Dynamics365-Business-Central-on-Zapier))
- Not optimized for high-volume historical data loads
- Licensing cost is additive on top of both ERP licenses

**Complexity:** Medium

### 5. Managed Migration Service

**How it works:** A specialist migration team handles extraction, transformation, loading, validation, and cutover. You define scope and mapping rules; they execute.

**When to use it:** When your engineering team is already committed to IFS implementation work and cannot absorb the migration workload. Also appropriate when NAV is heavily customized and building internal expertise for a one-time project doesn't justify the cost.

**Pros:**
- Predictable timeline and cost
- Migration expertise reduces risk of data loss and broken relationships
- Frees internal team to focus on IFS configuration and testing

**Cons:**
- Requires clear communication of business rules and custom logic
- Vendor dependency for schedule and execution

**Complexity:** Low (for your team)

### Migration Approach Comparison

| Approach | Best For | Typical Volume Range | Ongoing Sync? | Complexity |
|---|---|---|---|---|
| SQL + FNDMIG | One-time, mid-volume | Hundreds of thousands of records | No | Medium |
| API-to-API | Incremental/delta | Tens of thousands per sync cycle (constrained by NAV OData pagination and IFS API throughput) | Yes | High |
| Custom ETL | Enterprise, complex transforms | Millions+ (with batching and parallelization) | Partially | High |
| iPaaS / Middleware | Light post-migration sync | Hundreds of thousands (constrained by connector throughput) | Yes | Medium |
| Managed Service | Any scale, constrained team | Any | N/A | Low |

*Note: Volume ranges are directional based on typical migration patterns. Actual throughput depends on NAV server hardware, network topology, IFS Cloud environment tier, API concurrency limits, and record complexity. Always benchmark with representative data in your specific environment.*

**Recommendations by scenario:**
- **Small business, one-time move:** CSV/FNDMIG for master data. Manually recreate open transactions if volume is low.
- **Enterprise migration:** Custom ETL (SQL extraction) combined with IFS API or FNDMIG loading.
- **Ongoing NAV + IFS coexistence:** API-based sync or custom integration. Not CSV.
- **Low engineering bandwidth:** Managed service. DIY heroics on a one-time ERP migration rarely pay off.

## Pre-Migration Planning

Before writing a single line of migration code, audit what's actually in your NAV database.

### Data Audit Checklist

- **Customers & Vendors (Tables 18, 23):** Active vs. blocked records. NAV's `Blocked` field has multiple states (empty, Ship, Invoice, All) — decide which to migrate.
- **Chart of Accounts (Table 15):** Map NAV's G/L Account table to IFS's accounting code structure. Watch for account types that don't translate directly.
- **Items / Inventory (Table 27):** NAV's item table carries costing method (FIFO, LIFO, Average, Standard, Specific) — IFS uses different costing terminology.
- **Open Transactions:** Sales orders (Table 36), purchase orders (Table 38), production orders in progress at cutover.
- **Posted Transactions:** G/L entries (Table 17), customer/vendor ledger entries. Decide how much history to migrate vs. archive.
- **Fixed Assets (Table 5600):** Depreciation books, posted depreciation entries, disposal history.
- **Custom Tables:** Any table with an ID in the 50000–99999 range is a custom object. Catalog every one.
- **Dimensions (Table 349):** NAV's dimension framework (Global Dimensions 1 & 2, plus shortcut dimensions) must map to IFS's code parts.
- **FlowFields:** NAV uses calculated fields (FlowFields) that do not exist as physical data in SQL. These must be calculated during extraction.
- **Attachments:** NAV stores attachments in the `Document Attachment` table or via links to file shares/SharePoint.

### Migration Strategy: Big Bang vs. Phased

**Big bang** works for smaller NAV instances (single company, <50 users) where a weekend cutover window is feasible. Freeze NAV on Friday, migrate Saturday, validate Sunday, go live Monday.

**Phased migration** is necessary when multiple NAV companies exist or when IFS modules are being implemented in stages (e.g., Finance first, then Manufacturing, then EAM). Migrate master data first, run parallel for a period, then migrate open transactions at cutover.

**Incremental / delta sync** applies when the parallel-run period extends beyond a weekend. Migrate the bulk initially, then run delta extracts on modified records until cutover.

**Scope strategy:** Do not migrate 15 years of closed purchase orders into live IFS transactional tables. Migrate 2–3 years of historical data. Archive the rest in a data warehouse. For guidance on what data is worth moving versus archiving, see [What Data Should You Actually Migrate to Your New ERP?](https://clonepartner.com/blog/blog/what-data-should-you-actually-migrate-to-your-new-erp/).

## Data Model & Object Mapping

This is where NAV-to-IFS migrations succeed or fail. The two systems share similar concepts but implement them differently.

### Core Entity Mapping

| NAV Entity (Table) | NAV Table ID | IFS Cloud Entity | Notes |
|---|---|---|---|
| Customer | 18 | CustomerInfo | Map `No.` to `customer_id`. IFS separates customer identity from addresses (`CustomerInfoAddress`). |
| Vendor | 23 | SupplierInfo | NAV vendor terms → IFS payment terms mapping required. |
| Contact | 5050 | PersonInfo / CommMethod | Create as Person in IFS, then link to Customer via `CustomerInfoContact`. |
| Item | 27 | PartCatalog / InventoryPart / SalesPart | IFS distinguishes general part definition from site-specific inventory parameters. |
| G/L Account | 15 | Account | Restructure chart of accounts to fit IFS code part structure. |
| Sales Header | 36 | CustomerOrder | Map document types. IFS state machine applies. |
| Sales Line | 37 | CustomerOrderLine | Line-level item references and pricing. |
| Purchase Header | 38 | PurchaseOrder | Includes approval workflow state mapping. |
| Purchase Line | 39 | PurchaseOrderLine | Unit of measure conversions critical here. |
| G/L Entry | 17 | GeneralLedgerVoucher | Posted entries — decide on history depth. |
| Item Ledger Entry | 32 | InventoryTransaction | Costing and quantity tracking. |
| Fixed Asset | 5600 | FixedAsset | Depreciation method translation required. |
| Production BOM | 99000771 | ProductionStructure | Bill of materials mapping. |
| Routing | 99000764 | Routing | Operation-level mapping. |
| Dimension Value | 349 | CodePart (B–J) | NAV dimensions → IFS accounting code parts. |

### Handling NAV Dimensions → IFS Code Parts

This is one of the most underestimated mapping challenges. NAV supports up to 8 shortcut dimensions plus unlimited dimension sets. IFS uses a fixed structure of up to 10 code parts (A through J), where Code Part A is always the account.

You must decide:
- Which NAV dimensions map to which IFS code parts
- How to handle dimension combinations that don't exist in NAV's dimension set entries
- Whether to flatten rarely-used dimensions or carry them as custom attributes

**Structural framework for dimension mapping:**

1. **Identify NAV's Global Dimensions 1 and 2** — these are the most heavily used and should map to IFS Code Parts B and C (or whichever code parts your IFS implementation designates as primary analytical dimensions).
2. **Map shortcut dimensions 3–8** to remaining IFS Code Parts D–J based on reporting requirements. If you have more than 9 analytical dimensions in NAV, you must consolidate — IFS's 10-part structure (A reserved for account) is a hard ceiling.
3. **Dimension set entries** (Table 480 in NAV) represent unique dimension combinations. Export these to verify that every combination has a valid mapping in IFS before migrating transactions that reference them.
4. **Default dimensions** (Table 352 in NAV) — these drive automatic dimension assignment on transactions. Rebuild equivalent logic in IFS using posting control rules or default code part values on master data.

### NAV Posting Groups → IFS Posting Control

NAV uses Customer/Vendor/General/VAT Posting Groups to determine G/L account assignment. IFS uses Posting Control rules. These are architecturally different — you cannot copy posting group assignments.

**Mapping framework:**

1. **Document NAV's posting group matrix.** NAV combines General Business Posting Group + General Product Posting Group to determine the G/L accounts for sales, purchases, COGS, and inventory. Export the General Posting Setup (Table 252) to see every combination.
2. **Map each combination to IFS posting control rules.** In IFS, posting control is configured per posting type (e.g., `M1` for material cost, `M3` for inventory valuation) and driven by control types (site, part group, project, etc.) rather than a flat matrix.
3. **Rebuild, don't translate.** IFS posting control is more granular than NAV posting groups. Work with your IFS finance consultant to define the posting type → control type → code part derivation rules. Then validate by running test transactions and comparing the resulting voucher entries against what NAV would have posted.

### IFS Entity Service APIs vs. Standard Projections

IFS Cloud offers two API surface types relevant to migration:

**Standard projections** are tightly coupled to specific Aurena pages. They expose the entities and actions needed for that page's UI. These are what you see at `projection/v1/<ProjectionName>.svc`. They work well for CRUD operations on individual entities but may not expose all fields or all entity types needed for migration.

**Entity Service APIs** (available from IFS Cloud 24R2 onward) provide a more generic, entity-centric API surface designed for integration and data loading. They expose logical units directly rather than through page-specific projections, making them better suited for bulk migration scenarios where you need access to entities that lack a convenient standard projection. Entity Service APIs follow the pattern `entityservice/v1/<EntityName>`.

For migration, evaluate which entities have usable standard projections and which require Entity Service APIs. In some cases, you may need to request custom integration projections from your IFS implementation partner.

### Custom Objects

NAV custom tables (ID 50000+) have no automatic equivalent in IFS. For each custom table, you have three options:

1. **Map to an existing IFS entity** if a functional equivalent exists
2. **Create a custom logical unit in IFS** (requires IFS development expertise — custom LUs must be modeled through IFS's component architecture, not ad-hoc table creation)
3. **Archive the data externally** if it's historical or reporting-only

Where possible, prefer **custom attributes** on existing IFS entities over custom entities. IFS custom entities are flat and not suited to complex hierarchies. Some IFS entities also cannot be extended with custom attributes due to design or performance constraints. ([docs.ifs.com](https://docs.ifs.com/techdocs/26r1/040_tailoring/225_configuration/950_configuration_references/030_customattributes/))

> [!TIP]
> Add a persistent legacy key (e.g., `LegacyNavNo`) as a custom attribute to every target entity you care about. In IFS, persistent custom attributes are stored in the database, making them useful as idempotency keys, deduplication anchors, and rollback lookups.

### Sample Field-Level Mapping

| Dynamics NAV (Table 18 - Customer) | IFS (CustomerInfo) | Transformation |
|---|---|---|
| `No_` | `CustomerId` | String (Max 20). Preserve as-is or remap. |
| `Name` | `Name` | String. IFS limit may be shorter — truncate if needed. |
| `Address` | `Address1` (CustomerInfoAddress) | String (Max 35). |
| `City` | `City` (CustomerInfoAddress) | String (Max 35). |
| `Country_Region Code` | `Country` | 2-char ISO → may require full country database ID in IFS. |
| `Currency Code` | `CurrencyCode` | String (ISO 3). |
| `Payment Terms Code` | `PayTermId` | String mapping required — NAV and IFS payment term IDs won't match. |

## Migration Architecture

A resilient migration architecture separates extraction, transformation, and loading into distinct phases with a staging layer in between.

```
┌─────────────┐     ┌──────────────┐     ┌──────────────┐     ┌───────────┐
│ Dynamics NAV │────▶│  Staging DB  │────▶│  Transform   │────▶│ IFS Cloud │
│  (SQL Server)│     │ (PostgreSQL/ │     │  (Python/ETL)│     │ (REST API │
│              │     │  SQL Server) │     │              │     │  / FNDMIG)│
└─────────────┘     └──────────────┘     └──────────────┘     └───────────┘
         │                                                          │
    SQL / OData                                              OData REST /
    extraction                                              Excel Add-in
```

### NAV Extraction

**Direct SQL** is the fastest and most complete extraction method. NAV stores all data in SQL Server with predictable table names (prefixed by company name):

```sql
-- Extract active customers from NAV
SELECT [No_], [Name], [Address], [City], [Post Code], 
       [Country_Region Code], [Phone No_], [E-Mail],
       [Currency Code], [Payment Terms Code], [Blocked]
FROM [CRONUS].[dbo].[CRONUS International Ltd_$Customer]
WHERE [Blocked] = 0
```

NAV's OData endpoint can also be used but returns a maximum of 20,000 records per request by default. Use `$top` and `$skip` for pagination, and `$filter` for incremental extracts based on `Last Date Modified`. For tables with millions of entries (G/L Entry, Item Ledger Entry), SQL extraction is significantly faster. On-prem NAV API endpoints typically use port 7048 and must be admin-enabled. ([learn.microsoft.com](https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v1.0/enabling-apis-for-dynamics-nav))

> [!WARNING]
> **FlowFields:** NAV uses calculated fields that do not exist as physical data in SQL. If your IFS mapping depends on FlowField values (e.g., `Balance (LCY)` on the Customer table, which aggregates from Customer Ledger Entry), you must write SQL views or queries to aggregate the underlying data before extraction. Identify every FlowField in your source tables using NAV's Object Designer or metadata queries against NAV's `Field` system table.

### IFS Cloud Import Methods

**REST API (OData):** IFS Cloud follows an API-first design — every action possible in the Aurena UI can be executed via OData REST endpoints. Authentication is OAuth 2.0 (Client Credentials flow). IFS exposes OpenAPI documentation at `.../projection/v1/<name>.svc/$openapi`. ([docs.ifs.com](https://docs.ifs.com/techdocs/25r1/040_tailoring/300_extensibility/010_get_started/100_api_documentation/))

Authentication flow:

```http
POST https://<SYSTEM_URL>/auth/realms/<NAMESPACE>/protocol/openid-connect/token
grant-type=client_credentials
client_id=<IFS_CLIENT_ID>
client_secret=<IFS_CLIENT_SECRET>
scope=openid microprofile-jwt
```

Example entity creation:

```http
POST https://<ifs-host>/main/ifsapplications/projection/v1/CustomerHandling.svc/CustomerInfoSet
Authorization: Bearer <token>
Content-Type: application/json

{
  "CustomerId": "CUST001",
  "Name": "Acme Manufacturing",
  "DefaultLanguage": "en",
  "Country": "US"
}
```

**Common IFS API error responses during migration:**

| HTTP Status | Typical IFS Error | Cause | Resolution |
|---|---|---|---|
| 400 | `REFERENCE_NOT_FOUND` | Foreign key target doesn't exist (e.g., PayTermId not set up) | Load reference data first; verify lookup tables |
| 400 | `STATE_NOT_ALLOWED` | Attempting to create/update record in an invalid lifecycle state | Use correct state transitions or load via historical tables |
| 400 | `VALUE_TOO_LARGE` | Field value exceeds IFS column length | Truncate during transformation |
| 400 | `MANDATORY_NOT_NULL` | Required field missing | Add default value in transformation |
| 409 | `RECORD_EXIST` | Duplicate primary key | Expected for idempotent reruns; log and skip |
| 429 | (throttling) | Too many requests | Implement exponential backoff |

**IFS Data Migration (FNDMIG):** The built-in migration framework loads data through IFS business logic APIs. Create migration jobs in Solution Manager → Data Management → Data Migration, then populate via the Excel Add-in or file upload. This is the safest import path because it enforces all validation rules. For high-volume loads, IFS supports staged migration with tunable `PARALLELLEVEL`, `BULKLIMIT`, and `CHUNKSIZE` parameters, but the high-volume procedure is insert-only — updates and upserts are not supported in high-volume mode. ([docs.ifs.com](https://docs.ifs.com/techdocs/24r2/030_administration/050_data_management/050_data_migration/030_migration_types/020_source_migration/))

**IFS Data Migration Manager:** For governance-heavy migrations, IFS provides a Data Migration Manager that supports harmonization, cleansing, duplicate flagging, and deployment tracking. The Migration Manager sits above FNDMIG and adds workflow controls (approve/reject migration batches), data quality scoring, and audit trails suitable for regulated industries. ([docs.ifs.com](https://docs.ifs.com/techdocs/25R1/030_administration/050_data_management/080_data_migration_manager/))

> [!WARNING]
> Do not attempt direct SQL inserts into IFS's Oracle database. IFS's business logic layer enforces referential integrity, state machine transitions, and audit logging that direct inserts bypass. Records inserted via SQL will cause downstream failures in posting, reporting, and workflow execution.

### Handling Rate Limits

IFS Cloud APIs will throttle aggressive traffic. Public IFS documentation describes API classes and performance guards rather than a single universal rate limit — treat throughput planning as projection- and environment-specific. ([docs.ifs.com](https://docs.ifs.com/policy/APIUsageCloud.pdf)) IFS `$batch` requests process parts sequentially, and change sets are all-or-nothing. ([docs.ifs.com](https://docs.ifs.com/techdocs/26r1/040_tailoring/300_extensibility/050_ifs_odata_performance_and_security_optimization/020_batch_requests/))

Implement exponential backoff in your load scripts. Retry on HTTP 429, 503, and 504 responses. On the NAV side, on-prem OData settings also have concurrency and queue limits that can surface 429 responses under load.

**Throughput benchmarking:** Before your first test migration, run a throughput test by loading 1,000 records of your most complex entity type (typically CustomerOrder or PurchaseOrder) and measuring records-per-minute. This gives you a realistic basis for estimating cutover window duration. Factors that affect throughput: IFS environment tier (cloud vs. on-prem), record complexity (number of child entities), active business logic (custom validations), and concurrent users.

## Step-by-Step Migration Process

### Step 1: Extract from NAV

Extract data in dependency order — parent entities before children:

1. Chart of Accounts and Dimensions
2. Customers and Vendors
3. Items (with Units of Measure and Item Categories)
4. Fixed Assets and Depreciation Books
5. Open Sales Orders and Purchase Orders
6. Production BOMs and Routings
7. Historical G/L Entries (scoped by date range)
8. Custom tables

```python
import pyodbc

def extract_nav_customers(conn_string, company_name):
    conn = pyodbc.connect(conn_string)
    cursor = conn.cursor()
    
    table = f"[{company_name}$Customer]"
    query = f"""
        SELECT [No_], [Name], [Name 2], [Address], [Address 2],
               [City], [Post Code], [County], [Country_Region Code],
               [Phone No_], [E-Mail], [Currency Code],
               [Payment Terms Code], [Customer Posting Group],
               [Gen_ Bus_ Posting Group], [VAT Bus_ Posting Group],
               [Blocked], [Last Date Modified]
        FROM {table}
        WHERE [Blocked] = 0
    """
    
    rows = cursor.execute(query).fetchall()
    columns = [desc[0] for desc in cursor.description]
    return [dict(zip(columns, row)) for row in rows]
```

### Step 2: Transform

Transformation handles three categories of changes:

**Structural mapping** — field names, data types, and entity relationships. NAV's `No_` becomes IFS's `CustomerId`. NAV's `Country_Region Code` (2-character ISO) maps to IFS's `Country` field. NAV's integer-based Option fields (e.g., `Status: 0, 1, 2`) must map to IFS's string-based state values (e.g., `Planned`, `Released`, `Closed`).

**Value mapping** — picklist and code translations. NAV payment terms like `1M(8D)` must map to IFS payment term IDs. Build a lookup table for every coded field.

**Data cleansing** — fix inconsistencies before they hit IFS validation:
- Duplicate phone numbers or emails across records
- Addresses exceeding IFS field length limits
- Missing mandatory fields that NAV allowed as optional
- Orphaned records (e.g., Sales Lines with no corresponding Sales Header)

```python
def transform_customer_for_ifs(nav_customer, payment_terms_map, country_map):
    return {
        "CustomerId": nav_customer["No_"].strip(),
        "Name": nav_customer["Name"][:100],  # IFS name field limit
        "Country": country_map.get(
            nav_customer["Country_Region Code"], "US"
        ),
        "DefaultLanguage": "en",
        "PaymentTermId": payment_terms_map.get(
            nav_customer["Payment Terms Code"], "NET30"
        ),
    }
```

### Step 3: Load into IFS

Load in dependency order, just like extraction. Implement retry logic with exponential backoff for API failures:

```python
import requests
import time

def load_customer_to_ifs(ifs_host, token, customer_data):
    url = f"{ifs_host}/main/ifsapplications/projection/v1/"
    url += "CustomerHandling.svc/CustomerInfoSet"
    
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    max_retries = 5
    for attempt in range(max_retries):
        response = requests.post(url, json=customer_data, headers=headers)
        
        if response.status_code == 201:
            return {"status": "created", "id": customer_data["CustomerId"]}
        elif response.status_code == 409:
            return {"status": "duplicate", "id": customer_data["CustomerId"]}
        elif response.status_code in (429, 503, 504):
            wait = 2 ** attempt
            time.sleep(wait)
        else:
            return {
                "status": "error",
                "id": customer_data["CustomerId"],
                "detail": response.text
            }
    
    raise Exception(f"Max retries exceeded for {customer_data['CustomerId']}")
```

Make loads **idempotent** so reruns do not create duplicates. Write every source key, target key, and error message to an audit table. Quarantine bad rows instead of stopping the entire batch — unless referential integrity requires a hard stop.

### Step 4: Rebuild Relationships

Once base records (Customers, Items, Vendors) are in IFS, run a second pass to create linking records:
- Customer → delivery addresses → invoice addresses
- Customer → contact persons (PersonInfo → CustomerInfoContact)
- Item → supplier catalog entries
- Item → BOM components → routing operations
- Sales orders → order lines → item references

Never join on mutable names. Use legacy keys or staging crosswalk IDs.

### Step 5: Validate

Run validation before declaring migration complete. See the Validation & Testing section below.

## Edge Cases & Challenges

### The State Machine Trap

IFS requires transactional records (orders, work orders) to follow a strict lifecycle. You cannot insert an order with a "Closed" state. You must either:
- Insert it as "Planned," progress it through "Released," and close it via the API — which triggers all intermediate business logic (inventory reservations, approval workflows, etc.)
- Use IFS's specific historical data APIs or archive tables to bypass the state engine for legacy data
- For truly historical data, migrate only summary balances rather than individual transactions

This is the most common source of migration failures against IFS. Budget significant testing time for transactional entity migration. In test migrations, expect 10–30% of historical transactions to fail state machine validation on the first attempt.

### NAV Posting Groups → IFS Posting Control

See the detailed mapping framework in the Data Model & Object Mapping section above.

### Duplicate Records

NAV environments frequently have duplicate customers or vendors created over years of use. IFS enforces unique customer IDs. Run deduplication *before* migration, not during. IFS Data Migration Manager supports duplicate flagging, but only if you define match rules up front. ([docs.ifs.com](https://docs.ifs.com/techdocs/25R1/030_administration/050_data_management/080_data_migration_manager/))

### Multi-Company NAV → IFS Sites

NAV separates companies within a single database using table name prefixes. IFS uses a multi-site architecture with shared master data. Decide early whether NAV companies become IFS sites or IFS companies — the data flow is different for each. Key decision criteria:
- If NAV companies share customers/vendors/items → IFS sites within one company (shared master data)
- If NAV companies are legally distinct entities with separate charts of accounts → separate IFS companies

### Attachments and Documents

NAV stores attachments in the `Document Attachment` table (linked via record IDs) or as links to file shares/SharePoint. IFS uses its Document Management (DocMan) module. Migration requires extracting files, converting them if necessary, and re-uploading via IFS's document API with correct entity linking. Binary content often needs a separate migration workstream. ([docs.ifs.com](https://docs.ifs.com/techdocs/25r2/030_administration/210_cloud_file_storage/migrating_meta/))

### Costing and Inventory Valuation

NAV's costing methods (FIFO, LIFO, Average, Standard, Specific) do not map 1:1 to IFS inventory costing. If you migrate inventory quantities, align the valuation method first — otherwise opening balances will be wrong from day one. Common mapping:
- NAV Standard Cost → IFS Standard Cost (closest match, but recalculate cost rolls in IFS)
- NAV Average Cost → IFS Weighted Average
- NAV FIFO → IFS FIFO (available but implementation differs at the posting level)
- NAV LIFO → No direct IFS equivalent; requires costing method change and revaluation

### Orphaned Records and Loose Relationships

NAV allows loose relationships. IFS requires strict hierarchies. If a NAV Contact is missing an Account association, IFS will reject it. If a Sales Line has no corresponding Sales Header, IFS will reject it. Identify orphaned records during the audit phase and either fix them or exclude them.

## Limitations & Constraints

- **IFS projection availability:** Not all IFS entities have integration-ready projections exposed out of the box. Standard projections are often tightly coupled to specific Aurena pages. For data migration, you may need Entity Service APIs (available from IFS Cloud 24R2+) or custom integration projections. See the Entity Service APIs section above.
- **NAV OData pagination:** NAV returns a maximum page size of 20,000 records per request. For tables with millions of entries, SQL extraction is the only practical path.
- **IFS field length mismatches:** IFS has strict field-length validation. NAV's `Name` field (50 chars standard, often extended to 100) may exceed IFS limits on equivalent fields. Truncate or split during transformation.
- **Historical transaction depth:** Migrating every posted G/L entry from a 15-year NAV installation into IFS is technically possible but rarely advisable. Most organizations migrate opening balances plus 2–3 years of history.
- **NAV dimensions vs. IFS code parts:** NAV's dimensions are highly flexible. IFS uses a fixed set of code parts (A–J). You will likely have to flatten or restructure your NAV dimensions to fit IFS accounting rules.
- **Orphaned record rejection:** Orphaned records in NAV (e.g., a Sales Line with no Sales Header) will be rejected by IFS. Identify these in the audit phase.
- **IFS Excel Add-in compatibility:** The Excel Add-in works reliably with Excel 365. Desktop clients (2016/2019) have known issues with the authentication flow.
- **FNDMIG high-volume mode limitations:** High-volume migration jobs in FNDMIG are insert-only. If you need to update existing records during migration (e.g., enriching a customer record loaded in an earlier phase), you must use standard-mode FNDMIG or the REST API.

## Validation & Testing

Never assume a 200 or 201 response means the data is correct in IFS.

### Record Count Reconciliation

Compare source and target counts for every migrated entity:

```sql
-- NAV side: count active customers
SELECT COUNT(*) FROM [Company$Customer] WHERE [Blocked] = 0
```

Verify against IFS via the REST API or an IFS lobby report. Document expected discrepancies (e.g., "12 blocked customers excluded by design") so validation doesn't stall on known exclusions.

### Field-Level Spot Checks

Sample 5–10% of records per entity and compare field values between NAV and IFS. Prioritize:
- Financial fields (balances, prices, costs)
- Coded fields (payment terms, posting groups, currencies)
- Address data (often corrupted by encoding issues — especially with non-ASCII characters)

### Financial Reconciliation

For G/L migrations, run Trial Balance and Aging reports in both systems for the same cut-off date. They must match to the penny. Any discrepancy must be resolved before go-live. Common sources of discrepancy:
- Rounding differences between SQL Server and Oracle decimal handling
- Currency conversion rate differences
- Dimension/code part mapping errors that route amounts to different accounts

### UAT Process

1. Load data into IFS test environment
2. Have finance users verify chart of accounts and opening balances
3. Have operations users verify item master, BOMs, and routings
4. Execute end-to-end transactions (create order → ship → invoice → post) to verify posting control
5. Run IFS standard reports and compare against NAV equivalents

### Rollback Planning

**FNDMIG rollback:** IFS Data Migration jobs can be reversed within the migration framework. Navigate to the migration job in Solution Manager and use the "Reverse" action, which deletes records created by that job in reverse dependency order.

**API-loaded data rollback:** For data loaded via REST API, maintain a deletion manifest structured as:

```
entity_type, record_id, created_timestamp, batch_id
CustomerInfo, CUST001, 2025-01-15T08:30:00Z, BATCH_042
CustomerInfoAddress, CUST001-DEL, 2025-01-15T08:30:01Z, BATCH_042
```

Write a deletion script that processes the manifest in reverse dependency order (child records before parents) using DELETE requests against the same projections used for creation.

**NAV freeze procedure:** Keep NAV running in read-only mode until IFS validation is complete. Set all NAV users to read-only permission sets, disable job queue entries, and block posting dates. Take a full backup of the IFS database before the final production migration.

**Run at least two full dress rehearsal migrations** in IFS's non-production environment before the real cutover. Time each rehearsal to validate that the cutover window is achievable.

## Post-Migration Tasks

Once data is in IFS, the migration is not over.

**Rebuild automations.** NAV codeunits, report triggers, and job queue entries don't migrate. Rebuild equivalent logic using IFS workflows, scheduled database tasks, IFS Business Process Automation (BPA), or IFS Connect for event-driven integrations. IFS Connect is IFS's native messaging and integration layer — it handles event actions, routing, and transformation for both inbound and outbound messages. If your NAV environment used codeunits to trigger emails, file exports, or API calls on posting events, IFS Connect is the architectural equivalent.

**Reconfigure integrations.** Any third-party system connected to NAV (EDI, shipping, payroll, CRM) must be re-pointed to IFS endpoints. Map each integration:
- NAV SOAP/OData endpoint → equivalent IFS projection or Entity Service API
- NAV XMLport-based file exports → IFS Connect outbound channels or scheduled REST extracts
- Test each integration independently before go-live

**Train users.** IFS's Aurena interface is a significant departure from NAV's Windows client or web client. Budget time for user training, especially for finance and warehouse teams.

**Monitor for data drift.** Watch IFS background jobs and API logs for the first 48 hours. Run daily reconciliation reports for the first 30 days. Check for records that should have migrated but didn't surface in IFS workflows.

**Repoint BI/reporting.** Any reporting connected to the NAV SQL database must be redirected to IFS data sources. IFS Cloud exposes data via OData for reporting tools, and IFS Lobby provides built-in dashboarding.

For a detailed migration checklist, see [The Ultimate ERP Data Migration Checklist (10-Point Plan)](https://clonepartner.com/blog/blog/the-ultimate-erp-data-migration-checklist-10-point-plan/).

## Best Practices

- **Extract via SQL, load via API/FNDMIG.** This is the safest, most performant combination for one-time migrations.
- **Run at least two full test migrations** in IFS's non-production environment before the real cutover.
- **Validate incrementally.** Don't wait until all data is loaded to start checking. Validate each entity type as it's loaded.
- **Scope aggressively.** Blocked customers, cancelled orders, orphaned dimension values, and dead custom tables are dead weight.
- **Document every transformation rule.** When your finance team asks "why does this account balance differ by $0.03?" you need to trace it back to a specific rounding rule in your transformation logic.
- **Freeze NAV modifications** at least 4 weeks before cutover. No new custom reports, no schema changes, no ISV updates.
- **Back up NAV before anything else.** Full SQL Server backup plus a NAV `.navdata` export.
- **Preserve source keys.** Add a legacy NAV key as a custom attribute on every IFS entity to support traceability, deduplication, and rollback.
- **Benchmark throughput early.** Load 1,000 records of your most complex entity in the first week to establish realistic cutover window estimates.
- **Separate historical data from operational data.** Use IFS archive tables or a data warehouse for closed transactions. Reserve live IFS tables for open/active records and recent history.

## When to Use a Managed Migration Service

Building a NAV-to-IFS migration pipeline in-house makes sense if your team has deep expertise in both NAV's SQL schema and IFS's OData/FNDMIG architecture, and if the migration is straightforward — single company, standard entities, limited customization.

For most real-world scenarios — multiple NAV companies, years of C/AL customizations, complex dimension structures, tight cutover windows — the risk-adjusted cost of building internal expertise for a one-time project exceeds the cost of engaging specialists.

Consider external help if:
- No one on the team understands NAV custom tables, C/AL-era service exposure, and posting logic
- Your IFS implementation partner is focused on process design, not legacy data surgery
- You need a weekend cutover or parallel-run delta logic
- The business expects zero tolerance for silent data loss

The hidden costs of DIY ERP migration surface in test cycles, reconciliation meetings, cutover rehearsals, extended parallel-run periods burning dual licensing costs, and the rework after users discover missing data in week two.

> Planning a Dynamics NAV to IFS Cloud migration? Let's scope it. We'll review your NAV environment, map the data complexity, and give you a realistic timeline. Book a technical scoping call with our team.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### Can you migrate directly from Dynamics NAV to IFS Cloud?

No. There is no vendor-provided migration wizard or tool between NAV and IFS. Every migration requires a custom ETL pipeline — extracting data from NAV's SQL Server database, transforming it to match IFS's entity model and validation rules, and loading it through IFS's REST API or Data Migration (FNDMIG) framework.

### What is the best way to extract data from Dynamics NAV for migration?

Direct SQL queries against NAV's SQL Server database are the fastest and most complete extraction method. NAV also supports OData v4 web services, but these must be published per entity and have a default page size limit of 20,000 records. For large datasets like G/L entries or item ledger entries, SQL extraction is significantly faster than OData.

### What is the biggest risk when migrating to IFS?

Ignoring the IFS state machine. You cannot simply insert historical records in a 'Closed' or 'Invoiced' state. They must pass through specific API state transitions or be mapped to dedicated historical archive tables. This is the most common failure point in NAV-to-IFS migrations.

### What happens to NAV custom tables during IFS migration?

NAV custom tables (ID 50000+) have no automatic equivalent in IFS. Each must be individually assessed: map to an existing IFS entity if a functional equivalent exists, create a custom logical unit in IFS (requires development work), or archive the data externally for historical reference.

### Can middleware like Zapier handle a NAV to IFS migration?

Not as the primary migration engine. Middleware is designed for event-driven, low-volume syncing. Zapier's documented support is centered on Business Central, not Dynamics NAV on-prem. Use middleware for light post-migration sync at most — not for bulk historical data loads.
