Note: This document is a reference pointer. Complete documentation has been moved to the canonical hooks skill.
For comprehensive data lifecycle hooks documentation, see:
→ objectstack-data/references/data-hooks.md
The canonical reference includes:
- All 14 lifecycle events (beforeFind, afterFind, beforeInsert, afterInsert, beforeUpdate, afterUpdate, beforeDelete, afterDelete, beforeCount, afterCount, beforeAggregate, afterAggregate, beforeFindOne, afterFindOne)
- Complete Hook definition schema
- HookContext API reference
- Registration methods (declarative, programmatic, file-based)
- 10+ common patterns with full examples
- Performance considerations and optimization tips
- Testing strategies (unit and integration)
- Best practices and anti-patterns
import { Hook, HookContext } from '@objectstack/spec/data';
const hook: Hook = {
name: 'my_hook', // Required: unique identifier
object: 'account', // Required: target object(s)
events: ['beforeInsert'], // Required: lifecycle events
handler: async (ctx: HookContext) => {
// Your logic here
},
priority: 100, // Optional: execution order
async: false, // Optional: background execution (after* only)
condition: "status = 'active'", // Optional: conditional execution
};| Event | When Fires | Use Case |
|---|---|---|
beforeFind |
Before querying multiple records | Filter queries, log access |
afterFind |
After querying multiple records | Transform results, mask data |
beforeFindOne |
Before fetching single record | Validate permissions |
afterFindOne |
After fetching single record | Enrich data |
beforeCount |
Before counting records | Filter by context |
afterCount |
After counting records | Log metrics |
beforeAggregate |
Before aggregate operations | Validate rules |
afterAggregate |
After aggregate operations | Transform results |
beforeInsert |
Before creating a record | Set defaults, validate |
afterInsert |
After creating a record | Send notifications |
beforeUpdate |
Before updating a record | Validate changes |
afterUpdate |
After updating a record | Trigger workflows |
beforeDelete |
Before deleting a record | Check dependencies |
afterDelete |
After deleting a record | Clean up related data |
See the full documentation for complete examples of:
- Setting Default Values — Auto-populate fields on insert
- Data Validation — Custom validation rules beyond declarative
- Preventing Deletion — Block deletes based on conditions
- Data Enrichment — Calculate and set derived fields
- Triggering Workflows — Fire notifications and integrations
- Creating Related Records — Maintain referential integrity
- External API Integration — Sync with external systems
- Multi-Object Logic — Cascade updates across objects
- Conditional Execution — Use
conditionproperty - Data Masking — PII protection in read operations
Three methods available:
// objectstack.config.ts
export default defineStack({
hooks: [accountHook, contactHook],
});ctx.ql.registerHook('beforeInsert', async (hookCtx) => {
// Handler logic
}, { object: 'account', priority: 100 });// src/objects/account.hook.ts
export default {
name: 'account_logic',
object: 'account',
events: ['beforeInsert'],
handler: async (ctx) => { /* ... */ },
};✅ DO:
- Use
before*for validation,after*for side effects - Set
async: truefor non-critical background work - Use
ctx.apifor cross-object operations - Handle errors gracefully with meaningful messages
- Test hooks in isolation and integration
❌ DON'T:
- Don't perform expensive operations in
before*hooks - Don't create infinite loops (hooks triggering themselves)
- Don't use
object: '*'unless absolutely necessary - Don't throw in
after*hooks unless critical - Don't assume
ctx.sessionexists
- objectstack-data/SKILL.md#lifecycle-hooks — Complete hooks system overview
- objectstack-data/references/data-hooks.md — Full data hooks documentation
- objectstack-platform/references/plugin-hooks.md — Plugin hook system
- objectstack-automation — Flows and Workflows for advanced automation
For complete documentation with detailed examples, context API reference, testing strategies, and performance optimization, see the canonical reference: