Created
February 9, 2026 11:21
-
-
Save vishnu-narayanan/9091e277f966eab6d3bc6bdc177e060d to your computer and use it in GitHub Desktop.
delete conversations older than x months
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Purge conversations created before a given cutoff date. | |
| # Copy this script to the ./scripts directory and run it with: | |
| # Usage: | |
| # bundle exec rails runner scripts/purge_old_conversations.rb | |
| # | |
| # Ensure | |
| # you have a full database backup (pg_dump) before running. | |
| # scale up sidekiq workers to ensure you have capacity for background deletion jobs this will enqueue | |
| BATCH_SIZE = 500 | |
| DEFAULT_CUTOFF_MONTHS = 24 | |
| print 'Enter Account ID (leave blank for all accounts): ' | |
| account_input = $stdin.gets.strip | |
| account = account_input.present? ? Account.find(account_input.to_i) : nil | |
| print "Enter cutoff in months (default: #{DEFAULT_CUTOFF_MONTHS}): " | |
| months_input = $stdin.gets.strip | |
| months = months_input.present? ? months_input.to_i : DEFAULT_CUTOFF_MONTHS | |
| cutoff_date = months.months.ago | |
| scope = account ? account.conversations : Conversation.all | |
| scope = scope.where('conversations.created_at < ?', cutoff_date) | |
| puts "\nConversations created before #{cutoff_date.to_date}:" | |
| puts '-' * 60 | |
| if account | |
| puts " #{account.name} (ID: #{account.id}): #{scope.count}" | |
| else | |
| scope.joins(:account).group('accounts.name', 'accounts.id').count | |
| .sort_by { |_, count| -count } | |
| .each { |(name, id), count| puts " #{name} (ID: #{id}): #{count}" } | |
| end | |
| total = scope.count | |
| puts '-' * 60 | |
| puts "Total: #{total}" | |
| if total.zero? | |
| puts 'Nothing to delete.' | |
| exit | |
| end | |
| puts "\nThis will enqueue conversations for async deletion via Sidekiq." | |
| puts 'Ensure you have a database backup before proceeding.' | |
| print 'Do you want to proceed? (y/N): ' | |
| unless %w[y yes].include?($stdin.gets.strip.downcase) | |
| puts 'Aborted.' | |
| exit | |
| end | |
| total_enqueued = 0 | |
| scope.find_in_batches(batch_size: BATCH_SIZE) do |batch| | |
| batch.each { |conversation| DeleteObjectJob.perform_later(conversation) } | |
| total_enqueued += batch.size | |
| puts "Enqueued #{total_enqueued}/#{total}..." | |
| # sleep 10 # Uncomment to throttle if Sidekiq queues are backing up | |
| end | |
| puts "Done. #{total_enqueued} conversations enqueued for deletion." | |
| puts 'Monitor the Sidekiq low queue for progress.' |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Deleting Old Conversations
This script deletes conversations (and all associated messages, attachments, etc.) created before a specified cutoff date.
Before You Start
Take a full database backup
Ensure Sidekiq is running and scaled up
Deletions are processed asynchronously on the
lowqueue. Each conversation deletion triggers background jobs for cleaning up messages, attachments, notifications, etc. Scale up your Sidekiq workers to handle the load.Running the Script
Copy
purge_old_conversations.rbto your Chatwoot installation directory(chatwoot/scripts/).Run:
bundle exec rails runner scripts/purge_old_conversations.rbThe script will prompt you for:
It will show a preview of how many conversations will be deleted per account and ask for confirmation before proceeding.
Monitoring Progress
/monitoring/sidekiqon your Chatwoot instanceIf Sidekiq jobs are queueing up
# sleep 10 # Uncomment to throttle if Sidekiq queues are backing upAdjust the value (in seconds) as needed to add a delay between batches.
After Completion
Once the Sidekiq
lowqueue is fully drained, run the following inpsqlto reclaim disk space: