Before widening concurrency slots: widening a 2-core server from 8 to 14, and the earlier conclusion that was half wrong

日本語版

Development log of the Toreca Dash app / September 2026

The back end of my app Toreca Dash runs over 200 scheduled jobs on one small server (2 cores, 3.8 GB of memory). The number of jobs that can run at once is capped: the concurrency slots.

On 7 September 2026, when I shortened some intervals to speed up first-come monitoring, the monitor I most wanted fast was slowed by waiting for a slot. I raised the slots from 8 to 11 and then 14. This is the record of that decision and of what to look at.

Numbers come from my work log of 7 September 2026.

8 slots were not enough

To speed up first-come monitoring I shortened several intervals. Then the one-minute “instant sell-out monitor” started being skipped, because all 8 slots were full.

8 slots (after shortening)11 slots
Queue length17–290
Running at oncepinned at 86 / 11 (room)
Monitor skips6 per 10 min1 per 10 min
Load average1.621.24
Memory1,161 MB667 MB

With 11 slots the queue was 0 and load and memory fell. Most jobs only wait for network replies and use no CPU. The cap was the slots, not the CPU.

The slot value lives only in a server settings file (runner.env) and never enters git, because the deploy script does not send it. Looking at the repository would not show this change, so I wrote it down and kept a backup of the old value.

“Only 2 cores, so no more” was half wrong

Later I added a lane for popular sets and a fastest lane. Concurrency pinned at 11, the queue grew to 15 and the monitor was skipped twice (effective interval 1.0 to 1.4 minutes).

At the time I concluded “with 2 cores, widening the slots would just slow everything” and reduced the Rakuten popular lanes.

After addingAfter reducing
Concurrencypinned at 119–11
Queueup to 150–1
Monitor skips2 per 10 min0
Monitor effective interval1.4 min1.0 min
Load1.661.25

That conclusion turned out half wrong. The Rakuten jobs holding slots are asleep on the API wait and use no CPU. More slots only means “more can sleep at once”, not more CPU contention. I measured again with 11 and 14:

11 slots14 slots
Monitor skips1 per 5 min0 per 6.7 min
Effective interval1.3 min1.0 min
Load1.251.25 (unchanged)

The deciding question: CPU-bound or waiting?

Two places to look: the queue length (queued in the health check; if it is always at least 1 there is no spare), and the average run time per job, longest first. If long Rakuten-API jobs top the list, they are the ones sleeping on slots.

That day I made the same regression four times: Amazon every 5 minutes, Amazon-like store every 5 minutes, batched Rakuten popular lanes, Rakuten popular lanes every 10 minutes. Each time I meant to speed up and instead ate slots and slowed the one I cared about.

What I learned

Do not count slots; look at what holds them.

This is the English version of the original Japanese article.

More in English