OpenEMR data migration from another EHR

Migrating into OpenEMR is a scoped extraction, mapping, validation and cutover project whose cost depends mainly on data quality, billing history and the number of source systems. This page explains what the work includes, what drives cost and duration, and what you need to provide.

On this page

What an OpenEMR migration involves

An OpenEMR migration usually starts from one of two situations. The first is moving patient records from another EHR or practice management system into OpenEMR, which means bringing demographics, encounters, documents and billing history across. The second is moving an existing OpenEMR installation to new hosting, such as a different cloud account, a data center or a rebuilt server. The work is different in each case, but both follow the same four stages: extraction, mapping, validation and cutover. Confirm early which situation applies, because it sets the source systems, the data volume and who needs to sign off.

Extraction pulls data out of the source system in a usable form. For a legacy EHR, that may be a vendor export, a database extract or a bulk interface, and the vendor's documentation determines what is included. For an OpenEMR-to-OpenEMR move, the source is the existing database and the document storage directory. Ask the source vendor what each export contains and what it omits, especially attachments, audit history and scanned documents.

Mapping defines how each source field lands in OpenEMR. Patients, insurance, providers, codes and visit types all need a target, and free-text fields often need a rule for where they go. Validation then checks whether the mapped data is complete and correct, using sample patients and reconciliation counts agreed with the clinical and billing leads before the full load. Cutover is the planned switch: a final extract, a freeze on changes in the old system, the load, verification and a go or no-go decision with a rollback path.

What the work includes

The migration covers five data domains and ends with a defined set of deliverables. Scope is agreed in writing before work starts, and the migration is fixed-scope by default.

Patient demographics

Patient identities, contact details, guarantor links, and identifiers from the source system are extracted, mapped to OpenEMR's patient fields, and checked for duplicates before load. Confirm which identifiers must carry over, how merged or inactive records are handled, and which fields OpenEMR has no equivalent for.

Encounters and clinical documents

Visit records, diagnoses, and the scanned or generated clinical documents linked to them are moved with their relationships intact. Document files need a defined storage location and an access check, since a document that loads without its encounter link is hard to find later. Confirm the source system's export formats and any coded data that must keep its code sets.

Scheduling history

Past and future appointments, provider calendars, and appointment categories are mapped to OpenEMR's scheduling model. Decide early whether historical appointments are loaded for reference or only future bookings are carried over, because that choice drives the volume of data and the validation effort.

Billing history

Charges, payments, insurance records, and claims history are extracted as the source system holds them, then mapped to OpenEMR's billing structures. Open balances and claim status need an explicit rule for what is carried forward and what stays in the archive. Confirm this with your billing lead and payer contracts before mapping starts.

Mapping specification

A written specification records each source field, its OpenEMR target, the transformation applied, and the rule for values with no equivalent. It is the reference for every load script and reconciliation check, so it should be approved by the clinical and billing owners before loads are built.

Load scripts and reconciliation reports

Load scripts or import procedures move each domain in a repeatable order, and reconciliation reports compare record counts and sampled values between source and target after each run. Ask for the reports to show exceptions by domain, so that rejected records can be traced to a cause and a decision.

Signed validation record, cutover runbook and rollback plan

The validation record documents who checked each domain and the result, and it is signed by the client's owners. The cutover runbook sets out the steps, owners, and go or no-go checks for the switch, and the rollback plan defines how the client returns to the source system if acceptance fails. Ask for all three to be reviewed together before cutover.

What drives cost and duration

This table lists the main factors that change migration effort, why each one matters for an OpenEMR move from another EHR, and how to keep each one under control.

DriverWhy it mattersHow to keep it down
Number of source systems and export formatsEach legacy system has its own extract logic, code sets and data gaps.Inventory every source early and retire sources that hold no needed data. If OpenEMR is the source, use the FHIR Bulk Data export (NDJSON) for extraction.
Volume and quality of historical dataDuplicate patients, orphaned encounters and free-text values slow mapping and cleaning.Profile the data before scoping and set rules for which records are archived and which are migrated.
Billing history depth and insurance payer mappingOpen balances, claims history and payer identifiers must map to OpenEMR billing structures.Limit history to open balances and recent periods, and confirm the payer list before mapping starts.
Scanned documents and attachmentsImage and PDF volume drives storage, indexing and any OCR or manual indexing effort.Agree a document scope, index only what clinicians need, and confirm the storage plan for the documents directory.
Custom forms and fee schedules to mapEach custom form or fee schedule needs a field-by-field map and clinical or billing sign-off.Freeze the form and fee inventory and retire unused forms before the build starts.
Number of environments and test cyclesEach trial load and reconciliation pass repeats extraction, mapping and validation work.Plan a fixed number of trial loads and ask the vendor to state the test cycle count in the quote.
Interface or FHIR connections to other systemsLive feeds such as labs, imaging or payers add build, testing and monitoring work.List every interface at scope time and decide which ones are migrated, rebuilt or retired.
User count for validation and trainingMore reviewers and trainees extend validation cycles and training sessions.Assign named reviewers per data domain and train users in groups by role.
Compliance evidence neededAssessors may expect migration logs, reconciliation reports and access records as evidence.Define evidence needs with your assessor early and keep reconciliation outputs from each test cycle.

