rls
graphql

Row-Level Security (RLS)

Excalibase GraphQL passes request headers directly into the PostgreSQL session, so your existing RLS policies work automatically.

How it works

Pass X-User-Id in your request header. Excalibase sets it as a PostgreSQL session variable before executing any query:

SET request.user_id = 'alice';

Your RLS policies can then reference this variable to filter rows.

Example

1. Create a table with RLS

CREATE TABLE orders (
  order_id  SERIAL PRIMARY KEY,
  user_id   TEXT NOT NULL,
  amount    DECIMAL,
  status    VARCHAR(20)
);

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

2. Create an RLS policy

CREATE POLICY user_isolation ON orders
  FOR ALL
  USING (user_id = current_setting('request.user_id', true));

3. Query with user context

POST /graphql
Content-Type: application/json
X-User-Id: alice

{
  "query": "{ orders { order_id amount status } }"
}

Alice only sees her own rows — the policy is enforced at the database level.

Role-based access

-- Different policies for different roles
CREATE POLICY admin_all ON orders
  FOR ALL TO admin_role
  USING (true);

CREATE POLICY user_own ON orders
  FOR ALL TO app_user
  USING (user_id = current_setting('request.user_id', true));

Pass X-User-Role header to switch roles.

Supported headers

HeaderPostgreSQL variable
X-User-Idrequest.user_id
X-User-Rolerequest.user_role
X-Tenant-Idrequest.tenant_id

These are set as session-scoped variables — they are isolated per connection and reset between requests.