PyModel

Go

One API for CRM and ERP: structuring a Go operations backend

When customers, orders, inventory, and invoicing drift apart across tools, the fix is a system boundary, not another integration. How we structured our Go operations backend.

Operations data tends to fragment. Customers live in the CRM, orders in the ERP, inventory in a warehouse tool, invoicing somewhere else. Each sync adds drift; each drift erodes trust in every downstream report.

Our operations backend collapses that fragmentation into one Go API where customers, orders, inventory, and invoicing live behind one boundary instead of drifting apart across tools. The interesting decisions were not about frameworks — they were about boundaries. The same structure generalizes, and it looks like this:

One boundary per fact

Model each operational fact — a customer, an order, an inventory count — as a coherent resource exposed by one service, instead of mirroring the internal tables of any source system. Each fact should have exactly one writing path. When two tools want to change the same value, that conflict should surface in code review, not in a midnight reconciliation script.

Durable state, durable jobs

A production design keeps state in PostgreSQL with explicit constraints and turns side effects — notifications, upstream ERP calls, warehouse refreshes — into durable job rows claimed by workers: retried with backoff, observable, safe across crashes. The job row is the truth; “did the webhook fire?” stops being an open question.

Idempotent integration boundaries

External systems are unreliable in both directions, so every inbound webhook and outbound call should be idempotent by key: replayed deliveries become no-ops, retried sends cannot double-charge. Integration code stops being defensive because the boundary guarantees it does not need to be.

What this buys the AI layer

A single, constraint-backed API is also what makes AI systems on top trustworthy: retrieval hits one source of truth, agents act through typed endpoints with real validation, and evaluation can replay against consistent state. You cannot ground answers in five drifting copies of reality.

The stack is deliberately boring — Go, PostgreSQL, durable job rows, idempotent boundaries — because operations software earns trust by being predictable. Boring here is a feature.