Making the Invisible Rules of NetSuite Explicit
(or why spec driven development and constitution are critical)
Most NetSuite development problems don’t start as failures. They start as assumptions.
A script assumes a subsidiary. An integration assumes currency. An GL account reference assumes IDs and internal IDs are stable (as in the same id in every environment, Sandbox vs. Prod, NetSuite Customer A vs. Customer B, Currencies, CoA…). Tax “just works.” Features that exist in sandbox must exist in production too, no? Everything behaves exactly as it did last year, right?
Until one day, it doesn’t.
By the time the issue surfaces, often as data drift, reconciliation gaps, or subtle financial inconsistencies, the original assumptions are long gone. The code still “runs”. The system still “works.” But no one can confidently explain why.
After years of working inside complex NetSuite environments, one pattern shows up again and again: the most dangerous rules in a system are the ones no one ever wrote down.
Why NetSuite systems drift over time
NetSuite is powerful because it adapts to many businesses. It supports different currencies, subsidiaries, tax regimes, accounting structures, and feature sets. That flexibility is a strength, but it also means that two NetSuite accounts (Dev and Prod) that look similar on the surface may behave very differently underneath.
Over time, teams begin to rely on what seems obvious. IDs and Internal IDs appear stable. Base currency feels implicit. Tax is assumed to be calculated somewhere else. A script “only runs in this context.” An integration “only runs once.”
These assumptions accumulate quietly. New engineers inherit them. Admins work around them. AI tools infer them. Eventually, the system’s behavior is governed more by tribal knowledge than by design.
Why documentation isn’t enough
Most organizations respond by writing documentation: diagrams, runbooks, READMEs, wiki pages. Those help explain what exists, but they don’t define what must never be violated.
Documentation describes systems.
Constitutions constrain them.
That distinction matters, especially when systems change hands, evolve across environments, or are modified with AI assistance. Without explicit constraints, even well-intentioned changes can quietly break foundational assumptions.
The missing piece: Specification-Driven Development
What’s missing in most dynamic NetSuite environments isn’t more documentation, it’s Specification-Driven Development (SDD).
SDD starts from a simple premise:
Behavior, constraints, and invariants must be specified before implementation, not inferred from code after the fact.
In an SDD workflow:
intent is written down
constraints are made explicit
decisions are recorded
implementation follows the specification
drift is treated as a defect, not an inevitability
Without specifications, systems morph by accident. With SDD, they evolve by design.
-
Specification-Driven Development (SDD) is an approach where behavior, constraints, and invariants are written down before code is written, and treated as first-class artifacts alongside the implementation.
Instead of inferring how a system works by reading code after the fact, SDD makes intent explicit up front:
what the system is allowed to do
what must never be assumed
what must remain true as the system evolves
In an SDD workflow, specifications don’t describe how something is implemented.
They define the rules the implementation must obey.For complex systems like NetSuite, with multiple environments, subsidiaries, currencies, tax regimes, feature flags, and integrations, SDD provides a way to prevent silent drift and accidental rewrites.
The NetSuite Engineering Constitutions published here are SDD artifacts. They define non-negotiable invariants that apply regardless of code structure, tooling, or whether changes are made by humans or AI.
SDD doesn’t slow teams down. It’s what allows systems to change without breaking their foundations.
What we mean by a “Constitution”
In this context, a Constitution is a foundational SDD artifact.
It is not:
a checklist
a style guide
a set of best practices
It is a collection of invariants: rules that must remain true regardless of implementation, environment, tooling, or time.
An invariant is not optional. If an invariant is violated, the system is considered incorrect, even if it appears to function.
For NetSuite, these invariants live at the boundaries where systems tend to fail: data identity, currency, subsidiaries, accounting structure, tax behavior, and feature availability.
Two Constitutions, one SDD model
To make those boundaries explicit, we’ve published two complementary Constitutions as part of an SDD approach.
The NetSuite SuiteScript Constitution governs how code behaves inside NetSuite. It focuses on preserving business behavior, avoiding destructive rewrites, handling record lifecycle safely, and respecting governance constraints. It makes canonical data rules explicit, how identifiers, currency, subsidiaries, tax, and accounting references must be handled in every script.
The NetSuite Integration Constitution governs how data crosses into and out of NetSuite. It defines contract-first design, idempotency, de-duplication, replay safety, reconciliation, and auditability. It enforces the same canonical data boundaries so integrations and internal scripts cannot silently disagree about meaning.
Together, these documents form a single specification layer that sits above code and integrations, anchoring behavior before implementation begins.
The assumptions that cause the most damage
Across real projects, certain assumptions cause outsized harm when they’re left implicit.
Internal IDs, for example, are frequently treated as stable. In reality, no NetSuite internal ID should ever be assumed consistent across environments: fields, accounts, subsidiaries, tax codes, forms, and searches included. If an identifier matters, it must be resolved explicitly.
Currency and FX are another common fault line. Every monetary amount must declare its currency. FX source and effective date must be explicit. Base currency cannot be assumed, and historical transactions should never be revalued implicitly.
Subsidiary context is equally critical. Subsidiary is not metadata; it defines meaning. Scripts and integrations must always declare subsidiary explicitly and treat cross-subsidiary behavior as a deliberate design choice.
Accounting structure adds another layer of risk. Charts of Accounts differ across environments and subsidiaries. Hard-coding account internal IDs is a reliable way to create subtle financial errors that surface months later.
Tax handling introduces further complexity. Tax behavior varies by locale and configuration. Whether tax is calculated internally or supplied externally must be explicit. Gross versus net semantics cannot be inferred.
Finally, NetSuite features themselves are optional capabilities. OneWorld, Multi-Book, Advanced Revenue Management, SuiteBilling, and Fixed Assets may or may not be enabled. Scripts and integrations must declare feature dependencies and fail safely if those capabilities are unavailable.
These are not implementation details. They are specification-level truths.
Why this matters even more with AI
AI tools are excellent at filling in gaps. They infer defaults, simplify logic, and remove what looks redundant. Without specifications, that behavior is dangerous in NetSuite environments.
Constitutions act as AI guardrails.
They tell both humans and machines where guessing is not allowed. They turn invisible assumptions into enforceable rules and make it possible to evolve systems without quietly breaking them.
How teams actually use these Constitutions
Teams that get value from Constitutions treat them as living SDD artifacts. They copy them into repositories, reference them from specifications and ADRs, use them as design and PR guardrails, and onboard engineers with them. When AI is involved, they require agents to read the Constitutions before generating code.
Most importantly, they treat invariant violations as defects, even when the system appears to work.
How this connects to Origami Precision
At Origami Precision, we work with teams and consultants that inherit complex NetSuite systems and need to make them understandable, safe, and evolvable. These Constitutions reflect patterns we’ve seen repeatedly across real implementations using Specification-Driven Development.
They also inform how we built origami lens, a metadata-driven way to observe real system structure, detect drift across environments, and ground specifications in reality.
Constitutions define the rules. Specifications define intent.
origami lens helps verify reality still matches both.
Reuse and feedback
Both Constitutions are published as standalone Markdown documents, free to reuse and adapt. They are provided as-is, without warranty. Attribution is required. This work is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0).
Repo: https://github.com/joshOrigami/netsuite-engineering-constitutions/tree/main/constitutions
Making assumptions explicit doesn’t slow teams down.
It’s what allows NetSuite systems to survive change.