- How does nlqdb isolate AI agent memory between tenants?
- Every table in a provisioned database has a `tenant_isolation` row-level-security policy keyed on `current_setting('app.tenant_id')`, and the read/write path sets that value transaction-locally on every request. Postgres applies the predicate to each statement, so isolation lives in the engine, not in application code you have to remember to write.
- What stops the LLM's SQL from reading another tenant's rows?
- Row-level security runs below the SQL. The policy predicate is enforced on every read regardless of the CTEs, JOINs, or aliases the model writes — the compiled SQL can't widen its own scope. Even a query with no tenant filter at all only sees the current tenant's rows, because the engine adds the boundary, not the query.
- Can I isolate AI agent memory per end-user, not just per account?
- Within a single shared database, per-user / per-agent row scoping (`app.agent_id`) is in progress (E-03, `SK-PIVOT-009`) — not shipped yet. Today the shipped boundaries are per-tenant RLS and per-device API keys; for hard per-user isolation now, give each end-user their own provisioned database.
- How is this multi-tenant isolation different from a WHERE clause?
- A `WHERE tenant_id = ?` filter lives in application code, so one forgotten predicate — or one LLM-generated query that omits it — leaks every tenant. RLS lives in the database and applies to every statement, and it fails closed: a missing scope returns no rows instead of someone else's. The blast radius of a mistake is nothing, not everything.