OPA Partial Evaluation

Published
Length
3 min read

Luis Felipe Dias

All posts

You run opa partial evaluation by marking unknown inputs and compiling rules into simpler checks. The engine evaluates known values first and returns residual statements for your app to run. Teams often use this method to push data filtering down into their databases. When roles remain too broad, users who bypass the app can still read everything. How opa partial evaluation works in practice Standard policy checks need every piece of data present before they make a decision. That works well w

Gatekeeper / OPA (K8s): the complete guide

Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.

Free white paper. No spam. Unsubscribe anytime.

You run opa partial evaluation by marking unknown inputs and compiling rules into simpler checks. The engine evaluates known values first and returns residual statements for your app to run. Teams often use this method to push data filtering down into their databases. When roles remain too broad, users who bypass the app can still read everything.

How opa partial evaluation works in practice

Standard policy checks need every piece of data present before they make a decision. That works well when a request holds a user name and a target resource. It fails when a policy depends on millions of rows inside a backend database. Pulling every row into the policy engine wastes memory and slows down the network.

Partial evaluation fixes this bottleneck by splitting the policy check into two separate steps. First, the team tells the engine which inputs are known and which remain unknown. The user identity and role are known at the start of the request. The actual database table values stay marked as unknown during this first step.

The engine runs the rules using the known user facts right away. It simplifies the remaining logic into a small set of conditions called residual rules. Your service then translates those residual rules into native query filters, such as SQL clauses. The database runs the final query and returns only the rows that match.

Where native query translation leaves gaps

This workflow solves the problem of filtering large datasets inside custom software services. Your app only fetches rows that match the simplified rules from the policy engine. It also lets teams precompile static policy rules before any user sends a request. Precompiling rules cuts down CPU work during peak traffic hours.

Still, this setup only protects data when traffic flows through your custom app code. Each service must also maintain its own translator to turn residual rules into queries. If a developer writes a bad translator, the database runs the wrong filter. The database itself only sees the shared service account that the app uses.

Gatekeeper / OPA (K8s): architecture patterns and best practices

Continue reading? Get the full guide.

Free. No spam. Unsubscribe anytime.

This leaves a wide operational gap whenever engineers or support staff need direct database sessions. A human user with a SQL client does not pass through your app translator. Standard database roles decide who can log in, not what individual statements do in flight. One broad role lets an engineer run destructive commands or pull raw customer tables.

Managing direct sessions and sensitive fields

To close that gap, teams must inspect queries and commands across direct sessions too. Relying on app code alone leaves admin tools, scripts, and debugging sessions unchecked. Teams also need a way to handle sensitive columns inside the rows that return.

Row filters only decide whether a whole record shows up in the output. They do not change sensitive values inside an allowed row during a support check. Data masking rewrites matched fields in results, such as emails, phone numbers, or card numbers. Combining command checks with field masking keeps direct data tasks safe without custom app translators.

Check database and API queries on the wire

Identity tools, roles, and network rules decide who opens a session. Setup alone cannot check what each query does or mask sensitive values in a response once a session starts. When workflows touch Postgres, MySQL, SQL Server, MongoDB, ClickHouse, Kubernetes APIs, SSH, or internal HTTP APIs, hoop.dev runs beside those services as an open-source proxy, a sidecar for your Postgres or API. It inspects requests coming in and results going back on the wire.

Your login details and client tools stay as they are while hoop.dev guardrails refuse bad deletes or drops before they run. On responses, hoop.dev data masking rewrites matched sensitive values in memory. Furthermore, hoop.dev holds SOC 2 Type II, is MIT licensed, and writes every query and decision to an audit trail that generates evidence for HIPAA, GDPR, and PCI DSS. See the source on GitHub.

Frequently asked questions

What is the main benefit of opa partial evaluation?

It lets the engine evaluate known inputs early and leave unknown values for later. This avoids loading huge datasets into memory just to make a single policy decision.

How do apps use the output of a partial policy check?

The engine outputs simplified logic that represents the leftover conditions required for approval. Your app code translates those conditions into native database filters, such as SQL where clauses.

Does partial evaluation protect direct engineer sessions to a database?

No, it only helps apps that translate residual rules before they send a query. Engineers who log in with a database client bypass the app and its translators.

Save the open-source gateway.

hoop is MIT-licensed infrastructure for controlling how AI agents reach production data. Star hoophq/hoop so you can inspect it, deploy it, or share it when your team starts governing agent access.