Support

Need help?

Most answers are already written down. For everything else, Oneop does not publish a response time — there is no SLA instrument behind one — so the fastest thing you can do is send a complete first message.

Search the help centreEmail support@oneop.ioOpen your workspace

Worth including

  • The email you log in with
  • The URL of the screen it happened on
  • What you expected, and what happened instead

Goes somewhere else

Architecture

The architecture behind CRM, finance and inventory in one platform

By The Oneop team8 min read

TL;DR

A unified business platform is one where CRM, finance and inventory share a single schema, so a contact is one row that tickets, orders, invoices and stock movements reference by foreign key, and a change across modules commits or rolls back as one transaction. The benefit is that cross-module facts cannot disagree.

“All-in-one” is an architecture claim dressed as a marketing one. Two products can both offer CRM, invoicing and stock, and be built so differently that only one of them can answer “is this invoice’s stock actually reserved?” without running a reconciliation job. This post is about what the claim has to mean underneath, and what it costs when it is true.

It is not a sales page. The tradeoffs section is the part worth arguing with.

The first requirement: one identity, referenced not copied

A unified platform stores each business entity once and has every module point at that row. The customer who opened a ticket, signed a quote, received an invoice and has a shipment in transit is one contact record with four foreign keys pointing at it, not four customer records connected by an email address that someone typed slightly differently.

The alternative architecture, which is far more common, is an identity mapping table. The CRM has customer 8841, the accounting package has customer ACC-2290, the warehouse system has wh-0031, and a sync job maintains the correspondence. That mapping is an asset that decays. Anyone can create a customer directly in one of the three systems and the map has no row for it. A merge in one system leaves an orphan in the others. The mapping is correct on the day it was built and quietly less correct every week after.

Referencing instead of copying also changes what a permission means. If a chatbot flow is granted order reads and no order writes, that boundary is real because there is exactly one set of orders. Where each module holds its own copy, a permission is a statement about one copy.

The second requirement: a transaction boundary that spans modules

The real test of a unified platform is whether two modules can change in one commit and roll back together. This is where architectural claims usually stop being true.

Consider issuing an invoice for a sales order. Three things must happen: the receivable, revenue and tax lines post to the ledger, the stock the order committed stays reserved, and the document numbering advances. In a single schema those are one transaction. Either all of it happened or none of it did. In a multi-system stack they are three remote calls, each of which can fail independently, and the recovery mechanism is a compensating action that also makes remote calls and can also fail.

The strongest version of the property is the reversal. Voiding an invoice in Oneop reverses its ledger entry and releases the stock that invoice had reserved, in the same action, because both rows sit inside the same transaction boundary. Confirming a sales order reserves stock inside the same commit that creates the order, so a failure halfway through rolls both back and no hold is left behind for an order that does not exist. Those are properties of where the data lives, not features that were added.

What each architecture can and cannot promise

PropertySynced suite of productsSingle-schema platform
Customer identityA mapping table between per-product IDsOne row, referenced by foreign key
Cross-module consistencyEventual, and only if every sync ranImmediate, enforced by the commit
Partial failureNormal, and handled by compensating actionsImpossible within one transaction
ReportingReads a warehouse fed by extractsReads the posted rows directly
Failure modeSilent drift discovered at month endLoud refusal at the moment of the write
AvailabilityDegrades partiallyDegrades wholly
Swapping one moduleReplace the product, rewrite the syncNot available; the module is part of the schema
Migration costPaid per integration, foreverPaid once, up front, and it is large

The bottom three rows are the honest half of the table, and they are why this is a tradeoff rather than a victory.

The failure case: the compensating transaction that never ran

A distributor runs a CRM, a cloud accounting package and a warehouse system, wired together with webhooks. An order is won. The CRM fires a webhook that creates the invoice in accounting. Accounting fires a webhook that tells the warehouse to reserve stock. The warehouse is mid-deploy and returns a 502.

Nothing alerts, because the accounting package’s webhook retry queue treats a 502 as transient and schedules a retry in fifteen minutes. The deploy takes twenty. By the time the retry fires, the retry queue has given up. The invoice exists, the revenue is recognised, and the stock was never reserved. Two days later the same units are sold to a second customer, who is the one who finds out.

