ERP data migration checklist

Use this checklist to decide what to move from a legacy ERP or accounting system into Odoo or ERPNext, in what order, and how to prove the balances reconcile before cutover.

On this page

How to use this ERP data migration checklist

A legacy ERP or accounting system is being retired, and the team has to decide what moves into Odoo or ERPNext, what stays behind as an archive, and how every opening balance will be proven before users rely on the new system. This checklist is built for that decision. It groups the work into functional, security, integration, operational and compliance requirements, and each item carries a verification method: a reconciliation report, a sample record review, a restore test, a role-permission walkthrough or a signed sign-off. Treat it as a scoping tool. It shows what to ask, who must answer and how the answer will be checked, but it does not guarantee a clean cutover, because the result depends on data quality in the source system, the chart of accounts design and how much history the business actually needs.

Use the items in order. Start by agreeing which master data, open items and balances are in scope, then confirm the verification method for each one before any file is prepared. Record who owns each control, whether that is finance for balances, IT for access and encryption of the migration environment, or operations for stock and open orders. Where a requirement comes from a regulation, such as record retention or access controls under the FTC Safeguards Rule at 16 CFR 314.4 for covered financial institutions, name the control owner and the evidence that will be kept, and confirm the interpretation with your own compliance or legal advisers. DeployOpen plans, implements, tests and documents these controls in your environment, and prepares evidence for compliance assessments, but it does not issue audit reports, attestations or certifications. Independent auditors and certification bodies make those determinations.

Which data to migrate and which to archive

This table compares each data type in a legacy ERP or accounting system against the decision to migrate it, archive it, or rebuild it, and how to verify the result. Read each row as a sign-off point: the verification column names the evidence to request before cutover. The main takeaway is that balances and open items must tie to the legacy system, while most closed history can stay in a read-only archive.

Data typeMigrate or archiveWhy it mattersHow to verify
CustomersMigrate active and open-balance recordsReceivables, credit terms and tax status depend on clean customer identity and duplicates break reportingCount and duplicate check against the legacy customer list, plus a sample of ten customers with terms compared field by field
VendorsMigrate active records and those with open payablesPayment runs and 1099 or equivalent tax reporting depend on correct vendor tax IDs and bank detailsTie open payables by vendor to the legacy aged payables report; confirm bank detail changes were approved
Products and itemsMigrate active items, units of measure and costing methodStock valuation and pricing rules fail when units or cost methods differ between systemsCompare item master extract to the legacy item list; test one item's on-hand value after load
Chart of accountsMigrate as mapped target structure, not a copyEvery balance and report line depends on the account mapping, and legacy accounts often carry obsolete codesSigned mapping table approved by the controller; legacy-to-target account totals compared before and after load
Tax codes and ratesRebuild in target, validated against filing historyTax rules are the most common source of misstated returns after migrationRe-run a sample of prior-period invoices through new tax setup and compare tax totals to filed returns
Currencies and exchange ratesMigrate currency setup and only the rates needed for open itemsForeign currency open items revalue incorrectly if the rate basis differsRevalued open items in target compared to the legacy revaluation report at the same date
Open items (AR, AP, inventory on hand)Migrate in full as balances with source document referencesThese drive collections, payments and audit testing, and they must tie to the closing positionSample tie-out of open invoices by document number, amount and due date to the legacy aged reports
Opening balancesLoad as a single balanced opening entry per entity and periodErrors here flow into every later period and are hard to isolate after go-liveTrial balance in target matches legacy trial balance at the cutover date for each entity, with differences explained
Transaction historyArchive closed periods as read-only; migrate only what reporting needsFull history increases load risk and cost, and it rarely changes operations once periods are closedConfirm the archive is searchable, retention periods are set, and archived totals agree to legacy period totals

In what order to load master data, balances and history

