Migrating 940 open cases without losing a clock
What we learned importing live dispute cases from an in house application, and why flagging thirty of them was the right answer.
Calder and Wynn moved 940 open dispute cases from an in house Rails application into a tenant over five weeks, phased by state. Thirty of those cases arrived flagged rather than dated. This is what we learned, including the part where the flags were the useful output.
The rule we set before we started
No imported case gets a due date the source data cannot support. If we cannot point at a document that evidences when the statutory window started, the case comes in with a null due date and a flag saying so.
This was agreed in writing in week one, because it is the kind of decision that becomes an argument in week four when there is a list of exceptions on a screen and a client on the phone.
What the source actually had
The old application stored a disputed_on date, which turned out to be three different things depending on which year the record was created in: a letter date before 2023, a queue entry date between 2023 and 2025, and an acceptance scan date after that. Nothing in the schema recorded which one it was.
| Bucket | Cases | Outcome |
|---|---|---|
| Acceptance scan present | 786 | Dated |
| Scan located in mail vendor export | 124 | Dated |
| No evidence, window still open | 21 | Flagged |
| No evidence, window arguably expired | 9 | Flagged |
Three things that cost us a day each
Duplicate consumers by address spelling
The old system matched consumers on a normalised address string. Two spellings of the same street produced two consumer records, each with part of the history. We now match on tokenised identity and the address is an attribute rather than a key, but the merge on that first migration was done by hand.
Business days across a state holiday calendar
Cancellation holds and the five business day obligations count business days. Business days differ by state. Our first pass used a single federal calendar, and four notices in Texas were reissued because a hold expired a day early. Per tenant, per state calendars shipped in 4.12.0 as a direct result.
Closed cases are not free
We planned to import open cases first and closed cases later, which was right. What we underestimated was that closed cases are where the audit questions come from, so the later import ran under more scrutiny than the earlier one and needed the same reconciliation rules.
What the flags were for
Thirty flagged cases meant thirty conversations, two of them with clients. That is a real cost and the managing partner said so at the time.
It is also the entire point. Those thirty cases were already in that condition before the migration. The old system had a date in a column, which felt like an answer and was not one. The choice was never between thirty flags and no flags. It was between thirty flags and thirty dates nobody could defend.
The cutover step we now always do
A signed baseline export is taken on cutover day, before the first live write. It is the last honest picture of what the source system said, chained as the genesis export for the tenant. It has been asked for once in three years, and that once justified all of them.