A helpdesk is not just a list of tickets. It is an operational history: people, organisations, messages, internal notes, attachments, states, queues, custom fields, timestamps, authorship, access restrictions and evidence of what happened.

A migration that imports 10,000 ticket subjects but loses the conversation order, attachment links or original author has not preserved that history. Define completeness before choosing the export tool.

Decide what the new system must achieve

Write down:

  • which support channels remain active;
  • how much history must be searchable and readable;
  • what must remain editable versus archive-only;
  • retention, privacy, legal-hold and deletion obligations;
  • acceptable downtime and maximum ticket/message loss;
  • required audit fidelity;
  • user, customer and organisation identity model;
  • integrations, automations and reporting outcomes; and
  • when the source can be made read-only or retired.

If the target cannot represent a source feature faithfully, choose deliberately among transformation, attachment/reference, read-only legacy access or approved disposal. Do not silently flatten it.

Inventory the source as a set of record classes

Create a migration ledger for:

  • tickets and their stable source IDs/numbers;
  • public replies, inbound/outbound messages and internal notes;
  • message threading and parent/sequence relationships;
  • requester, contact, agent, team and organisation records;
  • status, priority, type, category, queue/group and tags;
  • custom fields and their option values;
  • attachments, inline images and their storage references;
  • time entries, tasks, SLAs and escalation state;
  • knowledge-base content and templates;
  • audit/change history;
  • mailboxes, email aliases and routing rules;
  • web forms, API clients, webhooks and integrations; and
  • permissions, roles, queues and restricted/private content.

Count each class and identify whether it lives in the database, application filesystem, object storage, search index or external service.

Current self-hosted systems illustrate why this matters. Zammad’s backups can include separate database and file archives, and attachments can live in the database, filesystem or S3-compatible storage. osTicket can also place attachments in the database or filesystem. A database dump alone may therefore be incomplete even when every ticket row is present.

Establish privacy and retention before copying

Tickets commonly contain personal information, credentials sent in error, security evidence, contracts, invoices and customer systems data. Migration creates additional copies—in exports, staging, logs and backups.

Define:

  • approved source, staging and target locations;
  • who may access each copy;
  • encryption in transit and at rest;
  • how secrets and sensitive attachments are handled;
  • whether test data must be anonymised;
  • retention for tickets and audit records;
  • legal hold and deletion request handling; and
  • secure disposal of temporary exports after acceptance.

Do not claim that migration itself creates a new retention purpose. Use the organisation’s accountable privacy/legal decision for the relevant jurisdiction and contracts.

Prove the source recovery path

Take a current, application-consistent backup through the platform’s supported process. Include every required component:

  • database;
  • attachment/file/object storage;
  • application configuration and encryption material;
  • version/package/container definitions;
  • custom code, plugins and themes where relevant;
  • mail/API integration configuration without exposing secrets; and
  • the recovery instructions for that exact version.

Verify integrity and restore into an isolated environment where authorised. A backup job saying “success” is not enough. Current Zammad documentation, for example, warns that its restore process is version/context-specific and drops/recreates the target database. Never rehearse against production.

Keep this backup independent of the transformation and target. It is the rollback foundation and the durable source archive if the migration fails.

Design a field and relationship map

For every source record/field, specify:

Source concept Target concept Transformation Required fidelity Reconciliation evidence
Ticket ID/number External-reference field or target number Preserve stable lookup Exact/referenceable Source-to-target map
Public message Article/reply Preserve body, author, time, direction Exact content/order Count plus sampled threads
Internal note Private/internal note Preserve restriction Must remain non-public Permission check
Attachment Target attachment/object Preserve relation, name, size/hash where lawful Readable and linked Count/hash/sample open
Status/queue Target state/group Controlled mapping Business-equivalent Per-value totals

Do not store the only source-to-target key in a temporary log. Persist a controlled mapping so staff can resolve old references and reruns do not create duplicates.

Preserve original authorship and timestamps as historical metadata where the target supports it. If the target cannot impersonate old users safely, use a clearly labelled imported-author field rather than assigning every message to the migration account.

