---
title: "Server Script Hooks for Document Events"
space: "Wiki"
url: "https://support.aakvatech.com/wiki/server-script-hooks-for-document-events"
updated: "2026-07-22"
---

### **Server Script Hooks for Document Events**

In Frappe, **Server Script Hooks** allow custom Python logic to be executed during the document lifecycle. The following hooks correspond to various stages in the lifecycle of a document:

---

### **Order of Execution in Document Lifecycle**
Here's the sequence of hooks for document events:

1. **Before Insert**  
   Triggered before a new document is inserted into the database.
   - Use this to perform validations or initialize values.
   - Cancelling at this stage prevents the document from being saved.

   ```python
   # Example: Set default values
   if not doc.some_field:
       doc.some_field = "Default Value"
   ```

2. **After Insert**  
   Triggered immediately after a new document is inserted into the database.
   - Use this to perform actions like notifications or updates in related documents.
   - Document is saved in the database at this point.

   ```python
   # Example: Send an alert on document creation
   frappe.publish_realtime("Document Created", message=f"New {doc.doctype} created: {doc.name}")
   ```

3. **Before Save**  
   Triggered before a document is saved (either inserted or updated).
   - Commonly used for validations or calculations.
   - Cancelling prevents the document from being saved.

   ```python
   # Example: Prevent saving if total is zero
   if doc.total == 0:
       frappe.throw("Total cannot be zero!")
   ```

4. **After Save**  
   Triggered after a document is successfully saved in the database.
   - Use this to perform post-save actions like updating linked documents or notifications.

   ```python
   # Example: Update a linked document
   frappe.db.set_value("Related DocType", doc.linked_field, "status", "Updated")
   ```

5. **Before Submit**  
   Triggered before a document is submitted (transition from `Draft` to `Submitted`).
   - Used for final validations or checks.
   - Cancelling prevents the document from being submitted.

   ```python
   # Example: Ensure mandatory fields before submission
   if not doc.mandatory_field:
       frappe.throw("Mandatory Field is required before submission!")
   ```

6. **After Submit**  
   Triggered immediately after a document is submitted.
   - Use this for follow-up actions, such as creating related documents or notifications.

   ```python
   # Example: Log submission
   frappe.logger().info(f"{doc.doctype} {doc.name} submitted successfully.")
   ```

7. **Before Cancel**  
   Triggered before a document is cancelled (transition from `Submitted` to `Cancelled`).
   - Cancelling this prevents the document from being cancelled.

   ```python
   # Example: Prevent cancellation if linked documents exist
   if frappe.db.exists("Linked DocType", {"link_name": doc.name}):
       frappe.throw("Cannot cancel. Linked documents exist!")
   ```

8. **After Cancel**  
   Triggered immediately after a document is cancelled.
   - Use this for cleanup tasks like notifying users or reverting changes in related documents.

   ```python
   # Example: Notify about cancellation
   frappe.publish_realtime("Document Cancelled", message=f"{doc.doctype} {doc.name} was cancelled.")
   ```

9. **Before Delete**  
   Triggered before a document is deleted from the database.
   - Cancelling this prevents the document from being deleted.

   ```python
   # Example: Prevent deletion if conditions are not met
   if not doc.allow_deletion:
       frappe.throw("This document cannot be deleted!")
   ```

10. **After Delete**  
    Triggered after a document is deleted from the database.
    - Use this to clean up related data or log deletion events.

    ```python
    # Example: Log deletion
    frappe.logger().info(f"{doc.doctype} {doc.name} was deleted.")
    ```

---

### **Overall Order of Document Hooks**
For a typical lifecycle:
1. **Before Insert**
2. **After Insert**
3. **Before Save** *(for updates)*
4. **After Save**
5. **Before Submit**
6. **After Submit**
7. **Before Cancel**
8. **After Cancel**
9. **Before Delete**
10. **After Delete**

---

### **Key Considerations**
- **Cancelling:** You can stop the execution of certain events (like insert, save, submit, or delete) by raising an exception (`frappe.throw()`).
- **Validation vs. Action:** Use `Before` hooks for validation and `After` hooks for performing actions.
- **Chaining Effects:** Hooks like `After Save` can trigger other hooks indirectly, so design logic carefully to avoid infinite loops.
