Using Shopify order tags as a job ledger
Write the tag last, check it first, make every side effect repeatable. Three sentences that replace a database for once-per-order automation, and keep the work queue visible in the Shopify admin.
Ashraful
Shopify Select Partner
Short answer: write the tag last, after the work has actually succeeded, and check for it before starting. That single rule makes an integration safe to crash, safe to restart and safe to run twice, without a database. It works because Shopify's order record is the one piece of state both your code and a human can see, and a half-finished job simply has no tag.
Any integration that processes Shopify orders eventually faces the same question: how do you know what you have already done?
The instinctive answer is a database. A table of order IDs and statuses, which you write to as you go.
For a lot of automations you do not need one, and adding one makes the system worse. The order itself can carry the record.
The problem, precisely
Your process runs. It picks up order #1042, downloads a file, validates it, writes it to a folder, and the machine loses power halfway through.
On restart, what does it know?
With no record at all, it either reprocesses everything from the beginning of time or skips forward and loses orders. With a record written at the start, #1042 is marked "processing" forever and nobody knows whether the file landed. With a separate database, you now have two sources of truth that can disagree, and the interesting failures are exactly the ones where they do.
What you want is a record that is true by construction: present only when the work genuinely finished.
Tag as ledger
Shopify orders carry tags. They are visible in the admin, filterable, searchable, writable through the API, and they are part of the order — not a parallel system.
The rule is one sentence: write the tag as the last action, after every side effect has succeeded.
That ordering does all the work.
- Process crashes before the tag is written → the order has no tag → the next run picks it up and redoes it. Correct.
- Process crashes after the tag is written → the work was already done → the next run skips it. Correct.
- Process runs twice concurrently → both do the work, the second one's writes are idempotent, both try to tag → harmless. Correct.
There is no state that means "maybe". An order is either tagged and done, or untagged and pending.
The cost of this design is that a crash means redoing work, so every side effect must be safe to repeat. Writing a file to a deterministic path is safe. Sending an email is not. That constraint is the real one, and it is worth knowing before you choose this pattern.
What should the tags say?
Keep them few and mechanical. A tag vocabulary that grows becomes a state machine nobody documented.
A working set:
wf-queued— processed successfully and handed to the next stagewf-review— processed, but something failed validation and a human needs to lookwf-error— the process itself failed in a way worth flagging
Three tags cover most workflows. Prefix them so they are obviously machine-written and never collide with the tags merchandising uses.
If you need more than the outcome — which check failed, how many files, when — put that in a metafield and keep the tag as the flag. Tags answer "is this done"; metafields answer "what happened".
Reading it back
The check before starting is a tag lookup, and the query is the same one that drives the poll:
status:paid AND NOT tag:wf-queued AND NOT tag:wf-review
That single query is the work queue. Not a table, not a job runner — a filter over orders Shopify already holds.
It also means the queue is visible in the Shopify admin. Anyone can open Orders, filter by tag, and see exactly what is pending, what went to review and what is done. No dashboard to build, no access to grant, no second system to explain to whoever covers when you are away.
That last point is worth more in practice than it looks on paper. Most small automations fail not because the code was wrong but because nobody except the person who built it could see what was happening.
When are tags the wrong answer?
Be honest about the limits.
High frequency updates. Tag writes are API calls against your rate limit. Once per order is nothing. Several times per order across thousands of orders a day starts to matter.
Ordering between two concurrent writers. Tag updates are read-modify-write on the whole tag set. Two processes tagging the same order at the same moment can lose one of the tags. If more than one writer touches an order, you need real coordination, not tags.
Anything needing a timestamp or a value. Tags are flags. "Processed at 14:32 by worker 3, attempt 2" is a metafield.
Large ledgers. Hundreds of tags per order is an abuse of the field and makes the admin unusable for the people who actually merchandise the store.
Anything a customer might see. Some themes and apps surface order tags. Check before writing something internal into them.
The pattern fits single-writer, once-per-order, outcome-is-a-flag automations. That describes a large share of order automation, and almost none of a real order management system.
Tags, metafields, or a database?
| Order tags | Order metafields | Your own database | |
|---|---|---|---|
| Visible in admin | Yes, filterable | Only if configured | No |
| Filterable in order search | Yes | Limited | n/a |
| Holds structured data | No | Yes | Yes |
| Extra infrastructure | None | None | Yes |
| Safe with concurrent writers | No | Better | Yes |
| Survives your app being removed | Yes | Yes | No |
| Good for outcome flags | Yes | Overkill | Overkill |
| Good for detail and history | No | Yes | Yes |
The combination most of our builds use: a tag for the outcome, a metafield for the detail, and no database at all. The store is the system of record, which also means that when the automation is eventually retired or replaced, the history stays with the orders rather than disappearing with the service.
The rule, restated
Write last. Check first. Make every side effect repeatable.
Three sentences, and they replace most of what a job queue exists to do — for the specific case of once-per-order work with a single writer.
This is the same reasoning behind polling Shopify rather than using webhooks: design for the crash, not for the happy path, and prefer the failure mode where work is repeated over the one where work disappears.
We build Shopify order automation that runs on the client's own hardware, with no database to maintain and no monthly fee. Fixed price, source code handed over.
Got a process that quietly reprocesses or skips orders? Book a free 30 minute call. Or read how we built an order-to-print-file pipeline, or see our app development work.
Frequently asked questions
How do I track which Shopify orders an automation has processed?
Write a tag on the order as the final action, after the work has succeeded, and check for that tag before starting. An order with the tag is done; an order without it is pending. A crash mid-process leaves no tag, so the next run safely redoes it.
Should I use Shopify order tags or a database for job state?
Tags for single-writer, once-per-order work where the outcome is a flag. A database when you need timestamps, retry counts, structured history, or when more than one process writes to the same order. Tags avoid an entire piece of infrastructure and stay visible in the admin.
How do I stop an automation processing the same Shopify order twice?
Make the check-and-write ordering do it: check for the completion tag before starting, write it only after every side effect has succeeded. Also make the side effects idempotent, since a crash means the work will be repeated.
Can two processes write Shopify order tags at the same time?
Not safely. Tag updates are a read-modify-write of the full tag set, so simultaneous writes can drop one of the changes. Use this pattern only with a single writer per order, or move to metafields with proper coordination.
What should I name automation order tags?
Prefix them so they are clearly machine-written and never collide with merchandising tags — wf-queued, wf-review, wf-error. Keep the vocabulary to three or four. If you need more detail than an outcome, that belongs in a metafield.
Do order tags count against the Shopify API rate limit?
Yes, each write is an API call. One write per order is negligible. Writing several times per order across thousands of daily orders is worth measuring before you build it that way.
Can customers see Shopify order tags?
Not by default, but some themes and apps surface them. Check your theme and installed apps before writing anything internal into a tag.
About the author
Ashraful
Shopify Select Partner, Top Rated Plus on Upwork. 700+ Shopify projects shipped over 7+ years: themes, apps, migrations, speed, Hydrogen. Solo shop, no agency middlemen.
Read the full storyWorking on a Shopify project?
That's what I do every day. Pick whichever feels lower-friction.
More from the blog
Keep reading
Shopify automation with no hosting and no monthly fee
The monthly fee in most integration quotes is hosting, and hosting exists to accept inbound connections. Reverse the direction and the entire category of cost disappears.
ReadLetting customers upload files on a Shopify product page
Shopify's cart supports file attachments natively and almost nobody knows it. It is free, it works, and it stops at 20MB, which is exactly where print work begins.
ReadBuilding a DTF gang sheet builder on Shopify
A 22x120 inch sheet at 300 DPI is 950 megapixels. That single number decides most of the architecture, and it is why gang sheet pipelines work in testing and fall over in production.
Read