Skip to main content

Optimize Deletions: destroy_async for Rails

Purpose:

  • destroy_async is an option for the dependent attribute in Active Record associations.
  • It enables asynchronous deletion of associated records when their parent record is destroyed.
  • This approach prevents blocking the main request thread while deleting potentially large numbers of associated records.

How it Works:

  1. Association Definition:
    • When you define an association (e.g., has_many, belongs_to), you can specify the dependent behavior for deletion:
      1
      2
      3
      
      class Order < ApplicationRecord
        has_many :order_items, dependent: :destroy_async
      end
      
  2. Parent Record Destruction:
    • When you call destroy on the parent record (e.g., order.destroy), Rails doesn’t directly delete the associated order_items.
  3. Background Job Enqueueing:
    • Instead, Rails enqueues an ActiveRecord::DestroyAssociationAsyncJob in the background job queue (typically managed by Active Job).
  4. Background Job Processing:
    • A separate worker process picks up the job from the queue and executes the following steps:
      • Fetches the associated records for deletion (e.g., order_items belonging to the destroyed order).
      • Iterates through the associated records and calls destroy on each one, triggering their deletion callbacks and database operations.

Benefits:

  • Improved Performance: The main request thread isn’t blocked by potentially slow deletions, enhancing responsiveness for the user.
  • Scalability: Background jobs can be distributed across multiple workers for large datasets, improving overall deletion speed.

Considerations:

  • Active Job Setup: Ensure you have Active Job configured in your Rails application for destroy_async to work effectively.
  • Foreign Key Constraints: Asynchronous deletion bypasses database-level foreign key constraints. Make sure your application logic handles potential data inconsistencies if necessary.
  • Callbacks: Callbacks defined on the associated models (before_destroy, after_destroy, etc.) will still be executed during background deletion.

When to Use destroy_async:

  • It’s generally recommended for situations where you anticipate a large number of associated records to be deleted, potentially causing performance issues for the main request.
  • Consider trade-offs (e.g., potential data inconsistencies) before using destroy_async.