Project phases and outputs

The sequence moves from source inventory and a controlled target build to tested loads, business sign-off and a cutover that leaves the old system archived and recoverable.

  1. Inventory the source system and its data

    We identify the source EHR or OpenEMR instance, its data domains (demographics, encounters, documents, billing history), volumes, custom fields and interfaces, and who owns each domain. The output is a signed source inventory listing every table or export, its owner, known data quality issues and the systems that read from it.

  2. Build the target OpenEMR environment

    We provision OpenEMR 8.x on infrastructure you control with PHP 8.3 or later and a MySQL or MariaDB compatible database, then apply the hardening baseline and access controls. The output is a documented build record with versions, configuration, backup settings and a working non-production instance that the migration team can reach.

  3. Map fields and align code sets

    We map each source field to an OpenEMR destination, document transformation rules, and align coded values such as diagnosis, procedure, medication and payer codes to the terminology OpenEMR uses. The output is an approved mapping specification with a rule for every field, including fields that will be dropped or stored as documents.

  4. Extract and transform the data

    We extract from the source in a repeatable way, apply the mapping rules in scripts under version control, and record every transformation and exception. The output is a versioned transformation package and an exception log that names each record rejected or changed, with the reason.

  5. Run test loads and reconcile results

    We load the transformed data into the target several times, comparing record counts, totals, sampled patient records and document links against the source after each run. The output is a reconciliation report per load showing matched, changed and unresolved records, with each unresolved item assigned to an owner.

  6. Validate with your clinical and billing users

    Your clinicians, front-office staff and billing team check scheduled test cases against the source using agreed scripts, and record accept or reject decisions. The output is a signed acceptance record that lists each scenario tested, the result and any open defects with their agreed resolution.

  7. Cut over, go live and archive the source

    We freeze the source, run the final load, repeat reconciliation, switch users and interfaces to OpenEMR, and keep the source read-only through an agreed hold period. The output is a go-live record with the final reconciliation results, followed by a documented archive of the source data and a closing report.

What to keep in-house and what to outsource

The table lists each OpenEMR data migration workstream with who usually owns it and the skills it needs, so you can see which parts to keep with your staff and which to hand to a partner.

WorkstreamUsually owned bySkills requiredKeep in-house or outsource
Source data accessSource EHR administrator with migration engineer supportSource system database knowledge, export tooling, vendor export rightsSplit: practice confirms access rights, partner runs extraction
Field mappingMigration engineer with practice data stewardOpenEMR schema and data model knowledge, understanding of source field meaningsOutsource the draft, practice approves every mapping
Transformation scriptingMigration engineerScripting, OpenEMR schema knowledge, handling of code sets and date formatsUsually outsource
Billing history reconciliationPractice billing lead with migration engineerBilling and claims knowledge, clinical coding literacy, ledger reconciliationKeep sign-off in-house, partner builds reconciliation reports
Document and attachment migrationMigration engineer with practice records managerFile handling, storage layout in the OpenEMR documents directory, HIPAA-aware handling of PHISplit: partner moves files, practice confirms retention and access
Clinical validationPractice clinicians and clinical staffClinical coding literacy, knowledge of charts and workflows, HIPAA-aware handling of PHIKeep in-house. Clinical sign-off stays with the practice
Cutover executionPartner lead with practice IT and operationsRunbook design, downtime planning, rollback procedures, access to hostingShared: partner runs the runbook, practice approves go-live
Security and access reviewPractice security or compliance lead with partner engineersHIPAA-aware handling of PHI, OpenEMR access control and hardening knowledgeKeep approval in-house, partner prepares evidence and configuration

What usually goes wrong

Most OpenEMR migration problems trace back to a small set of predictable gaps in extraction, matching, reconciliation and cutover. Each card names the failure and the control that prevents it.

Incomplete source exports

The old system often exports fewer records than the practice expects, because archived patients, inactive providers or custom fields sit outside the default report. Ask for a written inventory of every domain being extracted, then reconcile record counts per domain against the source before any load begins. Gaps found at this stage are cheap to close.

