Skip to content
Milan Inventory SyncGet the free plugin

মিলন — Bengali for “a coming together”

Every marketplace you sell on, agreeing on one number

Stock, listings and orders kept in step between WooCommerce and Amazon, eBay, Etsy, Shopify and Walmart. Woo stays your source of truth, and nothing about your catalogue leaves your server.

Shopify free forever, on unlimited sites. Pro from $149/year, flat — never per order and never per SKU.

Part of the Nishchoy family:Nishchoy ReviewsUttor AEOChala SubscriptionsPoth CheckoutMilan Inventory Sync

Free on WordPress.org

One channel, done properly

The free plugin is Shopify, complete — not five channels crippled until you pay. Everything below works fully, forever, on as many sites as you like.

Shopify sync, completely

Push WooCommerce stock to Shopify, and read Shopify's stock back so you can see where the two disagree. One channel, done properly, rather than five channels done badly enough to force an upgrade.

Product mapping that refuses to guess

Map by hand, or auto-map by SKU. The auto-mapper skips any product whose SKU is blank or appears twice on either side, and tells you which — because a wrong mapping pushes one product's stock onto another product's listing.

Order import that leaves customers alone

Shopify orders become WooCommerce orders, HPOS-native. Customers are matched by email and created when absent. An existing customer record is never modified, in any field, for any reason.

Webhooks that cannot double-process

Every inbound event is recorded under a unique key before anything happens. A marketplace that retries — and they all retry — collides with its own earlier delivery and is answered with a 200 that does nothing.

A sync log and a conflict log

Every push, pull and failure, with the endpoint, the status code and how long it took. Every conflict, including the ones resolved automatically, so you can trace what changed your stock and why.

REST API and WP-CLI

Channels, mappings, conflicts and sync runs are all scriptable. `wp milan sync`, `wp milan status`, `wp milan map` and `wp milan diagnose` do from a shell what the screens do from a browser.

The hard part

Overselling is four races, not one bug

Selling the same unit twice is what gets sellers suspended, and it is the reason this plugin is built the way it is. Here is what is actually done about it, rather than a promise that it does not happen.

Every stock write is a compare-and-swap

Each mapping carries a version number. A write says “set stock to 4, but only if the version is still 11” — so two sales landing in the same second cannot both succeed with stale numbers. The loser retries against the new value instead of overwriting it.

Reserved buffers hold the last unit back

Set aside a unit or two per channel so the final one is never the one two marketplaces sell at once. Pro suggests buffer sizes from products that actually came close, rather than a number you had to invent.

Nothing is synced from a checkout hook

Every channel operation is an Action Scheduler job. A marketplace that is slow, rate-limiting you or entirely down cannot make your own checkout slow, because your checkout never waits for it.

One rate limiter, shared by every channel

Amazon allows about five requests a second and less on some endpoints; Etsy counts by the hour; Shopify is generous. A single limiter holds a token budget per channel and per endpoint, respects every retry-after header it is given, and is the only thing in the plugin allowed to make an outbound request.

Which marketplaces, and at which tier

Every channel implements one interface, so adding another is a class rather than a rewrite — including one of your own. See the channel adapter guide.

  • ShopifyFree · Admin REST 2024-10. Two-way in Pro.
  • AmazonPersonal Pro · Selling Partner API, every marketplace.
  • eBayPersonal Pro · Trading API for stock, Fulfillment for orders.
  • EtsyPersonal Pro · Open API v3.
  • WalmartPersonal Pro · Marketplace API v3.
  • FlipkartBetaAgency · India.
  • MeeshoBetaAgency · India.
  • JumiaBetaAgency · Africa, ten countries.
  • LazadaBetaAgency · Southeast Asia, six countries.
  • NoonBetaAgency · Middle East, three countries.

Before you buy, know this: every adapter is written and unit-tested against recorded API responses, but none has yet been run against a live seller account — the sandbox runs are written and not yet executed. The five regional marketplaces are further back still: built from published documentation and labelled beta in the plugin itself. This note stays here until that changes. If it matters to your store, wait for it to.

