Triggers
Event-driven logic that fires automatically on INSERT, UPDATE, or DELETE - on graph labels or document collections. Triggers execute within the same transaction as the triggering operation, guaranteeing atomicity.
CREATE TRIGGER
-- After insert on a document collection
CREATE TRIGGER create_profile
AFTER INSERT ON COLLECTION auth.users
FOR EACH ROW AS {
UPSERT DOCUMENT IN profiles NEW.id {
id: NEW.id,
username: NEW.username,
email: NEW.email
}
}
-- Before delete with RAISE to prevent deletion
CREATE TRIGGER protect_admin
BEFORE DELETE ON COLLECTION auth.users
FOR EACH ROW AS {
RAISE 'Cannot delete admin users'
}
-- Set timestamps on graph node creation
CREATE TRIGGER set_timestamps
BEFORE INSERT ON :Project PRIORITY 10
FOR EACH ROW AS {
SET NEW.created_on = timestamp(),
NEW.created_by = current_user()
}
-- Audit log on delete
CREATE TRIGGER audit_delete
AFTER DELETE ON :Project
FOR EACH ROW AS {
CREATE DOCUMENT IN audit_log uuid() {
action: 'DELETE',
old_name: OLD.name,
deleted_by: current_user(),
timestamp: timestamp()
}
}Trigger Body Statements
| Statement | Description |
|---|---|
| CREATE DOCUMENT IN coll key { ... } | Insert document (no-op if key exists) |
| UPSERT DOCUMENT IN coll key { ... } | Insert or merge fields |
| MATCH DOCUMENT d IN coll WHERE ... SET ... | Find and update documents |
| SET NEW.field = expr | Modify row before write (BEFORE only) |
| RAISE 'message' | Abort the operation (BEFORE only) |
OLD / NEW Pseudo-Variables
| Event | OLD | NEW |
|---|---|---|
| INSERT | Not available | The new row |
| UPDATE | Row before changes | Row after changes |
| DELETE | The deleted row | Not available |
Management
CREATE OR REPLACE TRIGGER name ... DROP TRIGGER name ENABLE TRIGGER name DISABLE TRIGGER name SHOW TRIGGERS SHOW TRIGGERS ON :Label SHOW TRIGGERS ON COLLECTION auth.users
Built-in Functions in Triggers
| Function | Description |
|---|---|
| current_user() | UUID of the current session user |
| current_username() | Login username of the current session |
| is_sync() | Whether the operation was sync-originated |
| timestamp() | Current epoch milliseconds |
| uuid() | Generate a new UUID v4 |
Chaining, Backfill & Depth
Trigger chaining: an UPSERT DOCUMENT executed inside a trigger body fires any AFTER triggers defined on the target collection.
Trigger backfill: creating a new trigger automatically processes all existing records in its target (label or collection), so existing data is immediately consistent with the new logic.
Priority ordering: lower number fires first (default 100). Recursive trigger firing is capped at 16 levels deep to prevent infinite loops. Use SKIP TRIGGERS on sync rules to prevent cascades.