Type
Reference Architecture
Platform
Shopify Plus
Systems
ERP · CRM · PXM
Adapters
NetSuite · HubSpot · Salsify

Services
Stack
Node.js · TypeScript · Hono · BullMQ · Redis · PostgreSQL · Drizzle ORM · React
The Challenge
This is the wall Plus merchants hit at scale: orders need to land in NetSuite as SalesOrders with B2B purchase order numbers and Net 30/60/90 terms, inventory flows back on a 15-minute polling cycle, customer records sync to HubSpot with lifetime value enrichment, and product content published in Salsify has to materialize as Shopify products and metafields.
Each integration has its own auth scheme, data model, failure modes, and conflict surface — and they all have to run reliably across many merchant tenants at once. The hub answers with a small, opinionated core that pushes all system-specific behavior into adapters, config, and per-tenant data.
Production adapters · NetSuite / HubSpot / Salsify
Postgres tables behind full multi-tenancy
Conflict strategies, configurable per mapping
Tests across 34 files
The Approach
Every external system implements connect, disconnect, healthCheck, pull, and push over a shared BaseAdapter that owns retry, error classification, logging, and metrics. Enabling NetSuite for a new merchant is a row in the database, not a deploy.
A tenant context middleware plus a scoped DB helper put an explicit tenant predicate on every query — forgetting a where-clause should not be a quiet correctness bug. RBAC resolves per-tenant roles on every mutating route.
Per-tenant field mappings, type coercion, and checksum-based change detection ahead of every write. When both sides changed, one of four strategies decides — source wins, target wins, most recent, or manual review — with both versions audit-logged.
Inbound, outbound, and dead-letter queues on BullMQ, with an error classifier splitting transient from permanent failures. The dashboard surfaces the DLQ with retry and resolve actions, and alerts fire when it crosses a threshold.
44-second film · silent · loops


The Outcome
Demo mode included
Adding a fourth or fifth adapter — Acumatica, Klaviyo, Algolia — means writing a new BaseAdapter subclass and a manifest; the SyncManager, transform engine, queues, DLQ, metrics, and dashboard pick it up without a code change. A DEMO_MODE switch boots the whole system in memory with 24 hours of seeded sync activity, so reviewers explore the architecture without Docker, Redis, or Postgres running.
The dead-letter queue is not a graveyard. Failures become work items rather than pages that silently pile up.
More Work