---
title: "Read-only Enforcement"
description: "Block every write and DDL statement for an agent credential. Reads pass, writes are rejected in the wire protocol before they reach your database."
canonical: "https://pgbeam.com/docs/read-only"
last-updated: "2026-09-14T19:37:21.000Z"
---

# Read-only Enforcement

> Block every write and DDL statement for an agent credential. Reads pass, writes are rejected in the wire protocol before they reach your database.

URL: https://pgbeam.com/docs/read-only

Read-only is the safest access mode for an agent. With it, PgBeam allows reads and rejects every `INSERT`, `UPDATE`, `DELETE`, and DDL statement before it reaches your database. The agent receives an LLM-readable reason, so it can adjust instead of failing blind.

## Turn it on

A credential's policy is fixed at creation. To move an existing credential to a different policy, rotate or re-issue it against the new profile.

In the dashboard, set **Access mode** to **Read-only** on the policy profile.

## What is allowed and blocked

Statement

Read-only

`SELECT`

Allowed

`WITH … SELECT` (read-only CTE)

Allowed

`EXPLAIN` of a read

Allowed

`INSERT` / `UPDATE` / `DELETE`

Blocked

`CREATE` / `ALTER` / `DROP` / `TRUNCATE`

Blocked

`COPY`

Blocked

Data-modifying CTE (`WITH … UPDATE`)

Blocked

`SELECT … INTO t` (creates a table)

Blocked

`EXPLAIN ANALYZE` (runs the statement)

Blocked

`SELECT … INTO t` and `CREATE TABLE t AS SELECT …` are the same statement in Postgres, so both are blocked. `EXPLAIN ANALYZE` runs the statement it is given rather than only planning it, so it is blocked whenever the statement underneath it writes or creates a table. A plain `EXPLAIN` of a read executes nothing and stays allowed.

## What the agent sees

A blocked write comes back as a Postgres error (SQLSTATE `42501`):

The error is written to be read by an LLM, so an agent can correct its plan and retry within the rules.

## Fails closed

A multi-statement batch is rejected if any statement in it would be blocked. Unparseable SQL and unknown statement types are rejected too. This prevents an agent from slipping a write past the parser.

Read-only is the right default. When an agent genuinely needs to write,
read-write mode with a tight allowlist is one option.
Sandbox writes let an agent write freely against an
isolated, throwaway branch without touching production, and
approvals hold a production write until a human signs off.

## Related

Policies

Allowlists

Audit log