$before / $after / $event / $value Variables (in Events)
$before / $after / $event / $value Variables (in Events)
Level 9 — Real-Time Features, Events & Functions Built-in contextual variables available inside
DEFINE EVENTtriggers and field definitions that expose pre-change state ($before), post-change state ($after), operation type ($event), and field values ($value).
1. Prerequisites
DEFINE EVENT— Server-side event triggers.DEFINE FIELD— Field definition clauses (ASSERT,VALUE).
2. Term Category
Advanced Feature (after, $event trigger variables): - System Variables & Logic
3. Explanation
(1) Design Motivation — "Why did we design this?"
When writing reactive database triggers or field validation rules, the code needs to know:
- What operation triggered this? (
CREATE,UPDATE,DELETE) - What did the record look like before the change?
- What will the record look like after the change?
- What is the specific field value being validated right now?
SurrealDB provides four specialized contextual variables:
$event: A string indicating the write operation type ('CREATE','UPDATE', or'DELETE').$before: The complete record object as it existed before the write (evaluates toNONEonCREATE).$after: The complete record object as it will exist after the write (evaluates toNONEonDELETE).$value: Used insideDEFINE FIELDassertions (ASSERT) and defaults (VALUE) to represent the incoming field input value.
(2) Reality Metaphor
Think of an inspector comparing building blueprints before and after a renovation:
$event: "Renovation Type: Room Extension."$before: Photo of the house before construction started.$after: Photo of the house after construction finished.$value: Checking the exact width measurement written on a single window frame.
(3) Code Examples
Short Snippet
-- Accessing $before and $after to track price drops
DEFINE EVENT price_drop_alert ON product
WHEN $event = 'UPDATE' AND $after.price < $before.price
THEN (
CREATE notification SET item = $after.id, old_price = $before.price, new_price = $after.price
);
Fuller Example
-- 1. Using $value in field assertion
DEFINE TABLE account SCHEMAFULL;
DEFINE FIELD balance ON account TYPE decimal
ASSERT $value >= 0.00; -- $value represents incoming balance number
-- 2. Complex Event using $before, $after, and $event
DEFINE EVENT audit_balance_change ON account
WHEN $event = 'UPDATE' AND $before.balance != $after.balance
THEN (
CREATE balance_history SET
account = $after.id,
old_balance = $before.balance,
new_balance = $after.balance,
difference = $after.balance - $before.balance,
timestamp = time::now()
);
4. Common Mistakes & Pitfalls
Mistake 1: Referencing $before during CREATE Operations
The mistake: Accessing $before.field inside an event handler when $event = 'CREATE'.
Why it's wrong: On a CREATE operation, no previous record existed, so $before is NONE. Dereferencing fields on NONE causes errors or unexpected evaluation.
Incorrect:
-- On CREATE, $before is NONE!
DEFINE EVENT bad_event ON user
WHEN $before.status != $after.status -- Errors on CREATE!
THEN (...);
Fix:
-- Guard with $event = 'UPDATE' first
DEFINE EVENT safe_event ON user
WHEN $event = 'UPDATE' AND $before.status != $after.status
THEN (...);
Mistake 2: Referencing $before in CREATE Event Handlers
The mistake: Referencing $before.name in an event handler matching $event = 'CREATE'.
Why it's wrong: During CREATE events, no previous record existed, so $before is NONE.
Incorrect:
DEFINE EVENT e ON TABLE user WHEN $event = 'CREATE' THEN (CREATE audit SET old = $before.name); // $before is NONE!
Fix:
DEFINE EVENT e ON TABLE user WHEN $event = 'CREATE' THEN (CREATE audit SET new = $after.name);
Mistake 3: Referencing $after in DELETE Event Handlers
The mistake: Referencing $after.id in an event handler matching $event = 'DELETE'.
Why it's wrong: During DELETE events, the record has been deleted, so $after is NONE.
Incorrect:
DEFINE EVENT e ON TABLE user WHEN $event = 'DELETE' THEN (CREATE audit SET del = $after.id); // $after is NONE!
Fix:
DEFINE EVENT e ON TABLE user WHEN $event = 'DELETE' THEN (CREATE audit SET del = $before.id);
5. Practice Exercises
Exercise 1: Comparing $before and $after Record States
Scenario:
In an event trigger on table product, check if field price has changed by comparing $before.price and $after.price.
Requirements:
- Define event
price_changedON TABLEproductWHEN$before.price != $after.price. - Create price log record inside
THEN.
Answer
Implementation
DEFINE EVENT price_changed ON TABLE product WHEN $before.price != $after.price THEN (
CREATE price_history SET
product = $after.id,
old_price = $before.price,
new_price = $after.price,
changed_at = time::now()
);
Technical Explanation
$beforeholds the record document state prior to mutation;$afterholds the post-mutation state.- Comparing
$beforeand$afteridentifies specific field changes during update operations. - Enables granular state change auditing.
Exercise 2: Branching Trigger Logic by $event Type
Scenario:
In a user event trigger, perform different actions depending on whether $event is "CREATE", "UPDATE", or "DELETE".
Requirements:
- Use
$eventvariable inside triggerWHENorTHENblocks.
Answer
Implementation
DEFINE EVENT user_activity ON TABLE user WHEN $event = "CREATE" THEN (
CREATE log SET action = "user_created", user = $after.id
);
Technical Explanation
$eventcontains a string indicating the mutation action type ("CREATE","UPDATE","DELETE").- Allows trigger conditions to target specific mutation types.
- Provides precise trigger execution control.
Exercise 3: Accessing $value inside Field Assertions
Scenario:
Inspect $value inside a field ASSERT expression to enforce that an account balance cannot drop below 0.
Requirements:
- Define field
balanceON TABLEaccountTYPEdecimalASSERT$value >= 0.0dec.
Answer
Implementation
DEFINE TABLE account SCHEMAFULL;
DEFINE FIELD balance ON TABLE account TYPE decimal
ASSERT $value >= 0.0dec;
Technical Explanation
$valuerepresents the candidate value being written to the target field.- Evaluates field assertion expressions before committing transactions.
- Aborts write operations violating assertion rules.
6. Related Terms
DEFINE EVENT— Server-side triggers.ASSERTClause — Field constraint assertions.$authVariable — Authenticated user variable.
7. Key Takeaways
$eventindicates operation type ('CREATE','UPDATE','DELETE').$beforeholds pre-change record data;$afterholds post-change record data.$valuerepresents the target field value inASSERTandVALUEfield clauses.