Skip to main content
The Sidecar is where runtime control happens. It is a proxy that runs next to the resource it protects, decodes the wire protocol between a client and that resource, and decides what reaches the resource and what comes back.

How a request flows

A listener decides how requests behave inside the Sidecar. Every request takes one of two paths, and both end at the resource or at a denial. Direct access sends the request straight through. Guardrails and Data Masking apply inline, deterministically, with no model call. See Direct Access. Agentic access routes the request through the AI Analyzer first. The analyzer classifies the statement and the risk level picks a tool: block it, allow it, hand it to a Guardrail, mask what comes back, or send it for review. See Agentic Access. The two features — Guardrails and Data Masking — are reachable from both paths. A listener can use one, the other, both, or neither.

What it can read

The Sidecar picks a codec per listener, and the codec decides how much of the traffic is legible. The HTTP codec captures nothing by default — no bodies, no headers. Everything captured reaches the policy engine, the audit trail and, where an analyzer is configured, a third party, so each listener opts in explicitly.

How many listeners

One listener per upstream. One process runs as many listeners as you declare. A listener is one bind address in front of one upstream, speaking one protocol, with its own set of rules. listeners is a list in the config file, so protecting a second resource means adding a second entry — not starting a second Sidecar:
Startup reports the count it resolved, so you always know how many you got:
Three rules follow from this:
  • Listeners are independent: each one picks its own protocol, bind address and transport. Moving one to a unix socket leaves the other on its TCP port.
  • Rules are per listener: top-level policy and mask are defaults every listener inherits, and any listener can override them. A strict production database and a permissive staging one live in the same process.
  • Audit is per listener: every event carries the listener’s connection name, so one Sidecar serving three resources still produces three separable trails.
Most deployments run a single listener. Add a second when the same workload reaches more than one protected resource. See Listeners for every field.

Where the process sits

The Sidecar is a single binary with no external dependency, so placement is only a question of who can reach it:
  • Beside one workload: a container in the same pod, reached over a unix socket. No port is opened, so reachability becomes a filesystem question rather than a network one.
  • On a host: a plain process binding a TCP port. Nothing to mount, nothing to chown.
  • Behind an existing proxy: Envoy, or anything that can forward plaintext to a local port. The Sidecar is an ordinary upstream, with no ext_proc, no WASM and no custom filter to install.
Nothing above the transport changes between these. Policy, masking and audit behave identically, because the Sidecar reads a connection and never asks what kind it is.

Denials the user can read

When a rule denies a statement, the Sidecar writes the refusal in the protocol’s own frame, always to the client, carrying the message the operator wrote in the config file: A developer reads the reason in psql instead of watching a connection drop.

Audit

Every session is recorded whether or not it issues a statement, so a client that connects and disappears still leaves a trace. Events are JSON lines written to stdout or a file, and the write happens before the forward: a crash between the two cannot lose the record of the statement that caused it.

The six event kinds

A denial writes violation instead of statement, not in addition to it, so pulling every denial never means scanning every statement anyone ever ran.

The admin API

The Sidecar serves a small read-only HTTP interface on its own listener, separate from every data lane — admin.listen, 127.0.0.1:19000 by convention. It answers three different questions: is the process healthy, what config did it actually resolve, and what has it recorded. GET /config is the one to reach for when a rule you wrote never fires. Inheritance is merged at startup, so the file tells you what you asked for and /config tells you what the process resolved:
The query endpoints filter on principal, connection, protocol, since, until, denied, open, and q for substring search, with limit and cursor for paging. /api/events also takes session_id and a repeatable kind. Both in-memory views are off by default, and each has its own budget: audit.memory_buffer sets how many events /events keeps, audit.query_sessions how many sessions back /api/*. Zero on either disables that surface without touching the JSON lines stream, which stays the record of truth.
The admin listener has no authentication and no CORS of its own, and it serves a read interface to every statement every user ran. Bind it to loopback, or put it behind whatever already gates access to your audit trail. Never expose it on a data port.
Where those events go on the way out — the bounded async queue, the file, and the two in-memory sinks — is in Architecture.

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.
Running many Sidecars, shipping shared rule sets to all of them, and seeing them in one place is what the Control Plane adds.

Next

Control Plane

Centralize your Sidecars and deliver rule sets to all of them.

Architecture

The full trace of one connection, from accept through the gate to the upstream and back.

Running the Sidecar

Transports, putting it behind Envoy, and a compose stack that runs the whole thing locally.

Config File Reference

Every section, every field, inheritance between listeners, and what startup refuses.