CRUD Order of Operations
Understanding the precise sequence of events during a data operation is crucial for debugging, extending functionality, and building reliable automations. This document outlines the step-by-step process the system follows for every Create, Update, and Delete action on a record.
Core Concepts
The system's logic is enhanced by two types of customizable actions that run during a CRUD operation: Record Triggers and Record Trigger Automations.
- Record Triggers: These are Python scripts (
.pyfiles) that you write. They provide maximum flexibility for complex logic, calculations, or integrations that require custom code. - Record Trigger Automations: These are no-code/low-code workflows built directly in the UI. They are perfect for creating validation rules, field updates, and other process automations without writing any code.
Both Triggers and Automations run at specific points in the transaction, defined by a context. The primary contexts are:
- Before: Runs before the record is saved to the database. This is your chance to validate data, modify the record's values, or prevent the operation from completing by raising an error.
- After: Runs immediately after the record is successfully saved to the database. This is ideal for performing actions on related records, sending notifications, or initiating other processes that depend on the original record being committed.
- Async: Runs in the background after the main transaction is complete and the response has been sent to the user. This is best for long-running processes, callouts to external systems, or any task that shouldn't slow down the user's experience.
Create Operation Flow
When a new record is created, the system follows a precise sequence to ensure data integrity, apply business logic, and execute any configured automations.
Create Operation Steps
- Initialization: The system receives the incoming data and loads the corresponding object schema and data model.
- Permission Checks: It verifies that the current user has the necessary object-level and field-level permissions to create the record.
- System Validation: It runs internal validations (
record_system_validations) and any hardcoded checks (hard_record_checks) specific to the object type. - Data Hydration: The system enriches the data by:
- Assigning a new UUID (
id). - Setting default values for
created_date,modified_date,created_by, andmodified_by. - Setting the
ownerif ownership is enabled for the object.
- Assigning a new UUID (
- Lookup Resolution: It processes any lookup fields, resolving record IDs or names into structured
Lookupobjects. - Field Formatting: Individual fields are validated and formatted based on their data type (e.g.,
phone,datetime,address). - Execute "Before Create" Triggers: It runs all active Record Triggers (Python code) for the 'Before Create' context, in their specified order. The data can be modified by these scripts.
- Execute "Before Create" Automations: It runs all active Record Trigger Automations (UI workflows) for the 'Before Create' context. The data can also be modified here.
- Database Insert: The final, validated, and modified record is inserted into the database.
- Execute "After Create" Triggers: It runs all 'After Create' Record Triggers. These triggers receive the saved data but cannot modify it further. They are used for side effects.
- Execute "After Create" Automations: It runs all 'After Create' Record Trigger Automations.
- Post-Processing: The system performs final tasks like invalidating caches, syncing records to Git if enabled, and updating role hierarchies.
- Queue "Async" Operations: All 'Async Create' Record Triggers and Automations are added to a background queue to be processed separately.
- Return Response: The newly created record is returned to the client.
Update Operation Flow
Updating a record follows a similar path to creation, but with the critical addition of fetching the original record data to enable comparisons and preserve existing values.
Update Operation Steps
- Initialization: The system loads the object schema and data model based on the request.
- Fetch Old Data: The current state of the record is retrieved from the database. This
old_datais available to all subsequent triggers and automations. - Permission Checks: It verifies object-level and field-level permissions for the update. The field-level check specifically compares
old_datato the incomingnew_datato ensure the user is allowed to make the requested changes. - System Validation: It runs internal and hardcoded validations.
- Data Merging: The system merges the incoming data with the old data. Any fields not included in the update request retain their original values. The
modified_dateandmodified_byfields are updated. - Lookup Resolution & Formatting: Lookups are resolved and fields are formatted, just as in the create process.
- Execute "Before Update" Triggers: Runs all 'Before Update' Record Triggers. These scripts receive both
new_dataandold_dataand can modify thenew_datapayload before it's saved. - Execute "Before Update" Automations: Runs all 'Before Update' Record Trigger Automations.
- Database Update: The final version of the record is updated in the database.
- Execute "After Update" Triggers: Runs all 'After Update' Record Triggers for side effects.
- Execute "After Update" Automations: Runs all 'After Update' Record Trigger Automations.
- Post-Processing: The system performs tasks like cache invalidation and Git sync.
- Queue "Async" Operations: All 'Async Update' Record Triggers and Automations are queued for background processing.
- Return Response: The updated record is returned to the client.
Delete Operation Flow
The delete operation is the most straightforward but still allows for intervention and post-processing through triggers and automations.
Delete Operation Steps
- Initialization: The system loads the relevant object schema and data model.
- Fetch Record: The record slated for deletion is retrieved from the database. This data is then available to triggers and automations as
old_data. - Permission Checks: It verifies that the user has permission to delete the record.
- System Validation: It runs any relevant hardcoded checks.
- Execute "Before Delete" Triggers: Runs all 'Before Delete' Record Triggers. These scripts can prevent the deletion by raising an error.
- Execute "Before Delete" Automations: Runs all 'Before Delete' Record Trigger Automations.
- Database Deletion: The record is permanently removed from the database.
- Execute "After Delete" Triggers: Runs all 'After Delete' Record Triggers. These are commonly used to clean up related data, log the deletion, or notify other systems.
- Execute "After Delete" Automations: Runs all 'After Delete' Record Trigger Automations.
- Post-Processing: The system performs final tasks like cache invalidation and Git sync.
- Queue "Async" Operations: All 'Async Delete' Record Triggers and Automations are queued for background processing.
- Return Response: A success status is returned to the client.