Architecture
This page explains the technical architecture of WCPOS for developers and advanced users.
Two-Part System
WCPOS is designed as a two-part system:
-
PHP Plugin: Hosted on your server, this is a relatively small plugin which extends the WooCommerce REST API with POS-specific endpoints.
-
JavaScript Client: This runs locally in your browser, the desktop app, or the iOS/Android apps.
You can think of it as two separate worlds:
- The PHP world is where data management happens using WordPress and WooCommerce.
- The JavaScript world keeps a local, offline-capable copy of the store data your tills need, optimised for fast searching and instant response.
Data Synchronization
v1.10.0 replaces the previous replication layer with a dedicated sync engine. The summary below is the short version — the full explanation lives at How the Sync Engine Works.
The client is local-first: every screen reads and writes the device's local database, and a background sync engine keeps that database and WooCommerce convergent. The engine does not blindly mirror your whole store — it works from what your screens actually need:
- Change detection: the POS polls a lightweight change log with conditional requests; an idle store answers with a single bodyless
304. - Declared demand: a screen declares what it's showing, and the engine decides whether that needs a request or is already answered locally.
- Seeds and lanes: a bounded catalogue seed, a recent-orders window, and idle-time maintenance lanes fill and verify local data on schedules you can tune per device.
- Durable writes: sales and edits queue locally and drain to WooCommerce, with visible recovery for anything the server refuses.
What gets synced: products and variations, categories/tags/brands, customers, tax rates, coupons (Pro), and orders. Payment gateways are fetched at checkout.
Architecture Pros and Cons
| Good 😊 | Bad 😟 |
|---|---|
| Searching local data is instant | Keeping data in sync is challenging |
| Cached data available offline | Limited by the WooCommerce REST API |
| Ability to create better native apps for desktop, iOS, and Android | WordPress themes and hooks cannot customise the POS app |
Local Database
The client stores data in a local database on each device — the web and desktop apps use OPFS (Origin Private File System) storage running in a worker, and the mobile apps use the same on-disk format through a filesystem engine. All platforms share one storage format and recovery tooling. This provides:
- Persistence: Data survives browser restarts and device reboots
- Performance: Fast queries without network latency — filtering, sorting, and pagination run inside the storage layer, so only the visible page of rows reaches the UI
- Offline browsing: Cached data remains accessible without internet
Each site + store + cashier combination gets its own local database, so cashiers and stores never share local data on one device. Upgrades never migrate a local database in place — the app re-downloads from the server, which is always the authoritative copy.
Checkout Architecture
The checkout process uses an iframe/webview that loads the WooCommerce Order Pay page. This approach:
- Leverages existing payment gateways: Any WooCommerce payment gateway can work in the POS
- Maintains security: Payment processing happens through WooCommerce's secure infrastructure
- Reduces complexity: No need to re-implement payment gateway integrations
API Extensions
The PHP plugin extends the WooCommerce REST API with additional endpoints for POS-specific functionality, registered under dedicated wcpos/v1 and wcpos/v2 namespaces — wcpos/v2 carries the v1.10.0 sync surface, which is why the app and plugin versions ship in lockstep. See WooCommerce REST API for an introduction.
The wcpos/v2 namespace
v1.10 introduces the wcpos/v2 REST namespace. Sync lives here, and the shared POS services that were previously served from wcpos/v1 are now served from wcpos/v2 (the wcpos/v1 service routes are pass-throughs to their v2 implementations). The wcpos/v1 routes still register for backward compatibility but are frozen — the current client no longer calls them.
Points that matter if you integrate against these endpoints:
- The v2 routes always register. The old
woocommerce_pos_sync_api_enabledoption has been removed; there is no longer a flag that turns the API on or off. - Public endpoints.
wcpos/v2/site,wcpos/v2/ping, andwcpos/v2/echoare public (used for capability and connectivity probing, including the transport fallbacks for restrictive hosts). - Orders are UUID-primary. Order identity on the wire is the UUID; the legacy
wooOrderIdfield has been retired from the order pull envelope. Order metadata is typed on the wire through a single normaliser. - Line-item pricing storage is documented for third-party sync compatibility — see How POS price overrides are stored.
- Default product sort in the POS is now name ascending (previously
menu_order, id). - Removed legacy methods. Several legacy
API\Settingscontroller methods (for exampleget_general_settings(),update_access_settings(),get_general_endpoint_args(),remove_license_transient()) have been removed; the class alias survives but those methods do not.
WCPOS Pro follows the same V1/V2 split — its shared services are promoted to wcpos/v2 while its order data stays frozen at v1. Store-scoped product pricing runs on the v2 lane, and the till's store scope is carried onto order writes so multi-store orders price and tax against the right store. See Pro.