You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A large number of emails are not being sent. It appears that mail confirmation messages are usually received, but "authors contacts" are only sent about half of the time, while monthly reminders are almost never sent.
I think I found the issue. We have two different cases of mail not being sent:
From cron jobs, e.g. bundle exec bin/rails runner -e production ''ReminderMail.register_reminder".
From Passenger application process, e.g. mails sent with deliver_later from a controller.
cron jobs
The cron job fails to send the email because register_reminder eventually calls AdminMailer.with(user: user, registers: registers).register_reminder_email.deliver_later, but we are using the async in-process queue adapter. #deliver_later returns immediately and the Ruby process terminates before the background job is finished.
This can be reproduced in production:
bundle exec rails runner -e production 'ExternalMailer.with(reply_to: "harry@vangberg.name", to: "harry@vangberg.name", subject: "Test").simple_email(Contact.find(30).message).deliver_later'
This does not send anything. But if you wait for e.g. 5 seconds before exiting, the mail is sent:
bundle exec rails runner -e production 'ExternalMailer.with(reply_to: "harry@vangberg.name", to: "harry@vangberg.name", subject: "Test").simple_email(Contact.find(30).message).deliver_later; sleep 5'
Short term fix
Change from deliver_later to deliver_now. ReminderMail.register_reminder is not a long-running task, so this should not be a problem. Pull request @ #283
Passenger application processes
The same issue arises in the second case. When a Passenger application process exits, any pending jobs will not be run. This should only be a problem when a worker crashes or when restarting because a new version is deployed. But as it turns out, our Passenger application processes are very short-lived:
$ passenger-status
[...]
/var/www/registry/code (production):
App root: /var/www/registry/code
Requests in queue: 0
* PID: 1979579 Sessions: 0 Processed: 13 Uptime: 38s
CPU: 0% Memory : 49M Last used: 0s ago
* PID: 1979670 Sessions: 0 Processed: 2 Uptime: 2s
CPU: 0% Memory : 0M Last used: 2s ago
* PID: 1979697 Sessions: 0 Processed: 0 Uptime: 1s
CPU: 0% Memory : 0M Last used: 1s ago
The maximum number of requests an application process will process. After serving that many requests, the application process will be shut down and Passenger will restart it. A value of 0 means that there is no maximum. The application process might also be shut down if its idle timeout is reached.
With the number of requests the Registry is handling, Passenger application processes are constantly churned, so the probability of background jobs being dropped/mails not being sent is quite high. I have not verified that this is actually what happens, but it seems very likely.
Short term fix
Setting passenger_max_requests to its default of 0 will make it much less likely that mails are dropped. This should not be a problem, unless we have memory leak issues. At the very least, increasing it to a much larger number would be sensible.
Long term fix
Use solid_queue which persists jobs to the database and runs them in an external worker. This way jobs would never be dropped. This would also allow us to e.g. automatically retry failed jobs, which is nice for all of the jobs we have that contact external services that might be unreliable.
solid_queue only supports Rails 7, so #257 needs to be done first, and we would need to run a worker process and restart it on deploy.
I was wondering if the mails sent by Devise were affected by the same issue as in #292, but Devise defaults to deliver_now, so this should not be an issue.
Activity
vangberg commentedon Jun 3, 2026
Today someone on Slack reported not receiving confirmation mail, fwiw.
vangberg commentedon Jun 18, 2026
I think I found the issue. We have two different cases of mail not being sent:
bundle exec bin/rails runner -e production ''ReminderMail.register_reminder".deliver_laterfrom a controller.cron jobs
The cron job fails to send the email because
register_remindereventually callsAdminMailer.with(user: user, registers: registers).register_reminder_email.deliver_later, but we are using the async in-process queue adapter.#deliver_laterreturns immediately and the Ruby process terminates before the background job is finished.This can be reproduced in production:
This does not send anything. But if you wait for e.g. 5 seconds before exiting, the mail is sent:
Short term fix
Change from
deliver_latertodeliver_now.ReminderMail.register_reminderis not a long-running task, so this should not be a problem. Pull request @ #283Passenger application processes
The same issue arises in the second case. When a Passenger application process exits, any pending jobs will not be run. This should only be a problem when a worker crashes or when restarting because a new version is deployed. But as it turns out, our Passenger application processes are very short-lived:
This is because
passenger_max_requestsis set to 30:With the number of requests the Registry is handling, Passenger application processes are constantly churned, so the probability of background jobs being dropped/mails not being sent is quite high. I have not verified that this is actually what happens, but it seems very likely.
Short term fix
Setting
passenger_max_requeststo its default of0will make it much less likely that mails are dropped. This should not be a problem, unless we have memory leak issues. At the very least, increasing it to a much larger number would be sensible.Long term fix
Use solid_queue which persists jobs to the database and runs them in an external worker. This way jobs would never be dropped. This would also allow us to e.g. automatically retry failed jobs, which is nice for all of the jobs we have that contact external services that might be unreliable.
solid_queue only supports Rails 7, so #257 needs to be done first, and we would need to run a worker process and restart it on deploy.
vangberg commentedon Jun 30, 2026
I was wondering if the mails sent by Devise were affected by the same issue as in #292, but Devise defaults to
deliver_now, so this should not be an issue.