Policy as Code
Policy as code is the practice of expressing rules as executable checks — versioned, reviewed, and evaluated by a system — rather than as prose that people are expected to follow. The rule stops depending on whether someone read the document and remembered it at the right moment.
The pattern is established outside data and worth borrowing precisely. Open Policy Agent describes itself as “an open source, general-purpose policy engine that unifies policy enforcement across the stack,” and its central property is that “OPA decouples policy decision-making from policy enforcement”: when software needs a decision “it queries OPA and supplies structured data (e.g., JSON) as input,” and the engine “generates policy decisions by evaluating the query input against policies and data,” with policies written in “a high-level declarative language called Rego.” Descriptions follow OPA’s documentation, checked in September 2026.
Why the decoupling matters
Separating the decision from the enforcement is what makes one rule apply in several places. The same policy can be consulted by a pipeline before it publishes, by a catalog before it registers a dataset, and by a deployment check before infrastructure is created — each of them enforcing, none of them holding its own copy of the rule. The alternative, which most organizations have by default, is the same intention implemented three times slightly differently, and discovering the differences during an audit.
It also changes what a rule change costs. A policy in a document is changed by editing the document and hoping; a policy in code is changed through review, is distributed from one source, and leaves a record of what changed and when.
One source is not the same as in force everywhere at the same instant, and the difference matters during a change. Enforcement points load policy — a sidecar fetches a bundle, an admission controller syncs, an agent polls — so between publishing a version and every point running it there is a window in which two versions are being enforced. Open Policy Agent’s bundle mechanism is explicit that distribution is eventually consistent, which is the honest general description.
So treat a policy change as a deployment: have a way to see which version each enforcement point is running, and check that the rollout completed rather than assuming it did. And write changes so that the intermediate state is safe — a period where some points enforce the old rule and some the new one should not itself be a violation, which usually means adding a rule before tightening it rather than swapping the meaning of an existing one.
What can be checked automatically
| Can be checked | Cannot be checked |
|---|---|
| Structure — required fields, types, naming conventions, whether a dataset has an owner and a classification | Whether the classification is honest, or whether the recorded owner knows they own it |
| Placement — whether a resource was created in a permitted region, whether a copy crossed a boundary | Whether the data in it is the data the policy was written about |
| Process — whether a contract exists before publication, whether a change went through review | Whether the review was meaningful |
| Values against rules — nulls where forbidden, ranges, referential checks; and, once a meaning has been agreed, whether the calculation implements it | Which meaning to adopt: cents or dollars, whether active excludes trials, whether a total should include refunds |
The right-hand column is not a gap to be closed by better tooling; it is the part that stays human. A meaning decision belongs in a written metric definition, not in a check.
But the boundary sits in a specific place, and drawing it too early gives away checks you could have had. Choosing the meaning is human; verifying that the code follows the meaning already chosen is ordinary testing. Once someone has decided that revenue is net of refunds and expressed in minor units, each of those becomes checkable:
- A fixture with a known answer. A small fixed input — three orders, one refunded — and the expected output computed by hand. The test fails if a later change starts including refunds, which no amount of column-type checking would catch.
- Unit and scale assertions. If the agreed unit is cents, a check that the column is an integer type and that amounts are not suspiciously small catches a value silently converted to dollars.
- Population assertions. If trials are excluded, assert that no trial account appears in the metric’s input — the definition’s exclusion rendered as a query.
So the honest division is not human judgment on one side and automation on the other. Deciding the meaning is human, writing it down is documentation, and testing that the implementation still matches what was written is automated. Skipping that last part is the common failure, and it is what produces a definition everyone agrees on and a calculation that stopped following it four releases ago.
What has to be true for a policy to bind
- It must sit where every access path crosses. A rule enforced in one interface binds only the people who arrive through it, and analytical platforms usually offer several routes to the same bytes — a SQL endpoint, a direct file read, an import into a reporting model, a share with another account. List the paths and say which mechanism enforces the rule on each.
- Each rule needs a stated severity. Blocking and warning are different promises: one leaves the previous good version in place when a check fails, the other publishes and records the failure. Deciding that per rule is what keeps a policy set from becoming either a wall nobody can ship past or a dashboard nobody reads.
Treat the policies themselves as code in every sense: review changes, version them, test them against examples that should pass and examples that should fail, and keep them where the people bound by them can read them. A policy engine with rules nobody can inspect has moved the opacity rather than removed it.
Where this becomes structural rather than optional is in a decentralized operating model: federated computational governance depends on “automated execution of decisions by the platform,” because there is no central team to review each case. How the operating models differ, and which decisions belong to whom, is worked through in Who Decides What.
References: Open Policy Agent Documentation; Zhamak Dehghani, Data Mesh Principles and Logical Architecture; Open Policy Agent, Bundles.
Discover more from Insightful Data Lab
Subscribe to get the latest posts sent to your email.