The sequence loads the structure the ledger depends on first, then the records that point to it, then balances and open items, and only then any archived history. Each stage ends with a trial load and a check before the next one starts, so errors surface where they are cheap to fix.

  1. Fix the chart of accounts and dimensions

    Map every legacy account to a target account in Odoo or ERPNext, then define the company, fiscal years, currencies, cost centers or analytic dimensions, and tax accounts that the rest of the data will reference. Finance owns the mapping and signs off each legacy-to-target line, while the implementation partner builds the structure in a non-production environment. Done means every legacy account has one target account, every balance-bearing account is accounted for, and a trial import of the structure completes without rejected rows.

  2. Load master data in dependency order

    Load the records that other records link to, in the order they depend on each other: units of measure, tax templates, payment terms, customers, suppliers, items, bank accounts, and employees or users where they carry finance roles. Odoo and ERPNext both let you import child records and linked documents, but a row that references a missing parent is rejected, so parents must exist first. Done means each master data file imports cleanly in a trial load and a sample of records opens with the expected links.

  3. Size batches to the import tool

    Split each file into batches before the first trial load. The ERPNext Data Import documentation advises importing only a few thousand records at a time, so large customer or item files are split into several runs with a log kept for each. Test the batch size on a copy of the real data, time each run, and record the error file produced for every batch. Done means the batch plan for every file is written down and the rerun procedure for failed rows has been tested.

  4. Load opening balances and open items

    Enter opening balances as a single balanced opening entry per company and fiscal year start, then load open invoices, open purchase invoices, unpaid payments and partially allocated items so that subledgers agree with the general ledger. Load these only after customers, suppliers and accounts exist, because each open item points to them. Done means total debits equal total credits, receivables and payables reconcile to their subledger reports, and the open item count matches the legacy aging report.

  5. Decide which history to archive

    Separate the history that must be queryable in the new system from the history that only needs to be retained. Transactions needed for current-year reporting, open tax periods and audit trail continuity usually stay in the ERP, while older records can move to a read-only archive. The retention rules for your sector and jurisdiction decide the split, so confirm them with your compliance and tax advisers rather than assuming a period. Done means each legacy data set has a recorded decision and an owner.

  6. Load migrated history where the decision requires it

    For the transaction history you chose to keep, load it after balances are proven, in the same batched way, and link it to the opening balance so reports do not double count. Keep the legacy system readable until the archive is verified. Done means historical totals by period match the legacy reports for the sampled periods and the archive can be searched by the people who need it.

  7. Run full trial loads and reconcile before sign-off

    Repeat the full sequence on a fresh copy at least once more, so the final run is a rehearsal of the cutover and not a first attempt. Reconcile trial results against the legacy trial balance, subledgers, bank statements and open item listings, then record each difference and its cause. Finance and the implementation partner sign the reconciliation together, and the signed record becomes evidence for auditors. Done means the last trial run reconciles with no unexplained difference.

Import tooling and batch sizes in Odoo and ERPNext

Each ERP has its own import path, and the path you choose sets the batch sizes, the order of loads and how much custom code the team must maintain. The cards below compare the built-in import tools, the external ID approach in Odoo, scripted loads and the Server Script restrictions that apply to ERPNext versions 15 and later.

ERPNext Data Import tool

The Data Import tool loads and updates records from CSV or Excel files or public Google Sheets, using downloadable templates that match each doctype. It supports child table rows, so a sales order or journal entry can arrive with its lines in one file. Because the documentation advises importing only a few thousand records at a time, plan master data, open items and balances as separate, sized batches. Confirm the template columns against your ERPNext version before the trial load, since templates change between releases.

Odoo spreadsheet import with external IDs

Odoo imports records from spreadsheets, and relations such as a product's category or a contact's country are resolved through external IDs. Load parent records first, assign each one a stable external ID from the legacy system, then reference that ID in child files. This keeps reruns idempotent, so a corrected file updates existing rows instead of creating duplicates. Confirm in your Odoo version how the import handles many2many fields and whether it can update existing records.

Scripted loads by the implementation team

For large histories, transformation rules or logic that the standard templates cannot express, the implementation team writes scripts that call the ERP's API or use its ORM. Scripts give repeatable, reviewable runs with logging and reconciliation hooks built in. They also become code that must survive upgrades and be documented for auditors. Agree in the statement of work who owns the scripts after cutover, where they are stored, and how each run is approved and recorded.

Server Scripts disabled by default

In ERPNext, Server Scripts run Python on document events or as API endpoints, and from version 15 they are disabled by default. They must be enabled with the server_script_enabled setting, and Frappe Cloud public shared benches do not allow them at all. If your load depends on a Server Script, you need a self-hosted or dedicated bench where the setting can be changed under change control. Confirm this setting and your hosting tier before the design is final, not during the cutover weekend.

Trial loads and batch logs

