DEV Community

Cover image for Why We Chose Permanent Sync Over Migration
Son Do
Son Do

Posted on

Why We Chose Permanent Sync Over Migration

MyCase Immigration / Docketwise Integration: 0: Why We Synced · 1: Before/After · 2: OAuth2 · 3: Sync vs Migration · 4: Sync Boundary · 5: Family Graph · 6: Write Patterns · 7: Webhooks · 8: Billing

When you are integrating two systems that have overlapping data, migration is the obvious first move. Pick a canonical schema, export from the source, import to the destination, point everything at the new store, and decommission the old one. One system. No sync to maintain. Clean.

We rejected migration for this integration, and the decision was not close.

This post covers why migration was the wrong choice for Docketwise immigration data specifically, and what permanent sync requires by comparison.


What migration would have required

A migration from Docketwise to MyCase would have meant: export all client and case data from Docketwise, transform it to the MyCase schema, import it into MyCase, and make MyCase the sole write system for those records going forward.

This runs into three problems immediately.

The first is that Docketwise's schema has no direct equivalent in MyCase for immigration-specific fields. Visa categories, USCIS form associations, matter types, and typed party role graphs are Docketwise-native concepts. MyCase's schema does not have columns for these. The migration would have required either a MyCase schema extension large enough to model the full immigration domain natively, or a decision to discard immigration-specific data on import.

Neither option was acceptable. A schema extension that imports the full Docketwise immigration model would have turned MyCase into an immigration case management system rather than a practice management system with immigration capabilities. Discarding immigration-specific data on import would have broken active case workflows.

The second problem is Docketwise continuity. Docketwise's standalone product would continue operating. Attorneys who use Docketwise without MyCase would continue creating and updating records in Docketwise. A migration that moved data to MyCase on day 1 would have Docketwise and MyCase diverging immediately. The migrated data in MyCase would be stale the moment any Docketwise user made a change.

The third problem is the definition of "when is migration done." A migration of active case data has no natural completion point. An immigration case is not a closed record; it is an active workflow. A petitioner's address changes. A case receives a USCIS response. A new derivative beneficiary is added. All of those are Docketwise writes that would need to replicate to MyCase after a migration. Which is to say: a migration of active case data is a sync that runs once and then stops, leaving both systems divergent. It does not actually solve the synchronization problem.


Why immigration data is operational, not archival

The migration argument is most compelling for archival data. If Docketwise were only storing completed historical cases, a migration could work. Export the archive, import it to MyCase, stop writing to Docketwise for historical records.

Immigration data is not archival. An active immigration case has a USCIS timeline. Deadlines are live. Form statuses change when USCIS acts. Party relationships are updated when a dependent is added or removed. An attorney querying a case expects the current state, not the state as of the most recent MyCase sync.

The consequence of this is that whoever holds the immigration data must be the system that processes immigration writes. Docketwise handles USCIS form preparation, processes immigration-specific validations, and has the domain logic for immigration case management. Migrating the data to MyCase without migrating that domain logic would have given MyCase a copy of immigration data with no way to correctly process changes to it.

Docketwise was not going to be decommissioned as a write system. That determined the rest of the decision.


The staleness argument

The most direct case against migration was this: a migration on day 1 is stale by day 2.

On day 1, we import all Docketwise data to MyCase. Every Client and Case record in MyCase reflects the state in Docketwise as of the import timestamp. MyCase users see accurate data.

On day 2, an attorney using Docketwise standalone updates a beneficiary's address. Docketwise's record is correct. MyCase's record, the one from the migration, is now wrong. The attorney using MyCase to check that client's contact information has stale data.

A migration that does not include a replication mechanism to keep the two systems in sync after day 1 has exchanged one synchronization problem (manual updates) for a different one (divergent records). The divergent records problem is worse because it is invisible. The attorney using MyCase does not know the data is stale. The attorney using Docketwise does not know that MyCase has old data.

Migration staleness: Docketwise and MyCase diverge immediately after migration runs as Docketwise standalone users continue making changes; permanent sync keeps both systems current indefinitely

Permanent sync makes the synchronization mechanism explicit and operational from day 1. There is no point at which both systems are assumed to be identical; they are kept current by the sync layer as long as both systems are live.


What permanent sync requires

If both systems are live write systems for their respective domains, the integration requires a synchronization layer that keeps shared records current in both.

The sync layer has three requirements.

The first is a defined boundary. Not all data syncs. The sync covers the records that both systems need for their core workflows. Everything else stays native to its owner. Part 4 covers how we drew that boundary.

The second is source-of-truth partitioning. Even within the records that sync, ownership of specific fields must be clear. When MyCase and Docketwise both have a Client record, and a field on that record is updated in one system, the sync layer needs to know which system's value wins. Partitioning by field domain prevents write conflicts without requiring a distributed locking mechanism.

The third is handling for continuous updates. The sync layer is not a one-time import. Both systems generate events continually. Webhook delivery, ordering failures, and duplicate processing are ongoing concerns. Part 7 covers specifically what went wrong with webhooks in staging and what the fixes were.


What we chose to sync

The sync covers Client and Case records only. These are the entities that both systems need for their core workflows: MyCase for billing and practice management, Docketwise for immigration case work.

The scope of what syncs within Client and Case is narrow: identity fields that both systems need to refer to the same person and the same matter. Part 4 covers the specific boundary in detail.

Everything else stays native. Docketwise owns immigration-specific fields. MyCase owns practice management fields. The sync layer does not attempt to reconcile fields that only one system cares about.

Migration vs permanent sync: migration produces a point-in-time copy that goes stale the moment a Docketwise user edits a record; permanent sync keeps both systems current indefinitely as long as customers use either one


Next: Part 4. Drawing the Sync Boundary: Client and Case Only. Once we chose sync over migration, the next question was what to sync. Not everything that overlaps belongs in the sync boundary. This post covers the test we used to decide what crossed the boundary and what the decision excluded.

Top comments (0)