Running an import
Step 4. Imports run as background jobs on our servers, one row at a time, with a durable outcome recorded for every row. You can close the tab, cancel mid-run, and resume later without duplicating anything.
Starting
The final step summarises what's about to happen — how many rows will be written, what that costs, and your conflict mode — and then Start Import begins.
If your balance is zero, the button is disabled and you'll see “You have no credits. Buy credits before importing.” with a link to Credits. Your file and mapping are still there when you come back.
It runs on our servers
Once started, the job doesn't depend on your browser. Close the tab, navigate away, or lose your connection and the import carries on. Come back to Jobs to see where it got to.
The wizard says so directly: “The import runs on our servers — you can leave this page and check progress in History.”
Watching progress
While a job runs you get:
- a progress bar and a processed-of-total count;
- live counts of succeeded, failed and skipped rows;
- a Cancel button;
- the per-row results appearing as they're decided.
The same live view is on Jobs, under Active, so you don't have to keep the wizard open to follow along.
An import in progress
Progress bar around 60%, live succeeded / failed / skipped counts, and the Cancel button.
assets/screenshots/import-running.png
Why it isn't instant
Rows are sent to Shopify strictly one at a time. That's slower than firing them in parallel, and it's the right trade:
- Rate limits. Shopify's Admin API throttles hard. Parallel writes hit the limit, get rejected, and end up slower than serial ones.
- Order. Rows that reference things created by earlier rows work predictably.
- Attribution. Every row's outcome is unambiguous — no interleaved failures to untangle.
Transient failures are retried automatically: up to three attempts per row on a rate limit or a server error, backing off one second then two. Everything else isn't retried, because a validation error won't become valid on a second attempt.
Practically: expect thousands of rows to take minutes, not seconds. Start it and go do something else.
Cancelling
Press Cancel and the job stops between rows. What's already imported stays — cancelling isn't a rollback, and nothing is un-written.
- You're charged only for the rows that were written before you cancelled.
- The job's status becomes cancelled.
- Unprocessed rows stay unprocessed, and Retry will pick them up.
Cancellation is checked every five rows rather than after each one — checking per row would add a database query per row for a feature used rarely. So a cancel takes effect within a handful of rows rather than instantly.
Retry and resume
Open a job from Jobs and press Retry. It resumes from the first row that was never attempted.
| Row state | What Retry does |
|---|---|
| Never attempted | Imported now |
| Succeeded | Left alone — never re-written, never re-charged |
| Skipped | Left alone |
| Errored | Left as an error. A validation error won't fix itself; fix the file and import those rows separately |
| Uncertain | Left as uncertain, deliberately — see below |
Retry uses the conflict mode the job started with, and the results list keeps both halves of the run in one place.
The three cases Retry covers
- You cancelled
- Resume when you're ready. Nothing is duplicated.
- You ran out of credits
- The job stops cleanly at your balance with “Ran out of credits before all rows were imported.” Nothing is created that couldn't be charged for, because a credit is reserved before each write. Buy a pack, then Retry to finish.
- The server restarted mid-import
- Jobs run in-process, so a deploy or restart can leave one unfinished. A job stuck for more than 15 minutes is marked as interrupted with a message saying to retry, and Retry resumes it.
A cancelled job, ready to retry
Job detail with status Cancelled, partial counts, and the Retry button — ideally showing both processed and unprocessed rows in the results list.
assets/screenshots/job-cancelled-retry.png
Uncertain rows
Occasionally a row is interrupted after being sent to Shopify but before the outcome was recorded — a restart at exactly the wrong moment. ImportKit doesn't guess. That row is marked uncertain:
Interrupted while this row was being sent to Shopify, so it may or may not
have been created. It wasn't charged. Check this row in Shopify before
importing it again.
It isn't silently retried, because that could duplicate your data. It isn't silently dropped, because that could lose it. It's surfaced, refunded, and left to you — check that one row in the Shopify admin and import it on its own if it's missing.
Uncertain rows are rare. When they happen, the count appears in the job's stats so you know to look.
Rows that fail don't stop the import
A bad row is a bad row, not a failed import. Processing continues, the row is refunded, and the reason is recorded against it. A file with 900 good rows and 100 broken ones imports 900 and charges for 900.
This is also how permission-blocked owner types behave: those rows report the missing permission, and everything else imports normally.
Fixing and re-importing the failures →
Job statuses
| Status | Meaning |
|---|---|
| Pending | Created, not started yet. |
| Running | Rows are being processed. |
| Done | Every row reached a final outcome. Some may have failed — check the counts, not just the status. |
| Cancelling | Cancel received; finishing the current row. |
| Cancelled | Stopped early. Resumable with Retry. |
| Error | The job itself failed, not just individual rows — for example running out of credits. The message says which. Usually resumable. |
Running more than one import
You can start another import while one is running, and Jobs shows all active jobs with their own progress. Both compete for the same Shopify rate limit, so two imports aren't twice as fast as one. Sequential is generally the calmer choice.
They also share one credit balance, so a large job can consume the credits a smaller one was counting on.
When it finishes
The finished step gives you:
- final counts — succeeded, failed, skipped, and credits used;
- Retry, if any rows weren't processed;
- Start over, to begin a new import;
- Buy more credits, if you ran short.
Then go to Jobs for the per-row detail — including the Shopify ID of everything created, and a download of just the failures.