Loyalty Program Migration Without Losing Member Balances
Move loyalty platforms without corrupting balances. Map economic rules, reconcile every member, force timing failures, prove replay, then cut over.
The short version: A loyalty program migration is a ledger transfer, not a software import. Preserve each rule’s economic meaning, reconcile every member, force timing defects with deterministic fixtures, then cut over only after rollback passes explicit ledger and transaction gates.
Key takeaways
- Treat points, rewards, expiries, and pending transactions as financial records.
- Accept zero unexplained member-level variance, not merely matching totals.
- Separate elapsed parallel operation from forced tests for duplicates, reversals, expiry, and event order.
- Size cutover and rollback tests from measured production volume.
- Keep one writable ledger until every cutover gate passes.
Platform selection ends when the contract is signed. Migration control starts there. Turn the requirements defined during Loyalty Program Software: Buy for Requirements, Not Features into migration acceptance criteria rather than leaving them in procurement paperwork.
Map economic rules before moving records
Start with the source ledger. Map member_id, balance type, account status, expiry date, tier, pending points, adjustments, reversals, reward reservations, and transaction history. For each field, record whether it transfers directly, transforms, or has no target destination.

A matching field name does not prove matching behavior. One platform may expire points transaction by transaction; another may expire the full balance after inactivity. Both can expose expiry_date while granting different member value.
Flag every change in economic meaning. Examples include rounding 99.6 points to 100, combining balance buckets, dropping pending points, or replacing rolling tier qualification with calendar-year qualification. Product, finance, and support must approve each change with the affected member count and liability amount.
Set history depth from the longest refund, dispute, expiry, settlement, accounting, and service window. If refunds remain possible for 90 days, importing 30 days of transactions cannot explain every valid reversal. Those figures are a policy example; use the longest applicable window in your operation.
Configuration-first failure: the team accepts the target platform’s defaults, then forces source records into them. The import completes while expiry, tier, or redemption rights change quietly.
Reconcile every member, not just aggregate liability
Run deterministic reconciliation outside both platforms. Compare member counts, account states, positive and negative balances, pending balances, reward counts, tier counts, expiry dates, and aggregate point liability. SQL or a spreadsheet should perform arithmetic, duplicate detection, and referential-integrity checks; people should review only explained exceptions.

Totals cannot detect offsetting errors. Two members can be wrong by 5,000 points in opposite directions while aggregate liability still matches. Calculate a delta for every member and every balance bucket, then produce an exception file containing member_id, source value, target value, delta, reason code, owner, and approval status.
Compare distributions as a second control. Count members at zero, below zero, near redemption thresholds, and in high-balance bands. Derive boundaries from source percentiles or configured reward thresholds; bands such as 0, 1–999, and 1,000+ are illustrative, not universal cut-offs.
Accept zero unexplained variance. Numerical differences may remain for approved test-account removal or legally expired balances, but each needs a member list, reason, owner, and liability amount. Report both denominators: affected members divided by imported members, plus affected liability divided by imported liability.
A statement such as “99.9% matched” is incomplete. Ten failures among 10,000 members may include low-value test accounts or the program’s largest balances. The member and liability denominators distinguish those outcomes.
Completion-message failure: a vendor reports that the import job succeeded, so the team skips independent reconciliation. Job completion proves records were processed; it does not prove member rights survived.
Force defects instead of waiting for them
Parallel operation and fixture testing answer different questions. Run both platforms for one complete transaction cycle — 7 to 30 days for most order-to-settlement timings — to observe ordinary production timing. This range is an operating heuristic; derive the final duration from your longest settlement, refund, batch, expiry, and reversal latency.

Elapsed time will not reliably produce rare conditions. Webhooks, batch settlement, and retries can deliver events out of order, but a quiet test period may contain no duplicate or boundary event. Inject those cases deliberately.
Create a fixture catalog with the source event, initial ledger state, expected ledger rows, expected final balance, and expected member status. Include at least these six baseline scenarios: ordinary earn, duplicate earn delivery, refund after redemption, reversal after tier crossing, expiry during a pending transaction, and purchase across the program’s date boundary. Six is the stated baseline because each represents a distinct mechanism discussed here; add one fixture for every custom earning, redemption, expiry, and tier rule configured in your program.
For the duplicate fixture, send one original event plus one duplicate and one retry using the same immutable event ID. The expected result is one posting, two rejected or ignored deliveries, and one final balance movement. For out-of-order testing, send a reversal before its original transaction, then verify the documented pending or rejection behavior before replaying the original.
Record coverage counts: configured rule paths, fixture-covered paths, fixtures run, fixtures passed, and unexplained output differences. Pass only when every configured rule path has a fixture, every fixture matches its expected ledger rows and final state, and all differences are explained and approved.
Happy-path failure: the team observes ordinary earns for three days and sees matching totals. Duplicate handling, month-end processing, scheduled expiry, and reversals remain untested because none happened naturally.
Cut over only after rollback passes measurable gates
Write the cutover runbook before rehearsal. Name the final export time, write-freeze start, validation gates, routing change, go/no-go owner, rollback triggers, recovery steps, and support owner. Use named people rather than departments.

Stop balance-changing writes during the final transfer or queue them with immutable event IDs. Size the freeze from measured export, import, reconciliation, and routing durations, then add contingency based on rehearsal results. An arbitrary two-hour window has no operational basis.
Build the rollback rehearsal from production telemetry: peak events per minute, largest observed queue, active member count, ledger size, and measured export/import duration. Use at least the observed peak rate and queue depth; if the test environment cannot sustain them, document that capacity gap rather than calling the rehearsal production-shaped.
Rollback passes only when source routing is restored, each queued event ID posts once, member-level reconciliation shows zero unexplained delta, and test members complete one earn and one redemption successfully. Also verify authentication, reward reservation, and support lookup. State the last safe reversal point because rollback becomes harder once target-only transactions accumulate.
Tell members what remains unchanged before describing new features: balance, rewards, tier, access, and downtime. After cutover, show the transferred balance with an effective timestamp. Suppress promotions for unresolved cases; Lifecycle Suppression Rules: Stop Marketing Through Service Failures provides the related operating rule.
Paper-rollback failure: traffic returns to the old platform, but queued events replay twice because event IDs were not preserved. The recovery creates a second ledger incident instead of resolving the first.
Frequently asked questions
What reconciliation variance is acceptable?
Zero unexplained variance. Approved exclusions can exist, but each requires a member-level record, reason, owner, approval, and liability amount.
How long should platforms run in parallel?
Run for one complete transaction cycle; 7 to 30 days works as an operating heuristic, measured from your own order timing. Derive the period from your settlement, refund, batch, expiry, and reversal timing; use forced fixtures for rare conditions.
How much transaction history should migrate?
Import enough to cover the longest refund, dispute, expiry, accounting, and service window. If full history is impractical, retain a searchable read-only archive linked by member and transaction ID.
When does rollback stop being safe?
When target-only transactions can no longer be replayed accurately into the source ledger. Establish that boundary during rehearsal, record it in the runbook, and require explicit approval before passing it.