The post-mortem blames the warehouse deploy. The actual cause is that “invoice issued” and “stock reserved” were allowed to be two independent facts. In a shared transaction boundary that state is not reachable, because the reservation and the posting either both commit or neither does. We wrote about the inventory half of this mechanism in stock you can promise: ATP and why overselling happens and the ledger half in double-entry accounting for founders.

Tenancy is part of the architecture, not a layer on top

Putting several modules in one database raises an obvious question: what keeps one customer’s data out of another’s? The answer has to be structural. In Oneop, isolation is a property of the schema rather than a filter a developer has to remember. The database carries 329 tables, 275 of them with a tenant_id column, and every query against those tables is scoped to the tenant on the session. No endpoint reads or writes across a tenant boundary. The security page accounts for the remaining 54 tables individually, because “the rest are platform tables” is the kind of sentence that hides things.

The costs, stated plainly

Coupling is real. A shared schema means a migration to one module’s tables is a change other modules can feel. The discipline that replaces the network boundary is module-level service code and explicit interfaces, and that discipline has to be maintained deliberately.

The blast radius is larger. One database means one failure domain. A bad migration, a lock held too long or a disk filling up affects everything at once rather than one product. Distributed stacks trade this for partial failure, which is genuinely better for uptime and genuinely worse for consistency.

Migration is a one-time wall. Moving CRM, books and stock into one system is not a weekend. The data model has to be mapped, historic balances have to be brought in, and the cutover has a date. A platform that pretends otherwise is selling you the easy part.

Module depth varies. No single platform matches the depth of every specialist tool it replaces. Consolidation is worth it where modules share records and expensive where they do not, which is the framework we set out in integration strategy: which tools to replace and which to keep.

Concentration is a real dependency. One vendor holding the CRM, the books and the stock is a bigger dependency than five vendors holding a fifth each. The mitigations to demand before adopting any system of record are data export, real import tooling and published limits, with or without AI in the picture.

Where Oneop draws the module lines

A shared schema does not require every capability to be on. In Oneop, finance, statutory tax filing, project management, sequences, email-to-ticket and e-signature stay off until a workspace owner turns them on, and off is not cosmetic: the routes return 404, the background schedulers do not run, and the navigation entry is not there. Inventory and the core CRM and support modules are on from the start. The full list of what ships off is on why Oneop, with the plan ladder on pricing.

The reason this architecture matters most right now is that AI agents are being sold as a way to paper over the gaps between systems. They cannot. An agent reading synced copies and writing through remote APIs inherits every problem in the table above, which is the argument in why your AI agent should live inside your system of record. This post is the layer underneath that one: the agent can only be trustworthy if the records it acts on are singular in the first place.

Frequently asked questions

What is the difference between an integrated suite and a single-schema platform?

An integrated suite is several products with their own databases, connected by sync jobs and webhooks, where each product holds its own copy of the customer and reconciles later. A single-schema platform stores the customer once and has every module reference that row directly. The suite can drift between syncs; the single schema has nothing to drift because there is no second copy.

Does one database mean everything is coupled to everything?

It means the coupling is visible instead of hidden. Modules in a single schema still need boundaries: separate service layers, explicit interfaces between modules, and capabilities that can be switched off entirely. What a shared schema removes is the pretence that two systems holding the same fact are independent, when in practice a broken sync job already couples them.

Is a single database a single point of failure?

For availability, yes, and that is a genuine tradeoff. A distributed stack fails partially while a single database fails wholly. The counter-argument is that partial failure in a multi-system stack is not obviously better: an order system that stays up while the ledger is unreachable keeps accepting work that will have to be reconciled by hand afterwards.

When should a business not consolidate onto one platform?

When a specialist tool owns a domain the platform does not model at all, when regulatory or contractual requirements force data into a specific system, or when the migration cost exceeds the drift cost you are trying to remove. Consolidation is worth it where modules share records. It is rarely worth it where they merely exchange files.

How does multi-tenancy fit into a shared schema?

In a shared-schema platform, tenancy is a column on the table rather than a filter applied by application code. Every tenant-scoped table carries a tenant identifier, every query is scoped to the tenant on the session, and no endpoint reads across the boundary. Making isolation a property of the data layer is what stops it depending on a developer remembering to add a WHERE clause.

Written by

The Oneop team

Writing from the team that builds Oneop — an AI customer platform with web chat and email on top of a real CRM, help desk, ledger and warehouse.

Related reading

Start on the free plan and see the real thing

No credit card. Free plan, 2 seats.

Free forever · 2 seats · No credit card