Heroku timeout when sending emails

Sidekiq is definitely the way to go with Heroku. I don't think mailboxer supports background configuration out of the box. Thankfully, it's still really easy with sidekiq's queueing process.

  1. Add gem 'sidekiq' to your gemfile and run bundle.
  2. Create a worker file app/workers/message_worker.rb.
class MessageWorker
  include Sidekiq::Worker

  def perform(sender_id, recipient_id, body, subject)
    sender = User.find(sender_id)
    recipient = User.find(recipient_id)
    sender.send_message(recipient, body, subject) 
  end
end
  1. Update your Controller to Queue Up the Worker

Remove: current_user.send_message(@recipient, params[:body], params[:subject])

Add: MessageWorker.perform_async(current_user.id, @recipient.id, params[:body], params[:subject])

Note: You should never pass workers ActiveRecord objects. That's why I setup this method to pass the User ids and look them up in the worker's perform method, instead of the entire object.

  1. Finally, restart your server and run bundle exec sidekiq. Now your app should be sending the email background.

  2. When you deploy, you will need a separate dyno for the worker which should look like this: worker: bundle exec sidekiq. You will also need Heroku's redis add-on.


Sounds like a H21 Request Timeout:

An HTTP request took longer than 30 seconds to complete.

To create a background worker for this in RoR, you should grab Resque, a Redis-backed background queueing library for RoR. Here is a demo. Another demo. And another demo.

To learn more about using Resque in Heroku, you can also read the herokue article up here. Or this tutorial (it's an old one though). Another great tutorial.

There is also a resque_mailer gem that will speed things up for you.

gem install resque_mailer #or add it to your Gemfile & use bundler 

It is fairly straightforward. Here is a snippet from a working demo by the author:

class Notifier < ActionMailer::Base
  include Resque::Mailer

  default :from => "[email protected]"

  def test(data={})
    data.symbolize_keys!

    Rails.logger.info "sending test mail"
    Rails.logger.info "params: #{data.keys.join(',')}"
    Rails.logger.info ""

    @subject = data[:subject] || "Testing mail"
    mail(:to => "[email protected]",
         :subject => @subject)
  end
end

doing Notifier.test.deliver will deliver the mail.

You can also consider using mail delivery services like SES.


Sidekiq is an option that you could consider. To get it working you can add something like RedisToGo, then configure an initializer for Redis. Then on Heroku you can add something like worker: bundle exec sidekiq ... to your Procfile.

https://github.com/mperham/sidekiq/wiki/Getting-Started

It also has a dashboard for monitoring.

https://github.com/mperham/sidekiq/wiki/Monitoring