channel_binding=require. Every statement from an AI agent, from a developer in psql, or from an application then passes through your guardrails, masking rules and audit trail.
Requirements
- A Neon project. The Free plan works. IP Allow, in Allow only the Sidecar, needs the Scale plan.
- Docker on a host with outbound access to Neon on port
5432. - A Postgres client, such as
psql.
Setup
1
Copy the host of each branch
In the Neon console, open the branch and click Connect. The Connection pooling switch picks the pooled host.
Or use the Neon CLI:Both give a string in this form. The host and the database name are the two values you need.Each branch has its own host, so each branch gets its own listener. Copy the host exactly as shown. The pooled host adds

-pooler after the endpoint id. New projects name the default branch production, older ones main.2
Write the config
Save this as
config.yaml. Replace the two upstream hosts with yours. Add a listener for every branch the Sidecar should front.config.yaml
guardrailsblocksDROP,DELETEandTRUNCATEon every listener.maskreplaces email addresses in results on every listener.auditwrites every statement to stdout as JSON lines, andquery_sessionsturns on the/api/sessionsendpoint.upstream_tls: {}encrypts the hop to Neon and verifies Neon’s certificate against the host trust store. Neon’s certificates chain to a public root, so there is no file to download.adminserves health checks and the audit API. It has no authentication, so the next step publishes it on loopback only.
upstream host, and the Neon proxy routes the login to that branch. The config holds no database password. The Sidecar relays the login from the client to Neon.3
Validate and start the Sidecar
--validate prints config OK: 2 listener(s) and one line per listener with its rule count. Versions are on the releases page.4
Point your clients at the Sidecar
Change the host and port, and drop Neon’s default string refuses the hop to the Sidecar on the same host. With
channel_binding=require. The user, password and database stay the same. Every client with a Postgres connection string takes the same change: a Postgres MCP server or psql an AI agent uses, a developer’s psql, and application drivers. The Neon MCP server uses Neon’s API instead of a connection string, so it stays outside the Sidecar.sslmode=require the client stops with server does not support SSL, but SSL was required. With channel_binding=require alone it stops with channel binding required, but SSL not in use.sslmode=disable applies only to the hop from the client to the Sidecar on the same host. When clients reach the Sidecar over a network, turn on downstream_tls and connect with sslmode=require. Leave channel_binding at its default, because the Sidecar offers SCRAM-SHA-256 without channel binding.Verify
Create a test table through the Sidecar:15433 to reach the dev branch. Its sessions show "connection":"neon-dev".
Allow only the Sidecar with IP Allow
Neon’s IP Allow limits which IP addresses can connect to a project’s branches. It is a Scale plan feature. Neon applies the list to every branch, or to protected branches only. Allow only the Sidecar’s egress IP on the branches you lock down, and no client with another IP can reach those branches directly and skip your rules. Branches outside the list stay open to direct connections. Workloads that share the Sidecar’s host or NAT gateway keep that access, so give the Sidecar a static egress IP of its own. The protected-branches shape keeps development branches open while the Sidecar fronts the branches that matter:- Mark
productionas a protected branch in the Neon console. - Add the Sidecar’s IP to IP Allow, scoped to protected branches:
IP Allow also gates the serverless driver and the Neon MCP server, which connect from other IPs. The Data API is not available on projects with IP Allow. Neon’s Private Networking over AWS PrivateLink is the alternative for a VPC, also on the Scale plan.
Name who ran each statement
By default every client connects asneondb_owner, so the audit shows one shared user. Two ways give each statement a name.
A role per person. Create a Postgres role for each person in the Neon console or with the CLI, grant it what it needs, and connect as that role. The audit records it as the principal. Roles belong to a branch, and child branches copy them.
current_setting('hoop.user') returns it.
unsupported startup parameter in options: hoop.user. On that host, use a role per person. See trace ids from the startup packet to choose which options the Sidecar records.
Behavior to know
- A denied statement closes the connection. The client reads the message as
FATAL42501, and Postgres rolls back the open transaction. Connection pools open a new connection. See denials the user can read. - Neon errors reach the client unchanged. A login failure, an IP Allow refusal or a pooler message reads the same with or without the Sidecar.
- The Sidecar removes channel binding. It offers
SCRAM-SHA-256instead ofSCRAM-SHA-256-PLUS, with the same password. See TLS on each leg. - Scale to zero works through the Sidecar. Neon suspends an idle compute and wakes it at the next login. Through the Sidecar, a connection to a suspended compute took 1.8 s against 1.0 s for a warm one. The Sidecar’s dial timeout covers only the hop to the Neon proxy, so the client’s connect timeout governs the wake.
- One listener per branch. The Sidecar derives the TLS server name from
upstream, and Neon refuses a login whose server name andoptions=endpointdisagree, so a listener cannot be pointed at another branch at runtime.
Free and Enterprise
Free tier: one Data Masking rule and one Guardrail per Sidecar are free, forever. Running more than one rule per feature, or managing rules centrally across Sidecars, requires Enterprise.
- Listeners are not capped. The limits count rules per Sidecar process. One Sidecar in front of every branch uses one guardrail rule and one masking rule, however many listeners it has. Rules that differ per branch need a license.
- More rules: an Enterprise license with the guardrails and data-masking features lifts the one-rule caps, with or without a Control Plane. In Docker, pass it with
-e HOOP_LICENSE="$(cat license.json)". See Licensing. - Reviews and central management: connect the Sidecar to a Control Plane, which also needs an Enterprise license. It adds reviews, shared rule sets and one view of many Sidecars.
Next
Guardrails
Write rules that block statements by operation, table or content.
Data Masking
Choose entity types, columns and masking strategies.
PostgreSQL
What the Postgres lane decodes, terminates and masks.
Config File Reference
Every section and field of
config.yaml.