Supplier stock sync that writes only the numbers it has read
How a supplier stock sync reads wholesalers' B2B portals and updates Shopify: no number on the page means no write, and succeeded means the shop really changed.
AFKzona Group · 6 min read
- The short answer
- The supplier's stock lives on a web page, not in an API
- Stocksync is a browser, a queue and a record of every product
- Unknown is never written as zero, and "succeeded" always means the shop changed
- The shop only ever receives figures the supplier published
- Evaluating a supplier stock sync: five questions to ask
- What generalises
- Questions
The short answer
- Stocksync is a supplier stock sync system: on a schedule it signs into a wholesaler's B2B portal with the shop's own account, reads stock levels, subtracts a safety buffer and sets the matching quantities in Shopify.
- Stocksync keeps unknown and zero apart: a product the portal shows without a number keeps its current figure in the shop, recorded with its reason.
- A run counts as succeeded when every change it decided has reached the shop, and a test guards that rule.
- Writes are absolute quantities, so a repeated run leaves the same figure, and every product in a run is recorded with what was read, what was written and why.
Stocksync never writes a stock figure when the portal gives no number. A trade portal that says "In stock" gets its quantity stored as unknown, and the shop's figure stays as it is: a guessed zero would hide goods the shop can sell.
That rule is what makes a supplier stock sync safe to leave running, and this case study follows it from the wholesaler's login page to the quantity in Shopify.
The supplier's stock lives on a web page, not in an API
For the wholesaler Stocksync is built for, stock exists only on a page behind a login form: an HTML table, a session cookie, availability written as "7 in stock" or "Out of stock". There is no feed. So someone logs in each morning and retypes figures, or nobody does and the shop oversells.
Feed integrations cover suppliers that publish a feed. Automating the person with two browser tabs has two unglamorous halves: reading a page designed for humans, and changing someone else's shop without making it worse.
Stocksync is a browser, a queue and a record of every product
Stocksync drives headless Chrome over the DevTools Protocol, runs the login steps the shop recorded, reads each product's quantity and sets changes through Shopify's Admin GraphQL API. A job queue in Postgres runs it unattended. Every run is recorded, with one row per product: what was read, what was written, and why.
- A recipe, not a scraper. Four step types (go to, fill, click, wait for) and CSS selectors for row, product code and quantity, entered once by the shop. No code per supplier.
- A parser for prose. "1,430 in stock" becomes 1,430, "Sold out" becomes 0, "In stock" becomes unknown.
- A buffer. The shop gets the supplier's figure minus the buffer, never below zero: with a buffer of two, 12 becomes 10. Syncs run every 15 minutes to 24 hours.
- Absolute writes. Shopify receives "set available to 10", in batches of 250, its cap on array inputs. Sent twice, it still leaves 10. A "subtract 2" sent twice subtracts four.
- A queue that survives restarts. Jobs are claimed with
FOR UPDATE SKIP LOCKED; a job whose worker died is reclaimed after 15 minutes. - Encrypted credentials. Portal password and Shopify token use AES-256-GCM, are decrypted only inside the worker's sync, and are never shown.
Unknown is never written as zero, and "succeeded" always means the shop changed
Two rules are built into the code and checked by tests. A product the portal shows without a number keeps its current figure, with the portal's text recorded, and is never written as zero. And a run counts as succeeded when every change it decided has reached the shop, with each product's outcome on the run page.
Each product ends a run in one of four recorded states, and only one of them writes to the shop.
A sync that reports success after changing nothing is worse than no sync at all, because the shop stops checking.
A test guards the second rule: it syncs against a deliberately unconnected store and asserts that every product is read, none is counted as updated, each is counted as failed, and each carries a reason. The engine tests sign into a portal fixture built like a real trade portal, with a session cookie and prose availability, and check the parsing rules, exact quantities, a change from 143 to 4 seen on the next read, and a wrong password failing the run.
The shop only ever receives figures the supplier published
Every figure Stocksync writes is one the supplier published on the portal at the last sync, minus the shop's buffer. When a portal changes its layout, the shop keeps its current figures and the run names the login step or product to re-point, so the shop never shows a quantity nobody read.
The same rule shapes the rest of the design:
- Absolute values make retries free. Shopify reports throttling inside a normal response, and Stocksync reads every reply for it. Because the values are absolute, the next run resends them with no risk of counting twice.
- The record answers the question shops actually ask. Each run keeps the login steps completed and the duration, plus the final page address and title once the stock page is reached, next to the per-product rows.
- Access stays the shop's own. Stocksync signs in with the shop's existing trade account and reads the stock page that account already sees.
Evaluating a supplier stock sync: five questions to ask
| Question | What good looks like |
|---|---|
| What happens when the portal shows no number? | The shop keeps its current figure and the product is recorded, never written as zero. |
| What does "succeeded" mean? | Every decided change reached the shop, product by product. |
| Is the write absolute or a change? | Absolute quantities, so a repeated or duplicated run leaves the same figure. |
| What happens when the portal's layout changes? | The shop keeps its figures, and the run names the step, selector or product to re-point. |
| Where are the portal credentials, and who can see them? | Encrypted with an authenticated cipher, key outside the database, decrypted only where the sync runs, never shown. |
What generalises
Any integration that writes into a system people rely on faces the same decisions. Keep unknown and zero as different values in the data. Define success as the effect having landed, and test it with the target disconnected. Prefer writes that set a value over writes that change one, so a retry needs no coordination.
Then record, per item, why. Trust in a sync comes from answering "why did this figure change?" weeks later.
If your shop buys from a wholesaler that only shows stock behind a login, see how we approach integrations and small, scoped tasks, or book a call to walk through your supplier's portal.
Common questions
How can I sync supplier stock to Shopify if the supplier has no API?
Something has to read the page a person would read. Stocksync signs into the wholesaler's portal with the shop's own account using headless Chrome, follows the login steps and CSS selectors the shop recorded once, reads the quantity for each product code, subtracts a safety buffer and sets absolute available quantities in Shopify through the Admin GraphQL API. Every product in every run is recorded with what was read and what was written.
How often should supplier stock be synced to an online shop?
Often enough that the shop never sells what the supplier sold an hour ago. Stocksync runs on a schedule set per supplier, from every 15 minutes to once a day, with a safety buffer on top. Busy suppliers with fast-moving stock suit a short interval and a small buffer; slow-moving catalogues suit a daily sync. Each run sets absolute quantities, so its timing never causes a double count.
What happens when the supplier changes their website?
The shop stays safe. Stocksync writes only quantities it has read, so a new layout never turns into wrong figures in the shop: if a login step no longer matches, the run names that step, and if a product is not where it was, the shop keeps its current quantity. The recorded steps and selectors are pointed at the new layout, and the next run carries on from there.
What safety buffer should an online shop use for supplier stock?
Enough to cover what can sell between two syncs, because the supplier's other customers are buying too. Stocksync publishes the supplier's quantity minus the buffer, never below zero, and sets the buffer per supplier. With a buffer of two, a supplier figure of 12 becomes 10 in the shop and 1 becomes 0. A shorter sync interval allows a smaller buffer.
How are supplier portal passwords stored?
In Stocksync the supplier password and the Shopify access token are encrypted with AES-256-GCM, using a key held in the server environment rather than in the database. The authentication tag means an edited ciphertext fails to decrypt instead of producing garbage. They are decrypted only inside the sync that the background worker runs, and the interface never displays them.