Deliberate omissions

Four things Milan will not do for you

Each of these is something a competitor does automatically and this plugin refuses to. If you want the convenient version, buy the other thing — you should find that out here, not after paying.

It will not guess a mapping

A SKU that is blank, or that appears on two products, is skipped and reported — never matched on a best-effort basis. The failure mode of a confident guess is that one product's stock lands on another product's listing, and you find out when a customer orders something you do not have.

It will not resolve a conflict silently

When Woo says five units and Amazon says three, something has to win. You choose the rule per channel and per event type — Woo wins, the channel wins, most recent wins, or send it to a review queue. Whichever it is, the conflict is written to a table with both values and the rule applied, including when it resolved itself.

It will not edit an existing customer

Importing a marketplace order matches an existing WooCommerce customer by email and creates one only when there is no match. It never writes to a customer record that already exists — not the name, not the address, not the phone number. A marketplace's idea of your customer does not overwrite yours.

It will not phone home

No telemetry, no analytics, no usage reporting, no remote asset, no external font. The only outbound requests Milan makes are to the marketplaces you connected yourself. Your catalogue, your stock levels and your orders stay on your server.

How it is built

Claims you can check by reading the source, which is GPL and on WordPress.org.

Credentials are encrypted at rest and cannot be printed

Marketplace tokens are sealed with libsodium against a key derived from your WordPress salts. The object that holds them masks itself when serialised to JSON, when dumped, and when cast to a string — so a careless var_dump in somebody's debugging session produces bullets rather than a live API token.

Webhook payloads are never stored

The receiver verifies the signature, records that the event happened, and queues a descriptor containing no customer data at all. The order is then re-read from the marketplace by the job that needs it. Nothing about a shopper is written to a log file at any point.

A dead channel is not a dead store

Every adapter method returns a result object rather than throwing. A marketplace returning 500s, timing out, or rejecting your credentials produces a failed sync row and an alert. WooCommerce carries on taking orders, and so does every other channel.

It is HPOS-native, not HPOS-compatible

Every order is read and written through WooCommerce's own order API. There is no legacy post-table query anywhere in the plugin, so there is nothing to break when a store turns High-Performance Order Storage on.

Against a hosted sync service

Sellbrite, Codisto and CedCommerce are what most stores compare this with. Rather than quote prices that will be out of date by the time you read this, the table sticks to structural differences — the ones that follow from a plugin living in your database and a service living in theirs.

Milan Inventory Sync compared with hosted multi-channel sync services
 Milan Inventory SyncHosted sync services
Where your catalogue livesYour database. Nothing is uploaded.Their servers, synced from your store.
What happens if you stop payingPro features stop; the free plugin and every mapping stay.The service stops syncing and your data goes with it.
Pricing shapeA flat yearly licence. Sell more, pay the same.Usually per-order or per-SKU tiers that grow with you.
Source of truthWooCommerce, unless you configure otherwise per channel.Often the service itself, sitting between Woo and the channels.
Reading the codeGPL, on WordPress.org, auditable line by line.Closed.
Where support livesEmail, with a 24-hour SLA on Business and above.Varies.

Pricing

Personal Pro includes every marketplace in the main five and every sync capability. The tiers above it buy sites, conflict tooling and support — you are never one plan away from a channel you needed.

Free

$0forever

Unlimited sites

Shopify sync, in full, genuinely free.

  • Shopify: read stock, push stock
  • Manual and SKU auto-mapping
  • Shopify order import
  • Idempotent webhooks
  • Sync log and conflict log
  • Channel health dashboard
  • REST API and WP-CLI
  • Setup wizard
Most stores

Personal Pro

$149per year

1 site

