Skip to main content
← Back to Insights

Stop Shipping Processes. Ship Data Contracts.

Stop Shipping Processes. Ship Data Contracts.

The question is why so many operational failures appear only after a workflow “goes live.” In most cases, the logic is fine. What breaks is the assumption layer: data that is mostly-right, mostly-complete, and mostly-consistent—until it isn’t.

What’s at stake is not just a failed run or an awkward close. It’s compounding fragility. The more you automate on top of undefined data, the faster small inconsistencies turn into systemic exceptions: mismatched currencies, missing rates, broken mappings, untraceable reversals, and “final” files that arrive after the business moved on.

From first principles, a process is an expression of rules. A system can only enforce rules against something explicit. If the dataset is implicit—owned by nobody, named inconsistently, refreshed unpredictably—then the automation can’t be reliable. It can only be optimistic.

The failure mode: workflows built on unclear datasets

A common pattern is a team doing the “right” things on the surface: standardizing templates, adding buttons, deploying scripts, tightening steps. The workflow looks clean. It runs. People see throughput and assume the system is stable.

Then a simple question exposes the gap:

  • “Can we restrict who can run this?”
  • “Why doesn’t this tie out?”
  • “Which currency rule did we apply?”
  • “What exactly is in scope?”

At that moment the room realizes the system never had an explicit answer—only a shared understanding that lived in people’s heads. So the process continues to run, but it produces exceptions instead of outcomes: missing records, diverging code sets across environments, gaps in rate tables, reversals that don’t reconcile, tax codes that don’t map, and files that change names without changing content.

Why it keeps happening: accountability and definition

Data treated as a byproduct

The structural root cause is that operational data is often treated as a byproduct of the business rather than a product of the system. When data is a byproduct, nobody is accountable for:

  • Field shape and naming
  • Allowed values and code sets
  • Completeness and refresh cadence
  • Forward-looking coverage (how far out the data is valid)
  • Change control (who can modify, and how changes are reviewed)

In that model, people assume “someone upstream” has it handled. Environments drift. Reference data diverges. Inputs get re-issued under new names. And the only validation is a human checking outputs after the fact, when the cost of correction is already high.

Approval confused with definition

The second root cause is mistaking approval for definition. Getting a stakeholder to say, “Yes, that looks right,” is not the same as defining what “right” means in a way a system can enforce.

Approval is a moment in time. Definition is a contract: specific fields, specific constraints, and specific failure states. Without definition, automation can pass tests and still be unsafe—because the tests are confirming plausibility, not correctness.

Data contracts: what the system is allowed to trust

A practical rule for automation design is simple: before automating a process, make the data contract explicit—and make the system enforce it.

A data contract is the operational truth you can hold the system to. It typically includes:

  • Which fields exist and how they’re named
  • Which values are allowed (and which are invalid)
  • What “complete” means (required fields, required joins, required mappings)
  • How updates arrive, at what cadence, and with what forward horizon
  • Who can change the data and how changes are audited

If this sounds heavy, it’s because it replaces hidden labor—debugging, chasing exceptions, and reconciling after the fact—with visible architecture.

A contract-driven rollout example (NetSuite, multi-subsidiary)

Consider an automated revenue and billing adjustment flow across multiple subsidiaries in NetSuite. The tempting approach is to focus on the workflow: identify transactions, generate entries, apply reversals, pull exchange rates, post journals, and confirm the results “look reasonable” on a handful of samples.

The contract-driven approach starts earlier. Before any automation is trusted, define the minimum dataset the flow is allowed to rely on.

Define the minimum trusted dataset

  • Currency codes: authoritative source, allowed values, and cross-environment consistency (sandbox vs. production, subsidiary variations).
  • Exchange rate rule: transaction date vs. posting date, and how reversals must reference the required date rule.
  • Rate table coverage: no silent gaps; explicit forward-looking horizon; refresh cadence; alert thresholds.
  • Master data uniqueness: uniqueness rules for customer/vendor/entity records; required fields for downstream transaction creation; deduplication policy.
  • Scope filters: precise definition of “in scope,” “out of scope,” and “missing,” including how exceptions are categorized.

These are not documentation bullets. They are enforceable constraints. The system should be able to say, deterministically, whether a run is safe to execute.

Enforce the contract in three places

  1. At ingestion. If a rate table has date gaps, the load fails and produces an exception list. If a dataset only publishes forward to an arbitrary cutoff, store that cutoff and alert before it becomes operationally relevant. This shifts failure left: problems are identified when the data arrives, not when the close is underway.

  2. At runtime. If a transaction lacks an exchange rate for the required rule, the process should not “do its best.” It should stop, tag the document, and route it to a queue with a reason code an operator can act on (missing rate, invalid currency, unmapped tax code, out-of-scope subsidiary, incomplete master record).

  3. At access. If only certain roles should run the process, make it a permission boundary, not a training note. In NetSuite terms, this means role-based permissions, script deployment restrictions, and controlled execution paths—because “please don’t click that” is not governance in a system that can mass-post.

What changes when you ship contracts instead of processes

The counterintuitive outcome is that teams spend less time debating the process. When the system enforces a contract, vague disagreement becomes a specific violation:

  • Not “rates seem off,” but “rate table missing for 2026-02-01 to 2026-02-05.”
  • Not “this doesn’t tie out,” but “reversal used posting-date FX; contract requires transaction-date FX.”
  • Not “we should restrict this,” but “role X cannot execute deployment Y.”

That specificity is operational control. It makes reliability measurable, exceptions classifiable, and ownership assignable. It also makes change safer: when someone modifies a code set, a mapping, or a reference table, the contract tells you exactly what downstream will break and how it will break.

The deeper implication: engineered operations

When you ship processes without data contracts, you’re outsourcing reliability to tribal knowledge. The organization becomes dependent on the people who remember which file is “actually final,” which environment has the “right” codes, and which edge cases to ignore until after close.

When you ship data contracts, you’re making a different bet: operations should behave like engineered systems. Explicit interfaces. Known failure states. Predictable change management. Exceptions become inputs to design, not personal heroics.

Ultimately, automation that scales is not primarily a workflow problem. It’s a trust boundary problem: what the system is allowed to assume, and what it must verify.

What this means in practice is straightforward: stop perfecting the steps and start making the data non-negotiable—named, owned, validated, and enforced.

The takeaway is that a “working process” is not the same as a controllable system. Data contracts are how you turn one into the other.