Duplicate patients from merged records

Practices that have merged charts or run several registration desks often hold the same person under multiple identifiers, with slightly different names or dates of birth. Agree a patient-matching rule set with the practice before loading, including which identifiers win and how ambiguous matches are routed to a human reviewer. Without it, encounters attach to the wrong chart.

Billing balances that do not reconcile

Open balances, payments, adjustments and insurance claims can drift between the source ledger and OpenEMR after load, which creates patient statements that are wrong. Reconcile patient balances and totals per account, and freeze the billing period used for the cutover so the comparison is against a fixed snapshot. Confirm who signs off the variance report.

Lost links between documents and encounters

Scanned notes, lab reports and referral letters can load as orphaned files that no longer sit under the encounter they belonged to. Map each document to its source encounter identifier, then sample records in both systems to confirm the link resolves. Broken links are easy to miss because the file still opens.

Code set and payer mismatches

Diagnosis and procedure codes, medication coding and payer identifiers rarely map one to one between EHRs, so claims and problem lists can load with values that do not match what OpenEMR expects. Build a crosswalk for each code set in use, list unmapped values for clinical review, and confirm payer records against current payer setup before billing resumes.

Unplanned scanned document volume

Legacy practices often hold far more scanned material than anyone counted, and bulk upload can strain storage, indexing and migration windows. Inventory the document store early, estimate size from that inventory, and decide which historical documents migrate and which stay in archive. Confirm storage capacity with your infrastructure team before scheduling loads.

PHI copied into test environments or email

Test loads and reconciliation spreadsheets are often built from production extracts and then shared by email or copied to laptops, which exposes protected health information outside controlled systems. Use masked or synthetic test data for build and rehearsal, restrict extract locations, and set rules for how reconciliation reports are transferred and deleted.

Cutover without a tested rollback

Teams sometimes rehearse the load but never rehearse reverting to the source system, so a failed go-live leaves staff with no working record. Schedule a timed freeze on the source system during final extraction, run at least one full rehearsal, and document the rollback steps and decision owner before go-live. Confirm the rollback window with clinical leads.

How the work changes by starting point

Extraction usually depends on what the source vendor will release, so the first task is confirming the export formats and data sets you can get before mapping begins.

  • Export scope: Ask whether the vendor provides clinical, scheduling, billing and document exports, and at what cut-off date.
  • Bulk FHIR access: If the vendor exposes FHIR Bulk Data, confirm which resource types are covered and whether they match your mapping plan.
  • Validation: Reconcile vendor-supplied counts against source reports, since vendor exports may omit or transform fields.
  • Cutover: Confirm the vendor's access window after termination and whether a final delta extract is available.
  • Confirm with the vendor: Contract terms on data return, export fees and how long data stays available after account closure.

What you need to provide

Before migration work starts, the client supplies the inputs that determine whether the mapping can be built correctly. The core items are read access or full exports from the source EHR, a data dictionary or schema documentation that explains how the source stores demographics, encounters, orders and billing, and sample records for each data type, including documents and billing history. Without the schema, mapping is guesswork, and without samples, validation cannot show whether real records survive the move. Ask the source vendor or internal administrators which export formats are available and whether the export is complete or limited to certain record types.

Two named owners are required for decisions that cannot be delegated to the migration team. A clinical owner approves how diagnoses, medications, allergies, encounter types and clinical notes map into OpenEMR's structures. A billing owner approves how payers, fee schedules, claims history and open balances are reconciled, since billing errors surface after cutover and are costly to unwind. Both should be available for mapping reviews and reconciliation sign-off, not only at the start.

The client also provides the target environment. Confirm the hosting location, the PHP version (recent OpenEMR releases require PHP 8.3 or later), and the MySQL- or MariaDB-compatible database version and configuration. Provide a test environment isolated from production so that repeated load and validation runs never touch live patient data. Decide early how historical scanned documents and attachments will be stored, including whether files live on the server's drive, in object storage, or in another document system, and whether they will be encrypted at rest. This decision affects storage sizing and the document directory's access controls.

Finally, name the sign-off owners for cutover and the recipient of the final migration record. Cutover approval should be given in writing by the clinical and billing owners, together with the IT owner responsible for the target system. The final migration record, which lists source extracts, mapping decisions, validation results, reconciliation totals and known exceptions, should go to the client's compliance or privacy lead and to whoever will maintain the system after go-live. Agree on these names and the recipients in the written scope, before extraction begins.

Frequently asked questions

