SurrealDB lets you declare permissions alongside your schema so access is enforced in the database, not only in application code. You attach a PERMISSIONS clause to DEFINE TABLE and DEFINE FIELD to describe which operations are allowed under which conditions.
These clauses apply to record users and to guests when guest access is enabled. System users are not restricted by table or field PERMISSIONS, using roles instead.
Defaults: NONE and FULL
On a table, omitting PERMISSIONS results in a PERMISSIONS NONE in the actual statement passed to the database: record users cannot SELECT, CREATE, UPDATE, or DELETE records in that table until you grant access. PERMISSIONS FULL allows all four operations.
Field permissions default the other way. A field without an explicit clause is stored as PERMISSIONS FULL. The table is the main access gate, while field permissions only narrow further when you need to (for example hiding a password). With FULL, a field follows the table's rules without adding its own.
Record and field rules
For each table, you set independent rules for create, select, update, and delete. Each clause is a SurrealQL expression that must succeed for that operation to proceed; if it fails, the operation is rejected for the affected records. Field-level permissions refine this: you can constrain select, create, and update on individual fields—useful for sensitive data that should not be readable or writable under the same rules as the rest of the record.
What the wider industry calls row-level security is implemented here by writing expressions that depend on the authenticated context. The $auth variable holds the current identity and claims after sign-in, so you can compare it to fields on the record (for example owner = $auth.id) and ensure each user only sees or changes their own data.
Example: users read only their own records
DEFINE TABLE order SCHEMALESS
PERMISSIONS
FOR select
WHERE customer = $auth.id
FOR create
WHERE customer = $auth.id
FOR update, delete
WHERE customer = $auth.id
;Example: a field only administrators may update
DEFINE FIELD internal_note ON order TYPE string
PERMISSIONS
FOR select FULL
FOR update WHERE $auth.role = 'admin'
;Together, table- and field-level PERMISSIONS give you flexible authorisation without duplicating policy in every client. For full syntax and options, see DEFINE TABLE and DEFINE FIELD.