Each trial load should run the full batch sequence against a copy of production, with a log that records the source file, row counts, rejected rows and the reason for each rejection. Repeat trial loads until the rejection rate is low enough that the remaining errors can be fixed by hand, and record that decision with the data owner. Ask the partner how logs are retained, since they are part of the evidence for the reconciliation sign-off.

How trial loads and reconciliation sign-off work

The dress rehearsal tests the mechanics before any real migration data is trusted. The team runs the full sequence of extracts, transforms and imports against a copy of the target environment, so that import errors, mapping gaps and missing master data surface while they are cheap to fix. Nothing from this run is considered migrated. In Odoo, the on-premise documentation describes database duplication with neutralization for test copies, which keeps a scratch database from sending emails, posting to live bank feeds or calling external services. In ERPNext, the environment can be built with Docker Compose using the production images from frappe_docker, or with the bench command line tool, so the rehearsal runs on the same versions planned for go-live.

  • Import order: Confirm that master data loads before transactions, and that each import file depends only on data already present.
  • Error log: Record every rejected row, its cause and the fix, so the same error does not return in the trial load.
  • Runtime: Measure how long each batch takes so the cutover plan rests on observed figures, not estimates.
  • Neutralized copy: Confirm that outbound email, payment connectors and integrations are disabled in the test copy.
  • Version match: Check that the rehearsal environment runs the exact release and add-ons planned for production.

Before leaving this stage, ask the implementation partner to show the rehearsal log and the list of fixes made to mappings and source files.

Security controls for data in transit and during the load

Migration extracts often contain customer names, bank details, tax IDs and employee records, so they fall under the same safeguards as production data. The cards below cover the controls a migration team should be able to show during a load, and each is tied to the FTC Safeguards Rule elements in 16 CFR 314.4 for covered financial institutions. Confirm with counsel or your compliance lead whether your organization is covered before you map these controls to your program.

Encrypt extracts in transit

Every transfer of legacy extracts from the source system to the staging area and into Odoo or ERPNext should cross an encrypted channel, especially where the path leaves your internal network. Ask the migration partner to document the protocol, the host keys or certificates used, and who can read the transfer logs. The FTC Safeguards Rule element on encrypting customer information in transit over external networks is the reference point here. Confirm whether your load crosses any external network, including vendor-managed staging.

Encrypt staging data at rest

Staging databases, CSV and Excel files, and backups of the load environment hold the same data as the source ledger, so they need encryption at rest and a defined retention period. Check where extracts are stored between the trial loads and the cutover, and who holds the keys. The Safeguards Rule requires encryption of customer information at rest, so a file share that is only access controlled does not meet that element on its own.

Limit access to extracts and staging

Apply least privilege to the extract folders, the staging database and the Data Import tool, and remove access once each load wave ends. Named accounts should replace shared logins, and the migration team should not hold production admin rights unless the cutover plan requires it. Review the access list before each trial load, because contractors and short-term analysts often keep access after their task closes.

Multi-factor authentication for data access

Anyone who can open an extract, log in to the staging environment or run an import against production should authenticate with multi-factor authentication. The Safeguards Rule requires this for any individual accessing any information system, which includes vendor consultants and service accounts used by a partner's tooling. Ask for a list of every account that touches production data, and confirm how each one is protected. Where an account cannot support a second factor, document the exception and the compensating control.

Log all load activity

Record who ran each import, which file and template were used, the record counts loaded and rejected, and any manual edits made to records during the load. These logs support the Safeguards Rule element on logging the activity of authorized users, and they also give the reconciliation team an audit trail for opening balances. Confirm where the logs are stored, how long they are kept, and whether they can be exported without the migration tool's administrator.

Change control for load scripts

Custom transformation scripts, mapping files and Server Scripts used during the load are changes to the system, so they should go through the same change management steps as production code. Record the version of each script, who approved it, and which trial load tested it. Frappe disables Server Scripts by default from version 15, so confirm whether the migration depends on enabling them and who signs off that setting. The Safeguards Rule requires change management procedures for this work.

Remove test copies with personal data

Trial loads often leave copies of production data in test sites, sandboxes and developer laptops, and those copies frequently carry personal information. Set a removal date for each copy, delete extracts from shared drives once the cutover is signed off, and use neutralized or masked data where the test does not need real identities. Odoo documents database duplication with neutralization for test copies, which is a useful pattern to confirm with your partner.

Operational requirements for the cutover and first close