Choose the least lossy migration path

Prefer, in order:

  1. a vendor-supported migration/import path;
  2. supported APIs with documented objects and idempotent lookup;
  3. a controlled intermediate representation mapped to a supported import; or
  4. direct database transformation only with source/target schema ownership, version pinning, specialist review and a disposable rehearsal.

A CSV export is valuable for inventory and simple fields, but usually cannot preserve rich bodies, threading, attachments, permissions and audit events on its own.

Do not write directly into a target production database because its tables look understandable. Applications enforce invariants through code, queues, search indexes, object storage and background jobs that a row insert may bypass.

Build a repeatable trial import

Use a representative authorised dataset covering:

  • old and new tickets;
  • long threads and different message directions;
  • private notes and restricted queues;
  • attachments of allowed types/sizes;
  • custom fields and uncommon statuses;
  • merged, linked, reopened and closed cases;
  • deleted/deactivated users;
  • non-ASCII text and time zones; and
  • integration-created records.

Run the same migration tooling from a clean target more than once during development. Record versions, parameters, logs, rejected records and transformations. A script that only works after manual database edits is not production-ready.

Reconcile content, not just counts

Use several layers:

Structural totals

Compare counts by record class, state, year, queue and attachment backend. Explain every excluded or transformed class.

Relationship integrity

Confirm every message belongs to the correct ticket, every attachment opens from the intended message, every requester/organisation mapping resolves and no source ID maps twice.

Content integrity

Use controlled hashes where appropriate and sample readable bodies, rich formatting, inline images, Unicode and large/old attachments. A matching byte count is not proof that users can access the item through the application.

Security integrity

Verify private notes remain private, queue restrictions hold, disabled users cannot log in, migrated roles do not gain broad access and credentials/tokens were not copied into content or logs.

Operational integrity

Search returns expected tickets after indexing, replies thread correctly, outbound mail uses the right identity, inbound messages create/update the right records, automation does not flood users, and reporting semantics are understood.

Keep an exception ledger with source ID, category, reason, disposition and owner. “99.7% imported” is meaningless if the missing 0.3% contains current escalations or audit evidence.

Control the final delta and cutover

Define one source of truth throughout:

  1. announce the cutover and staff/customer impact;
  2. suppress outbound notifications in the trial/target until intended;
  3. complete and reconcile the bulk import;
  4. freeze source writes or capture a precisely defined delta;
  5. import/reconcile that delta idempotently;
  6. switch inbound mail, web forms, API clients and staff access;
  7. run functional checks; and
  8. keep the source read-only for the approved acceptance period.

Mail routing deserves explicit control. Queued messages, forwarding loops and both systems polling the same mailbox can create lost or duplicate tickets. Record the last source message and first target message and reconcile the boundary.

Rollback is simple only before the target accepts new truth. After new tickets and replies arrive, returning to the source requires a reverse-delta plan. State that point of no return in the cutover record.

Use a read-only archive when full import is the wrong answer

Some old history may be too costly, risky or technically impossible to represent in the new platform. A controlled read-only source can be better than a lossy import if it has:

  • supported, isolated hosting;
  • restricted audited access;
  • reliable lookup from old ticket references;
  • retained attachments and decryption keys;
  • backup and recovery ownership;
  • a defined retention/disposal date; and
  • no live inbound/outbound channels.

Do not keep an unsupported internet-facing helpdesk indefinitely. If the old application cannot be secured, consider a protected static or document archive that preserves the required evidence without preserving the vulnerable application.

Finish with an acceptance record

The owner should receive:

  • source and target versions/configuration scope;
  • backup and recovery evidence;
  • mapping and transformation rules;
  • reconciled totals and exception ledger;
  • security/privacy review;
  • mail/API/integration cutover evidence;
  • staff and customer communication status;
  • rollback/point-of-no-return statement; and
  • source archive or disposal plan.

The migration is complete when staff can follow active work, authorised history is readable and appropriately restricted, inbound/outbound workflows are controlled, exceptions are owned and the organisation can recover the new system—not when an import command reaches 100%.