이메일 알림을 더 빠르게 보낼 수 있는 방법이 있을까요?

우리는 #Announcements 카테고리를 운영하고 있으며, 모든 회원은 이 카테고리의 첫 번째 게시글을 자동으로 구독하게 됩니다.

이를 통해 해당 카테고리의 게시글을 특정 날짜와 시간에 맞춰 게시할 수 있습니다.

그 결과, 공지사항이 약 25,000명의 회원에게 이메일로 발송됩니다.

우리가 직면한 문제는 이메일 발송에 1시간 이상 걸린다는 점으로, 시간적 시의성이 중요한 공지사항에는 이상적인 상황이 아닙니다.

Sidekiq를 모니터링하면 “Scheduled” 카운터가 개별 이메일을 하나씩 쌓아 올리는 것을 볼 수 있으며, 약 20,000개에 도달하면 “Enqueued” 탭으로 이동한 뒤 마침내 발송이 시작됩니다.

이 과정을 조금이라도 빠르게 만들 수 있을까요? :thinking:

시간적 시의성이 중요한 이메일의 경우, 현재 속도보다 약 100배 빠르게 발송할 수 있으면 좋겠습니다 :blush:

This discussion may help you, as it explains how to set DISCOURSE_MAX_DIGESTS_ENQUEUED_PER_30_MINS_PER_SITE, which defines the global limit for digests.

I timed it this evening.

I scheduled a post to publish in to the #Announcements category at 18:30.


At 18:40 there were 15,000 emails in the Scheduled queue.


At 18:45, so 15 minutes after the post, there were 22,000 emails in the Scheduled queue.


At 18:48 those emails then gradually started moving over to the Enqueued queue:


At 18:51 they were still moving over:


At 19:03 the emails were on their way out:


By 19:10 there were just 10,000 emails remaining:


At 19:27 there were just 569 emails remaining:


And at 19:29 all the emails had gone out:


So there we have it, one full hour to send 22,000 email notifications.

Can anyone help me identify the bottleneck here?

I’d very much like to be able to send these emails out faster than their current 22000-per-hour rate.

Shooting from the hip,
Is it possible it’s an infrastructure load issue?

Perhaps?

I genuinely don’t know :person_shrugging:

The CPU spiked to around 44% on the server:

And I use AWS SES for the SMTP.

There’s two things going on here:

  • delay while email jobs are enqueued
  • processing time for sending the actual email

For the first, I’m not 100% confident on this but I think lowering email_time_window_mins means the notifications get queued sooner.

Once the email jobs are scheduled, your sidekiq workers are working through them one at a time. Bumping up the sidekiq workers (set DISCOURSE_SIDEKIQ_WORKERS up from 5 to 10, 15, or 20 depending on server capacity) means more jobs get processed at the same time, so the queue gets emptied 2x/3x/4x faster.

I don’t know how the backend works in the finest detail, but the email_time_window_mins is just a delay setting before the first email goes out. During this time, any user that is set to receive the email may “forfeit” the email if they happen to be active within the window of period (official terminology: email skipped; skip reasoning: User was seen recently).

The default delay is 10 minutes, meaning the post must be live for 10 minutes, and only then will the emails be sent.

Richie’s issue is the time difference between the first email and the last email… a delay of one hour. This is probably due to the sheer amount of emails that need to be sent, though I cannot say for certain either.

Changing the setting above would only expedite the sending of the first email, but not address the completion duration of the entire batch of 22,000 emails.


What would be the recommended setting, obviously dependent on infrastructure capability?

Could a high setting result in server issues in terms of load or other?

“As many as the server can handle”.

It’s 100% dependent on the OP’s server capacity - too many and it’ll slow things down, too few and it’ll take longer to process.

Given the CPU graph hitting 40% (is that of a single CPU or total capacity?) I’d probably start with bumping it either 2× (conservative) or 3× (aggressive) and see what happens, depending on risk tolerance for slowdowns.

Great insight, thank you :slight_smile:

Does that DISCOURSE_SIDEKIQ_WORKERS have to be a multiple of 5? Could I set it to 7 for example?

I don’t have that parameter setting in my app.yml so I’ll assume it’s on a default of 5 somewhere.

Can I just create that setting under the existing unicorn workers setting, then rebuild?

Eg:

expose:
  - “443:443”

env:
    UNICORN_WORKERS: 8
    DISCOURSE_SIDEKIQ_WORKERS: 7

Is it as simple as that? :thinking:

Is anyone able to confirm this is the correct change to make to my app.yml when the DISCOURSE_SIDEKIQ_WORKERS parameter does not currently exist?

I believe yes, given a brief inquiry to the AI bot.

Thanks @TempAccount

Interestingly, DISCOURSE_SIDEKIQ_WORKERS only appears eleven times across the whole of meta:

https://meta.discourse.org/search?q=%22DISCOURSE_SIDEKIQ_WORKERS%22%20order%3Alatest_topic

…and one of those is in this topic :flushed_face:

Yes, this is correct.

Any (most?) setting can be overridden in this manner. The default value comes from discourse_defaults.conf.

Thanks @supermathie

My app.yml now reads:

env:
  LANG: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## How many concurrent web requests are supported? Depends on memory and CPU cores.
  ## will be set automatically by bootstrap based on detected CPUs, or you can override
  UNICORN_WORKERS: 8

  ## Added this line on 04/10/25
  ## REF: https://meta.discourse.org/t/is-there-a-way-i-can-send-email-notifications-faster/383103/12
  DISCOURSE_SIDEKIQ_WORKERS: 7

I’ll rebuild later in the week and time it sending emails :smiley:

Just so I know my change has taken effect, am I right in thinking this Threads value should increase from 5 to 7?

Yes, confirmed:

@Richie were you able to resolve your issue?

Thanks for following up.

No, alas not.

I’ve increased the threads from 5 to 8 but the emails are still taking the best part of an hour to send from start to finish.

I’d expect maybe a 40% increase in total throughput.

When jobs are queued, do you see 7/7 utilisation?

Also, look at the server load when it’s processing them, and if you can bump it up further I’d recommend doing so.

Ohhhhhh wait a minute. Is Discourse limiting itself somehow?

Have I missed a setting that’s restricting its CPU usage?? :scream:

It’s not limiting itself per se but each sidekiq worker will process one job at a time, so if you have 22000 emails waiting to go out seven of them will be processed at once.

On the ridiculous side of things, the server probably won’t be able to keep up if you set the number to 1000 parallel workers. So it’s about finding a number that suits all of your needs:

  • process as many jobs as possible at the same time to get through the 22000 emails faster
  • but don’t take up ALL of the server resources which would leave none left for users of the site