This table lists the operational requirements that should be written into scope before a legacy ledger moves to Odoo or ERPNext, with a verification method for each. Use it to test whether a partner's cutover plan can be evidenced, not just described. The main takeaway is that every requirement should end in a signed or rehearsed artifact that finance and IT can both inspect.

RequirementWhat it asks forHow to verify it
Named cutover ownerOne accountable person with authority over go or no-go decisions, data loads and finance sign-offWritten RACI in the scope document naming the person, their deputy and the decision rights
Rehearsal calendar in scopeDress rehearsals on copies of production data, each with timed steps and recorded issuesRehearsal plan attached to the contract, with a log of each run and the defects closed before the next run
Rollback planA tested path back to the legacy system or a pre-cutover database snapshot if the go-live failsA rehearsed rollback during a trial run, timed and signed off by the cutover owner
Freeze window agreed with financeAgreed cut-off for postings in the legacy ledger, with a defined period end and a rule for late entriesSigned freeze notice from the controller, plus a test confirming no postings after the cut-off timestamp
Parallel reporting for the first periodLegacy and new ledgers run side by side for the first close, with balances compared at agreed reportsReconciliation pack showing trial balance, open items and subledger totals matched or explained, signed by finance
Archived legacy accessRead-only access to the legacy system and an archive of history not migrated, retained under the records policyTest log showing named users can open archived records, plus confirmation of the retention rule applied to each record type
Support path after go-liveNamed escalation contacts, a defined issue severity process and a hypercare arrangement written into the contractSupport runbook and a dry run of one reported defect through the escalation path before cutover
Access and role checks at go-liveProduction user roles, approval rules and segregation of duties tested before users log inRole matrix reviewed by finance and IT, with test evidence that users cannot approve their own entries

What buyers ask before hiring migration help

What makes an ERP data migration take longer or cost more?

The biggest drivers are the state of the legacy data, the number of legal entities and charts of accounts being merged, how many years of history must be loaded, and how much custom logic sits in the old system. Duplicate customers, inconsistent item codes and unreconciled bank balances each add cleanup and review cycles before any load runs. Each entity adds its own mapping, validation and reconciliation pass. Ask any partner to break the estimate into these drivers in writing, and to state which assumptions about data quality they have made. Fixed-scope agreements should list the entity count, the history depth and the number of trial loads included.

Can our internal finance and IT team run the migration without a partner?

A capable internal team can run a migration if it has someone who has loaded data into the target system before, a clear owner for each master data object, and time to repeat trial loads. Most teams struggle with the reconciliation stage, not the import itself. Internal staff must supply the legacy extracts, a signed-off chart of accounts mapping, open item listings with aging, bank statement cut-off balances, and decisions on what to archive. They also need a test environment that mirrors production. Ask a partner to list which of these items they expect from your staff and which they will produce, so the split of work is explicit before the project starts.

How much time do finance and IT need to commit during migration?

Finance is needed most for mapping accounts, confirming opening balances, reviewing reconciliation differences and signing off each trial load. IT is needed for extracts from the legacy system, environment setup, access to the target database, scheduled batch runs and cutover steps. The commitment peaks during trial loads and the final cutover window, so ask for a calendar of named reviewers and approval points. Reviewers should be identified before the first load, because delays in sign-off usually extend the schedule more than technical failures do. A written plan should state who approves each reconciliation and what happens when a difference cannot be explained.

Should we migrate all historical transactions or archive older data?

Migrate balances, open items and the data needed to run the business from day one, and archive closed history that is only needed for reference or retention. Loading full history into an ERP increases trial load volume, slows reconciliation and adds error cases, and it rarely improves day-to-day operations. Archived data should remain retrievable for auditors and tax reviews, so decide the retention period with your compliance and legal owners first. For example, a company might load one prior fiscal year of detailed transactions and keep older ledgers in a read-only archive (illustrative). Put the retention rule in writing before scoping the load.

How do we choose between Odoo and ERPNext migration tooling?

Choose based on the target platform's import capabilities, the data volumes you need to load, and the team who will maintain the import process after go-live. ERPNext documents a Data Import tool that works from CSV or Excel files and supports child table rows, and its documentation advises importing only a few thousand records at a time, which makes batch planning essential. Odoo's import features and its module set differ, so confirm the specific import paths, file formats and batch limits for your chosen version with the vendor or your partner. Whichever platform you choose, ask how custom import scripts will be kept upgradable and who will own them.

