Triggers
Automatic actions that execute in response to database events.
Triggers & Automation
Overview
Triggers are automatic actions that execute in response to database events. They enable you to implement business logic, maintain data integrity, and integrate with external systems without manual intervention.
Trigger Types
Event Types
| Event | When Fired | Sync/Async | Use Cases |
|---|---|---|---|
before_create | Before INSERT | Sync | Validation, defaults, transformations |
after_create | After INSERT | Sync | Notifications, related records |
before_update | Before UPDATE | Sync | Validation, field protection |
after_update | After UPDATE | Sync | Audit logs, cache invalidation |
before_delete | Before DELETE | Sync | Dependency checks, archiving |
after_delete | After DELETE | Sync | Cleanup, notifications |
Creating Triggers
Basic Trigger Structure
typescript
// triggers/users/after-create.ts
import { TriggerDefinition } from '@algorithmshift/runtime';
export const trigger: TriggerDefinition = {
entity: 'users',
event: 'after_create',
name: 'Create User Profile',
description: 'Creates a profile and sends welcome email',
enabled: true,
priority: 10,
condition: (record, context) => {
return record.role === 'customer';
},
handler: async (record, context) => {
// Create profile
await context.db.profiles.create({
user_id: record.id,
display_name: record.name
});
// Send welcome email
await context.services.email.send({
to: record.email,
template: 'welcome-email',
data: { name: record.name }
});
}
};Common Patterns
Audit Logging
typescript
const auditableEntities = ['orders', 'products', 'users'];
for (const entity of auditableEntities) {
for (const event of ['after_create', 'after_update', 'after_delete']) {
registerTrigger({
entity,
event,
handler: async (record, context, oldRecord) => {
await context.db.audit_logs.create({
entity_name: entity,
record_id: record.id,
action: event.replace('after_', ''),
old_values: event === 'after_update' ? oldRecord : null,
new_values: event !== 'after_delete' ? record : null,
changed_by: context.user.id,
timestamp: new Date()
});
}
});
}
}Cache Invalidation
typescript
const cacheInvalidationTrigger: TriggerDefinition = {
entity: 'products',
event: 'after_update',
name: 'Invalidate Product Cache',
handler: async (record, context) => {
await context.cache.delete(`product:${record.id}`);
await context.cache.delete(`category:${record.category_id}:products`);
await context.cache.deletePattern('search:products:*');
}
};Best Practices
Do's
- Keep triggers focused and single-purpose
- Use async triggers for heavy processing
- Handle errors gracefully
- Log important actions
- Use conditions to filter when triggers run
- Test triggers thoroughly
Don'ts
- Don't create circular triggers
- Don't make slow API calls in sync triggers
- Don't modify the triggering record in after triggers
- Don't rely on trigger order for critical logic
- Don't skip error handling