At a glance
PostgreSQL Inventory Rows vs Ecom Inventory Count reconciles the stock figures held in your PostgreSQL inventory table against the stock count the storefront is publishing through the ecommerce connector. It is a drift detector: when the database (your system of record) and the storefront (what shoppers see) disagree on how many units of a SKU are available, you are either overselling stock you do not have or hiding stock you could be selling. Both cost money. The card surfaces the SKUs where the two counts have diverged, so a platform team can catch a broken sync job before it turns into cancelled orders or dead inventory.
| PostgreSQL side | The available-quantity rows in your inventory table (the count, and the per-SKU quantities, of stock the database holds as the source of truth). |
| Ecom side | The published inventory level per SKU from the connected storefront connector (Shopify, BigCommerce, or Adobe Commerce inventory API). |
| What the card shows | The count of SKUs whose PostgreSQL quantity does not match the storefront quantity, with the worst-drifting SKUs listed. A drift of zero means the sync is healthy. |
| Aggregation window | Real-time spot-check plus a rolling 24-hour view (RT/24h), so you see both the current divergence and whether drift has been accumulating. |
| Time window | RT/24h (live spot-check with a 24-hour trend). |
| Alert trigger | > 0 SKUs drifting. Any SKU where the database and storefront disagree is worth surfacing, because a single oversold hero product during a sale is enough to generate cancellations and chargebacks. |
| Roles | DBA, platform engineering, ecommerce operations, merchandising. |
Calculation
The engine takes the per-SKU available quantity from the PostgreSQL inventory table (the system of record) and joins it, by SKU, to the published inventory level returned by the storefront connector’s inventory API. For each SKU it computes the difference:Worked example
A platform team runs the storefront on Shopify and keeps inventory authoritative in PostgreSQL, pushing updates to Shopify through a sync worker every five minutes. On 18 Apr 26 at 14:20 BST the card flags drift. The detail table:| SKU | Product | PostgreSQL qty | Storefront qty | Drift | Direction |
|---|---|---|---|---|---|
| TR-OAK-180 | Oak dining table | 0 | 14 | -14 | Overselling |
| CH-LIN-02 | Linen dining chair | 6 | 48 | -42 | Overselling |
| LMP-BR-09 | Brass floor lamp | 120 | 0 | +120 | Underselling |
| RUG-WL-240 | Wool rug 240cm | 33 | 31 | +2 | Minor / in-flight |
> 0 alert has tripped. The team reads the rows by risk:
- Two SKUs are overselling, which is the dangerous direction. The oak table reads zero in the database but the storefront still advertises 14 units. Every order placed against those phantom 14 will be accepted and then cancelled, producing refunds, chargebacks, and one-star reviews. The linen chair is worse in volume: the storefront is offering 42 units that do not exist.
- One SKU is underselling, which is lost revenue rather than a customer-trust hit. The brass lamp has 120 units in the database but shows zero on the storefront, so it is invisible to shoppers. No orders, no complaints, just silent missed sales.
- One SKU is in-flight. The wool rug differs by two units, consistent with an order placed seconds before the sync cycle. The 24-hour view shows it self-correcting on the next sync; it is not a fault.
- Direction decides urgency. Overselling (storefront higher than database) damages customers and trust and must be fixed first. Underselling (database higher than storefront) is lost revenue you can recover once the sync is healthy. Always read the sign of the drift, not just the count.
- Small drift on hot SKUs is normal; persistent drift is a broken sync. A SKU off by one or two units for one sync cycle is in-flight inventory. The same SKU drifting for an hour, or the drift count climbing across the 24-hour view, means the pipeline has stalled.
- The database is the truth, the storefront is the symptom. When the two disagree, fix the propagation from PostgreSQL to the storefront rather than editing the storefront directly, which only masks the underlying sync fault and creates a second source of truth.
Sibling cards
| Card | Why pair it with this card | What the combination tells you |
|---|---|---|
| PostgreSQL QPS Spike vs Ecom Order Rate | The query-volume cross-channel sibling. | Inventory drift alongside an order spike with no QPS rise can mean the write path that updates stock has stalled. |
| PgBouncer Pool Saturation vs Traffic Burst | The capacity cross-channel sibling. | A saturated pool can starve the sync worker of connections, causing the very drift this card detects. |
| Slow Queries During Checkout Window (5m) | The checkout-latency cross-channel sibling. | Slow inventory queries during checkout can leave stock decrements lagging, feeding drift. |
| Query Error Rate % | The error view of the write path. | A spike in errors on inventory writes is a leading indicator of drift about to appear here. |
| Top Tables by Dead Tuples | The bloat view of the inventory table. | A heavily updated inventory table accumulating dead tuples can slow the reads the sync depends on. |
| PostgreSQL Health Score | The executive composite. | Persistent drift is a business-impact signal even when the database’s own health looks green. |
Reconciling against the source
Where to look directly:
On the PostgreSQL side, query the inventory table for the authoritative per-SKU quantity, for example SELECT sku, available_qty FROM inventory WHERE sku = ANY($1); for the drifting SKUs the card lists.
On the ecom side, read the same SKUs back from the storefront’s inventory API: Shopify’s InventoryLevel / GraphQL inventory query, BigCommerce’s catalogue inventory endpoint, or Adobe Commerce’s stock items API.
Compare the two numbers per SKU. The difference is the drift the card reports.
Why our number may legitimately differ from a manual check:
| Reason | Direction | Why |
|---|---|---|
| Sync window | Lower over time | A SKU drifting at the instant you check may have synced by the time you query both sides. The 24-hour view distinguishes in-flight drift from a real stall. |
| Multi-location stock | Variable | If the storefront aggregates stock across several locations and the database holds per-location rows, compare the aggregate, not a single location row. The card aligns to the storefront’s published total. |
| Reserved / committed stock | Variable | Some pipelines subtract reserved-for-order quantity before publishing. If the database shows on-hand and the storefront shows available-to-sell, a constant offset is expected, not drift. The card uses the available-to-sell basis on both sides where possible. |
| API caching | Marginal | Storefront inventory APIs may serve a cached value for a few seconds; a back-to-back manual query can see a value the card has not yet refreshed. |