One connector, many independent customer accounts · recorded walkthrough
A single, reusable integration platform that connects many customers' ERP accounts to one product. Per-customer differences — credentials, base URL, field names, custom fields, auth mode — are data, not code branches. NetSuite first, via SuiteTalk REST + SuiteQL, SuiteTalk SOAP, RESTlets and SuiteScript; Dynamics 365 and QuickBooks sit behind the same interface. Sync is bidirectional and resumable, idempotent, conflict-aware and observable.
The platform provisions fresh customer accounts and backfills them — paged, truncated and exhausted — through the real API surface.
Two tenants never share records. ERP internalIds are per-account, so ids collide across customers while the platform's links do not.
A customer whose schema is untrustworthy — custom fields and drifted types — is handled as configuration, with no code branch per customer.
Both sides changed the same record. The platform detects it at field level and resolves it, instead of a last-write-wins coin toss on ledger data.
A deep backlog is queued, a worker lease is stranded on purpose, and the drained queue is caught up by parallel workers.
Counts are read from the platform's own metrics, not written by the demo. Nothing is asserted that the run does not print.
ErpConnector interface serves every customer; adding an ERP is one connector + one register() call.Retry-After.fastapi served by uvicorn; pydantic v2 for request models and pydantic-settings for configuration.sqlalchemy 2 ORM over PostgreSQL with psycopg2 — every query scoped by tenant_id, with row-level security underneath.httpx for the async calls into each ERP account.cryptography — per-tenant secrets sealed with keys HKDF-derived from a master key (never stored in the clear, never rotated with the data).typer + rich for the terminal tooling; a resident worker draining an outbox with leases; prometheus-client for metrics.pytest for the ~190-test suite and ruff for lint — both pinned in requirements-dev.txt.locust + gevent in a deliberately separate virtualenv (five scenario files: smoke, soak, multi-tenant sync contention, signed SuiteScript ingest, webhook volume).Recorded from the live console: the simulated NetSuite account as a multi-window desktop — an Omni-style workspace of floating windows (draggable, resizable, minimize tray) — with each window in its own browsing context, and the numbers read from the platform's own endpoints.