Thousands of tokio tasks, and a design question

⚓ Rust    📅 2025-12-09    👤 surdeus    👁️ 1      

surdeus

Question 1: is it reasonable to run an unbounded collection of tokio tasks (with likely real-world task counts into the five figures), or should I keep the number of tasks limited in some way?

Question 2: is there a tidy way under tokio to start at most one instance of a job, if and only if that job isn't already running?


The background for this is that I'm building a chat service. One of the capabilities I'm exposing is that messages, conversations, and most other entities expire, and are then subsequently removed from the underlying data store. It's designed to run as a single process, so I can do this kind of data maintenance using background jobs.

I've got a fair bit of experience building multithreaded systems for this, and my intuition is that I should have a single "expiry worker" thread that can be notified when a new expirable thing is stored, and which then waits for each thing to expire before waking up and doing the work of marking it as deleted, publishing events to clients, or deleting it outright.

However, I'm less familiar with tokio's task model. The tokio introduction demonstrates using a separate task for each connection to a server, and furthermore suggests that developers should "feel free to spawn thousands, if not millions of tasks." That runs very much contrary to the above intuition, but it would be very convenient for me if that turns out to be true, as writing a task to wait and expire a single record is much easier than writing a task to monitor many expirable records at once.

Question one is motivated by wanting some outside reassurance, as I set about testing the "one task per expirable thing" approach myself, that I'm not wasting my time on something known not to work (or, conversely, that I'm doing something the framework supports well). Question two is motivated by the alternative: if I do have a single expiry task, I'd want it to stop when there are no more expirable things to process, and restart when an expirable thing is stored - but I don't want multiple expiry workers, really.

1 post - 1 participant

Read full topic

🏷️ Rust_feed