What should a fixed-scope data migration quote include?

A fixed-scope quote should name the source systems, the entities and currencies in scope, each data object to migrate (master data, open items, balances, selected history), and the data objects excluded and why. It should list the number of trial loads, the reconciliation reports produced, the sign-off points, and the cutover steps covered. It should also state which items the client must supply, the assumptions about data quality, the change process if the scope shifts, and what post-cutover support is included. Request a written statement of exclusions, such as custom report rebuilds or data cleansing performed by your staff. DeployOpen agrees scope, deliverables and timelines in writing before work starts, so ask any provider for the same level of detail.

What data quality problems should we fix before the first trial load?

Fix problems that break mapping or reconciliation: duplicate customers and vendors, missing tax identifiers, inconsistent item units, orphaned invoices and bank balances that do not match statements. Cleansing in the legacy system is usually cheaper than cleansing during import, because the source owner understands the business rules. Set a rule for how unresolved records are handled, such as moving them to a suspense account or excluding them with a documented approval. Ask the partner to run a data profiling pass on the extracts and report the defect counts by object, so cleanup effort is visible before the migration plan is fixed.

What a migration scope should contain before work starts

A written migration scope names every source system and extract before any data moves. For each legacy ERP or accounting system, list the database or export format, the period covered, the entities and currencies included, and who at the client owns the extract. Attach a mapping document for each object (customers, vendors, items, chart of accounts, open invoices, bank balances) that shows the source field, the target field in Odoo or ERPNext, the transformation rule, and the default value used when the source is blank. The scope also fixes the load order: chart of accounts and fiscal years first, then master data, then opening balances and open items, then any transactions the client has agreed to bring across. Confirm with your implementation partner whether the load order is written as a runbook with a named owner for each step.

The scope must state reconciliation criteria in measurable terms before the first trial load. Define which totals must match between the legacy system and the target at each cutover point, such as customer and supplier balances by account, inventory valuation by warehouse, and bank balances by account at the cutover date. Name the sign-off roles: the finance controller who approves balances, the data owner for each master data object, the application owner who approves configuration, and the person who accepts the cutover on behalf of the business. Also list what is out of scope. Historical transactions older than an agreed cutoff, attachments, and archived reports are often moved to a read-only archive rather than imported, and that decision belongs in the written scope with the retention owner named, so that nobody discovers the gap during the cutover weekend.

Most DeployOpen engagements are fixed-scope, so the scope document is the basis for the written agreement, and the quote follows from it. Ask the partner to show how each deliverable in the scope maps to a trial load, a reconciliation report and a sign-off record, because those items drive the effort. Ask what happens when the source data is poorer than expected: who decides whether a record is cleansed, excluded or loaded with a flag, and how a change to scope after work starts is priced and approved. Confirm the batch approach with the partner before pricing, since the ERPNext documentation advises importing only a few thousand records at a time through the Data Import tool.

How DeployOpen scopes, delivers and supports an ERP migration

DeployOpen treats the ERP data migration checklist as a written, fixed-scope workstream inside your own infrastructure, covering master data, open items, balances and cutover. Each stage ends with documented evidence that finance and IT can review and sign off before the next one starts.

How we scope

  • Inventory the legacy ERP or accounting system, its tables, extracts and reports, and the owner of each data set
  • Agree in writing which master data, open items, balances and history move, and which are archived
  • Set the target edition, hosting location and import tooling, with batch sizes and trial load count stated in the scope document

How we build

  • Map legacy fields and chart of accounts to Odoo or ERPNext targets, with transformation rules recorded per field
  • Run repeated trial loads into a non-production copy and log every rejected record with its reason and fix
  • Produce reconciliation reports for balances, open receivables and payables that finance can check line by line

How we hand over

  • Deliver a cutover runbook with a step-by-step weekend sequence, owners, rollback points and go or no-go criteria
  • Provide signed-off reconciliation packs, load logs and mapping documentation as the migration evidence file
  • Walk your finance and IT teams through the archive location and how to retrieve historical records afterwards

How we support

  • Support post-cutover correction of data exceptions during the period agreed in the written scope
  • Offer ongoing support, upgrades and testing as a retainer once the new system is live
  • Confirm with your auditors which migration controls and records they expect to see before cutover is scheduled

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.