The hardest hour of a Shopify migration is the one where you flip
DNS and the new store starts taking real orders. Most platforms tell
you "do not touch the migration on go-live night." Graftport is
built around the opposite assumption: re-running is a normal
operation, even on launch night. This guide is the contract for
how that works.
The run model: extract, transform, load
Every run in Graftport is one of four shapes:
| Mode | What it does |
|---|
| Extract only | Read from source, store raw. No destination touch. |
| Transform only | Re-shape last extract using current mappings. No fetches. |
| Load only | Push the last transformed shape to the destination. |
| Full | Extract → transform → load, in one run. |
Each mode can also be flagged dry-run, which means the run does
all its work but stops short of writing to the destination Shopify
store. Use dry-run liberally — it is exactly the same code path as
a real run, minus the final write.
The four modes are how you orchestrate launch. A typical sequence:
- Day -7. Run Full + dry-run to populate staging on a fresh
destination dev store. Spot-check.
- Day -1. Run Full + dry-run again on the same destination
to confirm nothing has drifted. Spot-check the last 100 orders
on the source.
- Launch hour. Run Full, no dry-run. Idempotent: anything
already loaded is skipped.
- Launch hour + 1. Flip DNS once Graftport reports the run
succeeded.
Idempotency: how Graftport prevents duplicates
Every record Graftport writes carries a stable identity formed
from the source platform plus the source ID. Magento's product
ID 7842 is magento:product:7842 regardless of which run touched
it. The destination Shopify product's metafield carries the same
identity tag.
On any subsequent run:
- Extract pulls every record from the source as before.
- Transform shapes it as before.
- Before loading, Graftport queries the destination for any
record carrying the matching identity tag.
- If found and unchanged: skipped. The skip is recorded; the
destination is not touched.
- If found and changed: synced. Counted at the sync rate
(much cheaper than a first-load record).
- If not found: first-loaded. Counted at the tier rate.
You can re-run a migration ten times in a row. The destination
will not gain duplicates. The bill grows by sync charges for the
records that genuinely changed since the last run, and by nothing
else.
The dry-run safety net
Dry-run runs the same extract and transform code as a live run.
What it skips is exclusively the destination writes. Use it for:
- Testing a mapping change. After editing a mapping, run
Transform only + dry-run and inspect the output in the Data
tab. Verify before you write.
- Catching breaking source changes. If the source store's
schema changes overnight (a custom attribute was deleted), dry-
run will surface a transform error before you load.
- Estimating cost. Dry-run reports the projected first-load
vs. sync record counts. The pricing dashboard converts that
into a cost estimate matching the current pricing plan.
A failed dry-run is cheap. A failed live load on launch night is
expensive in trust, even if Graftport is fully idempotent.
The launch-night runbook
A practical hour-by-hour timetable that has worked across many
launches:
T -2 hours. Run Extract only against the live source.
This locks in the source state at a known timestamp.
T -1 hour. Run Transform only + dry-run. Open the Data
tab, confirm record counts match expectations and no records
errored. Total time: usually under 10 minutes.
T 0. Run Load only (no dry-run). Pushes the just-extracted,
just-transformed payload to the destination. Most records are
skipped (already loaded from the rehearsal); a few hundred sync;
new orders since the rehearsal first-load. Total time: a few
minutes for a delta, longer for a full first push.
T +5 minutes. Open the run page, confirm failed = 0 and the
run status is succeeded.
T +10 minutes. Flip DNS to the destination Shopify store. Old
URLs continue to 301-redirect via the redirect table Graftport
loaded on the destination during the first run.
T +60 minutes. Submit the new sitemap to Search Console. Watch
the Coverage report.
What re-running does not handle
Two cases call for human judgment:
- Hard deletes on the source. A product that existed at first
load and has been deleted from the source by go-live is not
deleted on the destination. Graftport never deletes records you
did not explicitly remove. If you want to mirror deletes, do
them manually on the destination side, or contact us about
enabling soft-delete propagation per resource type.
- Field-level changes that need translation. If your source
team renamed an attribute between extract and load, the new
name needs a mapping update before the load. Run Extract
only + Transform only + dry-run to surface the gap before
it becomes a stuck launch.
Rollback if something is wrong post-launch
Graftport never overwrites a destination record without recording
what it did. Each loaded record's per-run trace lives in
run.record_event. If a re-sync clobbered a hand-edit your team
made on the destination Shopify store, you can:
- Open the run page, find the record in Data → Run output.
- The "previous value" is recorded alongside the "new value".
- Restore by hand, or revert the mapping that caused the change
and re-sync.
Larger rollback patterns:
- Revert a mapping change. Mappings are versioned in
app.mapping_template_version. From the mapping editor, click
Versions, pick a prior version, hit Restore. The next
run uses the restored shape.
- Re-pause a destination. If a re-run is pushing rubbish, you
can disconnect the destination credentials from the migration's
settings page. The next run fails fast at the load phase rather
than writing more bad data.
Cost shape on a re-run
The pricing tier you pay depends on whether a record is a first
load or a sync. The dashboard's projection is based on the most
recent dry-run; it is exact, not approximate. A typical launch-
night sequence costs:
- The original first load: priced at the first-load tier rates
(decreasing per record after the included monthly allowance is
consumed).
- Each rehearsal re-run: only the delta records get charged.
Records that did not change are skipped at zero cost.
- The launch-night re-run: also only the delta. Most launches
cost low double-digit euros above the original load.
Related reading
When go-live night arrives, the muscle memory you built in dry-runs
makes it boring. Boring is what you want.