What drives the cost of an OpenEMR migration and can it be quoted fixed-scope?

Yes, most engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. OpenEMR has no license fee and no paid edition, so the cost is services plus the infrastructure you run. The main drivers are the source system's export options, the number of data domains moving (demographics, encounters, documents, billing), the depth of billing history, how much custom mapping is needed and how many validation rounds your clinical and billing staff will run. Ask the quote to list each data domain, the access method for the source system, test cycles, cutover support and any assumptions it depends on.

How long does moving patient data from another EHR into OpenEMR take?

The timeline depends on the source system's export options, data volume, mapping complexity and the number of validation rounds clinical and billing staff need to sign off. DeployOpen does not publish durations. The timeline is set in the written scope after discovery, when the source data has been profiled. Ask for a phase plan that shows dependencies, the sign-off points for clinical and billing owners, the test cycles and the cutover window, and ask which of these depend on the source vendor's cooperation.

Can our own IT team migrate to OpenEMR without an implementation partner?

Yes, if your team has engineers comfortable with PHP, MySQL or MariaDB, healthcare data formats and the source system's export tools. OpenEMR's FHIR API implements Bulk Data export in NDJSON, which can help with extraction, but you must confirm that the resource types you need are available from your source. Clinical and billing sign-off is required either way. Partners add the most value in discovery, mapping rules, validation scripts and cutover runbooks, so compare those tasks with your team's capacity before deciding.

What must our organization supply before a migration project starts?

Expect to provide access to the source system, either an export, database read access or a supported API, along with its data dictionary and sample extracts. You will also need code sets for diagnoses, procedures and payers, provider and location lists, and named clinical and billing owners who can approve mappings. The target OpenEMR host must run PHP 8.3 or later on a MySQL- or MariaDB-compatible database, and you need a test environment and a cutover window agreed in advance. Confirm each item with your own systems owners before the scope is written.

How is billing history handled when moving from another EHR to OpenEMR?

Billing history moves as financial records tied to patients, encounters and payers, so it is mapped and reconciled rather than loaded as-is. Decide with finance how many years to migrate, which claim statuses to include, and how open balances, payments and adjustments are represented. Validation compares totals and aging per patient and payer against reports from the source system. Some organizations keep read-only archived reports for older history. Confirm which billing and fee sheet records your OpenEMR version can load before the mapping is agreed.

How is patient data protected during extraction and testing?

Extracts stay inside infrastructure you control, and access is limited to named people and documented in the scope. Use HTTPS only, restrict who can reach extract files, and encrypt stored copies. Follow the hardening guidance in the Securing OpenEMR guide, including removing setup scripts after installation and blocking direct web access to the documents directory. Where clinical validation allows, test with de-identified or minimized datasets, and delete working copies at the end of each cycle. Confirm the required controls and retention rules with your privacy and security officers.

How DeployOpen delivers OpenEMR migrations

DeployOpen plans, builds and hands over OpenEMR data migrations inside infrastructure you control, from extraction on the source system through validation and cutover. Each engagement is fixed-scope, with the scope agreed in writing before the work starts.

How we scope

  • Written scope lists which source data types move, such as demographics, encounters, documents and billing history.
  • Source system inventory records the export formats, data volumes and known data quality issues you can provide.
  • Scope names the OpenEMR version, PHP and database targets and the hosting model, such as Docker or a server you manage.
  • Scope states who owns clinical data decisions, sign-off on mapping rules and the acceptance criteria for cutover.

How we build

  • Field-level mapping documents each source field to its OpenEMR destination, with rules for codes, dates and duplicates.
  • Extraction and load scripts run first against copies of the source data, so mapping gaps surface before production.
  • Validation checks compare record counts, sampled patient charts and billing totals between source and target after each run.
  • Where the source system offers bulk export, OpenEMR's FHIR Bulk Data v1.0 export at system, patient and group level in NDJSON format can inform the extraction design. Confirm feasibility with your source vendor.

How we hand over

  • Delivered documentation covers the mapping specification, load procedures, validation results and known exceptions.
  • Cutover runbook sets out the freeze window, rollback steps and the order of operations agreed with your team.
  • Post-migration reconciliation report records what moved, what was excluded and who approved each exception.
  • Knowledge transfer sessions train your administrators to rerun validation and maintain the target environment.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers after cutover.
  • Post-cutover support can cover issues found in production data that validation did not catch, under the written scope.
  • Retainers can include applying OpenEMR security releases and planning version upgrades, so the system stays current.
  • Confirm with us which support responsibilities sit with DeployOpen, your staff and any third-party support vendor you choose.

Sources and further reading

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.