---
title: "Local policy testing"
description: "Test allowlists, masking, row filters, and statement rules against a local or dev database with the pgbeam-dev tool, before a policy reaches prod."
canonical: "https://pgbeam.com/docs/local-testing"
last-updated: "2026-09-05T14:02:29.000Z"
---

# Local policy testing

> Test allowlists, masking, row filters, and statement rules against a local or dev database with the pgbeam-dev tool, before a policy reaches prod.

URL: https://pgbeam.com/docs/local-testing

`pgbeam-dev` runs the PgBeam policy engine on your machine. Write a policy as a JSON or YAML file, evaluate statements against it offline, or stand up a local wire-protocol gateway in front of a dev database and point your agent at it. Nothing is deployed and no PgBeam account is involved; when the policy behaves the way you want, save the same file through the API, the dashboard, or the IaC providers.

## Who this is for

`pgbeam-dev` lives in the PgBeam source tree, which is not public. It is a tool for teams working with that source: self-hosted and enterprise deployments set up with the PgBeam team, and contributors. If that is you, run it from the repository root as a Go program:

A prebuilt binary distribution is planned but not available yet. If you are on the hosted platform without source access, the policy what-if and replay endpoints cover the same test-before-rollout need against your real traffic, no local tooling required.

Both modes run the same code the platform runs. `check` uses the engine behind the policy what-if endpoint, and `serve` runs the production proxy's wire path with a static local config. There is no separate local implementation that could drift from real enforcement.

## Policy file

The file shape is the API's `PolicyProfileInput` schema, the same body `POST /v1/projects/{id}/policies` accepts, validated with the same validators. Unknown fields are rejected.

## Check statements offline

Prints a verdict per statement: `allow`, `block` with the rule and an actionable hint, `mask` with the masked output columns, or `row-filter` with the injected predicate and the rewritten SQL. Add `-json` for a machine readable report, or `-file queries.sql` (or `-file -` for stdin) to evaluate a whole file of statements.

The exit code is 1 when any statement is blocked, which makes `check` a CI gate for policy-as-code repositories: keep the policy file and the queries your agent is expected to run in the repo, and fail the build when a policy change would break them.

## Run a local gateway

The gateway listens on `127.0.0.1:6432` (change with `-listen`) and prints a connection string for a local `agent_dev` credential. Connect any client, ORM, or agent to it and every statement is enforced exactly like production: blocked statements get the same LLM-readable errors, masked columns come back redacted, row filters are injected before the statement reaches your dev database. Each decision is logged to stdout.

Local limits, by design: no TLS (loopback only), approvals fail closed (no reviewer exists locally), `write_mode: sandbox` writes are rejected (no instant branches), budgets reset on restart, and the query cache is disabled so every statement hits the database. The tool's README (`backend/tools/pgbeam-dev/README.md` in the source tree) has the full flag reference.