Every marketplace and every capability. Nothing held back.

  • Everything in Free
  • Amazon, eBay, Etsy, Walmart
  • Two-way sync on every channel
  • Listing creation and updates
  • Price sync with per-channel markup
  • Order status and tracking push
  • Reserved stock buffers
  • Bundle and kit handling
  • Email, Slack, Discord and SMS alerts
  • Sync latency and oversell analytics
  • Import from Sellbrite, Codisto or CSV
  • WPML and Polylang
  • Reviews, Uttor, Chala and Poth integration

Business Pro

$299per year

3 sites

Personal Pro on three sites, with conflict tooling and a support SLA.

  • Everything in Personal Pro
  • Three site licences
  • Per-channel, per-event conflict rules
  • Bulk conflict resolution
  • Priority email support, 24-hour SLA

Agency

$599per year

25 sites

For agencies, and for stores selling outside the usual five.

  • Everything in Business Pro
  • Twenty-five site licences
  • Flipkart, Meesho, Jumia, Lazada, Noon (beta)
  • Multi-warehouse stock allocation
  • White-label branding
  • Video-call support

All five Nishchoy plugins — $449/year

Nishchoy Reviews, Uttor AEO, Chala Subscriptions, Poth Checkout and Milan Inventory Sync together, against $625 bought separately. They are built to work as one: Milan tells Uttor which channels have a product in stock so the schema stays truthful, pauses a Chala renewal for something that is out of stock everywhere, keeps Poth from upselling what you cannot ship, and can bring Amazon and Etsy reviews into Nishchoy Reviews.

See the bundle

Every paid plan is a yearly licence with automatic updates and support for as long as it is active. A lifetime licence at $499 is offered to the first hundred buyers. If a licence lapses nothing is deleted — Pro's features stop and the free plugin carries on.

Questions

Is the free plugin really limited to Shopify?

Yes, and it is complete for Shopify: stock in both directions of visibility, order import, webhooks, mapping, logs and the CLI. It is not a trial. If Shopify is the only place you sell besides your own store, the free plugin is the whole product and you never need to pay us anything.

Which way does stock flow?

WooCommerce is the source of truth by default: Woo's number is pushed out, and a channel that disagrees is corrected. You can invert that per channel and per event type — stock, price, listing content and order status are each configured separately, so you can let eBay own its own pricing while Woo owns stock everywhere.

What happens when two marketplaces sell the last unit at the same time?

The two stock writes race, and the compare-and-swap means exactly one of them wins on the first attempt; the other sees that the version number moved, re-reads, and applies its change to the new value rather than clobbering it. That prevents the lost update. It does not create inventory — if you genuinely had one unit and sold two, you sold two. Reserved buffers exist precisely to stop that last unit being exposed on several channels at once.

What happens to my data if my licence lapses?

Nothing is deleted. Pro's channels stop syncing and Pro's features switch off; the free plugin carries on with Shopify, and every mapping, log and conflict record stays exactly where it is. Renewing picks up where you left off. Uninstalling only removes your data if you tick the box asking for that — except stored credentials, which are always destroyed.

Where are my marketplace credentials kept?

Encrypted in your own database with libsodium, keyed off your WordPress salts. They are never written to a log, never included in an error message, and never sent anywhere except to the marketplace they belong to. They are shown back to you only when you ask to verify them.

Does it work with High-Performance Order Storage?

Natively. Every order operation goes through WooCommerce's order API rather than the posts table, so there is no legacy path to break when HPOS is enabled — and no compatibility shim doing the reading for us.

How many products can it handle?

It is designed for catalogues in the tens of thousands: syncs are batched Action Scheduler jobs, stock writes are single-row updates, and the rate limiter paces every channel independently. The load test targeting 10,000 SKUs across three channels is written and has not yet been run, so we are not going to quote you a figure from it. This answer will change when it has.

Can I move over from Sellbrite or Codisto?

Pro imports mappings from both, and from a plain CSV. The importer runs as a dry run first and shows you exactly what it will link before it links anything, because an import that silently mismaps a thousand products is worse than no import at all.

Start with the free plugin

Connect Shopify, map your products, and watch the sync log for a week. Upgrade when you want the other marketplaces.

Get it on WordPress.org