<@ULVA73B9P> can I have two different process work...
# ask-marvin
a
@Marvin can I have two different process workers connected to the same work pool and explicitly send a flow to a chosen worker? is this what I can use work queues for?
m
thought for 182.5 seconds
Yes — multiple process workers can poll the same work pool. But no — you generally cannot explicitly send a flow run to one named worker. How it works - A work pool is the main routing target for a deployment - A worker polls that pool for available work - A work queue is a subdivision inside the pool that helps with routing by queue, priority, and concurrency So the practical model is: - deploy flow -> work pool (+ optionally a work queue) - workers subscribe to that pool, optionally limited to specific queues - whichever eligible worker picks up the run first executes it So are work queues what you want? Yes, if your goal is to steer runs to a class/group of workers. No, if your goal is “run this on worker-A specifically.” Work queues let you do things like: - worker 1 listens only to
queue-a
- worker 2 listens only to
queue-b
- deployment X submits to
queue-a
- deployment Y submits to
queue-b
That gives you indirect targeting. Example:
Copy code
bash
prefect worker start --pool my-pool --work-queue queue-a
prefect worker start --pool my-pool --work-queue queue-b
Then configure deployment A to use
queue-a
, deployment B to use
queue-b
. Important caveat If two workers listen to the same queue, you are not guaranteed which one will pick up a given run. It’s effectively first-available / first-to-claim. So if you need deterministic routing: - use different queues, and/or - use different work pools Recommended pattern If your intent is something like: - one worker on machine A - one worker on machine B - certain flows must go to A, others to B then use either: 1. One work pool, multiple work queues - worker A ->
queue-a
- worker B ->
queue-b
or 2. Separate work pools -
pool-a
-
pool-b
Separate pools are often cleaner if the infrastructure/environment is meaningfully different. CLI reference Worker startup supports binding to a pool and queue(s):
prefect worker start --help
Docs: - Work pools - Workers - Work queue management If you want, I can also show you exactly how to configure a deployment to land on a specific work queue in
prefect.yaml
or in Python.
a
@Marvin thanks. having worker A listening on queue A is acceptable for our infra setup. We don't plan to have two different workers listening on the same queue (or if we do, then we accept that tasks could go to either worker)
m
thought for 4.7 seconds
That sounds like a good fit. If your setup is: - worker A -> listens only on
queue-a
- worker B -> listens only on
queue-b
then assigning a deployment to
queue-a
is a reasonable way to make sure it runs on worker A’s infrastructure. And yes, your understanding is correct: - one worker per queue -> effectively deterministic routing - multiple workers on the same queue -> any of those workers may pick up the run A couple practical notes: - Keep both workers in the same work pool if the only difference is routing - Use different work pools if the base infrastructure or job template differs substantially - Queue-based routing is a normal pattern in Prefect 3.x If you want, I can give you a minimal example of: 1. creating the queues, 2. starting each worker against its queue, and 3. assigning a deployment to the right queue in
prefect.yaml
or Python.
a
@Marvin is there a way to ask the currently running process worker to shut down? ideally with a submitted command. the extreme would be a flow which is just kill(mypid), but a nicer method would be better
m
thought for 152.4 seconds
Short answer: not through Prefect itself. There is not a supported “submit a command to this worker and have it shut itself down” feature for process workers in Prefect 3.x. What is supported: 1. OS-level signals to the worker process -
SIGTERM
/
SIGINT
for graceful shutdown - the worker stops polling and lets active runs finish 2. Pausing the work pool - prevents workers in that pool from picking up new runs - does not stop the worker process itself So the nicest built-in pattern is usually: - pause the pool (or otherwise stop new work from arriving) - send
SIGTERM
to the worker process from your process manager / host environment Example:
Copy code
bash
prefect work-pool pause my-pool
kill -TERM <worker-pid>
CLI reference: - Work pools - Workers I also verified the pause command exists:
Copy code
bash
prefect work-pool pause my-pool
About “a flow that kills its own worker” Technically, yes, a flow could do something crude like
os.kill(...)
if it can discover the right PID and has permission, but I would not recommend that pattern: - brittle - tightly couples flow code to worker process internals - easy to kill the wrong process - not a Prefect-supported lifecycle mechanism Also, a flow run is not given an official “shutdown my worker” API. Recommended approaches If you want a worker to terminate after some condition, better options are: - run the worker under systemd, Docker, Kubernetes, supervisord, etc. - have that supervisor decide when to stop/restart it - optionally pause the pool first so no new work is claimed If your goal is “worker A should do one thing, then go away”, you might also consider: - launching the worker externally for a bounded period - or using
--run-once
-style behavior if your workflow fits that model If you want, I can help sketch a safe self-draining pattern for your setup, e.g.: - worker listens on queue A - flow requests drain - external controller notices and sends
SIGTERM
- worker exits after current run completes That’s usually the cleanest approximation of “remote shutdown.”
a
@Marvin our use-case is that we want to create an ad-hoc worker session as an ECS task that is live for the duration of the session. We have an MCP where the operator is interactively triggering tasks. While we can have the mCP shut down the task when we're finished, we also want a timeout so that we don't leave unused resources running. We're currently thinking of an EventBridge schedule which shuts down the ECS task on a schedule; and update the schedule time each time a new command/task is received
m
thought for 17.1 seconds
Yes — that sounds like a reasonable architecture, and it’s probably a better fit than trying to make the Prefect process worker self-terminate. For your use case, I’d think of Prefect as handling work execution, while ECS/EventBridge handles worker lifecycle. Your proposed pattern makes sense - start an ad hoc ECS task running a worker - operator interacts through your MCP - each interaction extends the session expiry - EventBridge (or equivalent) shuts down the ECS task after inactivity That avoids depending on any unsupported “remote shutdown this worker” feature. Why this is a good fit A Prefect worker is just a polling process. It does not have a native session TTL / idle timeout control exposed through Prefect. Since your worker itself is an ECS task, ECS is the natural control plane for: - startup - shutdown - max session lifetime - idle timeout enforcement So yes: external lifecycle management is the right approach here. One important nuance If you hard stop the ECS task while a flow run is still executing, that run may be interrupted abruptly. So if possible, make your timeout controller a little smarter: 1. First drain the worker - prevent new work from landing on that worker - for your setup, that likely means pausing the queue/pool or otherwise ensuring no further commands target it 2. Then stop the ECS task - preferably after confirming there is no active run in progress Because you mentioned ad hoc worker session, I suspect you may have a dedicated queue per session or at least per worker session. If so, that is ideal. Recommended session model A clean pattern would be: - create a dedicated work queue for the session, e.g.
session-abc123
- start one ECS worker task listening only on that queue - deployments / triggered runs for that session target only that queue - every operator action updates a TTL record - an external reaper checks TTL expiry - on expiry: - stop sending work to that queue - optionally pause the queue/pool or mark session closed in your app - wait for any active run to finish - stop the ECS task - optionally delete the queue if it was ephemeral This gives you deterministic routing and a nice cleanup boundary. About EventBridge schedule per interaction That can work, but I’d consider whether a single periodic reaper is simpler than constantly updating schedules. Two possible designs: Option A: reschedule EventBridge every interaction - on each command, push expiry out by N minutes - EventBridge fires at expiry and stops the ECS task Pros: - direct - low conceptual overhead Cons: - more moving pieces - repeated schedule mutation - possible race conditions around updates near firing time Option B: periodic sweeper / reaper - store
last_activity_at
or
expires_at
somewhere durable - run a small periodic checker every minute - checker stops any ECS worker session whose
expires_at < now
and is idle Pros: - simpler state model - easier to reason about - better if you’ll have many concurrent sessions - easier to add “don’t kill if run is active” Cons: - timeout precision is to the polling interval, not exact second For most session systems, Option B is usually more robust. Very important design point: how do you know whether it is safe to stop? You’ll want your controller to know at least: - ECS task ID / ARN for the worker session - associated Prefect work pool + queue - session expiry time - whether a flow run is currently active If you can detect active work, then your shutdown logic becomes: - if expired and idle -> stop ECS task now - if expired and busy -> mark draining, then stop after completion How to make “draining” work well Since Prefect does not let you stop a single worker via API, draining usually means preventing more work from being submitted to that session.
In your case, the MCP likely controls task submission already, so you may not even need Prefect-side pause semantics. Your app can simply decide: - session expired -> do not submit more runs to that queue Then once the in-flight run finishes, terminate the ECS task. That may be cleaner than pausing the entire work pool, especially if other session workers share the same pool. If multiple sessions share one work pool Be careful with
prefect work-pool pause
because it affects the whole pool, not just one session worker. In your architecture, that suggests: - don’t use work-pool pause for per-session draining if many sessions share the pool - instead use: - one queue per session, and - application-level routing control, and - ECS stop logic per session That seems much more aligned with your goal. Practical recommendation Given what you described, I would recommend: - one shared work pool for this worker type - one dedicated work queue per ad hoc session - one ECS worker task per session listening only to that queue - MCP tracks
expires_at
- periodic reaper checks for expired sessions - if expired: - block new submissions for that session - if no active flow run, stop ECS task - if active flow run, wait and stop when complete That’s a solid design. When to use EventBridge schedule mutation anyway If you only ever have a small number of sessions and you already have scheduling logic in place, your current plan is perfectly acceptable. I’d just add protections for: - schedule fires while a run is still active - operator sends a new command right as the shutdown fires - ECS task is already gone - Prefect run is stuck / long-running Bottom line Yes — using ECS/EventBridge to enforce worker session timeout is a good approach, and likely the right one. If you want the most robust version, I’d lean toward: - session-specific queues - application-managed expiry state - periodic reaper instead of constantly rewriting EventBridge schedules If you want, I can help you design the exact control flow for: 1. session startup, 2. run submission to the right queue, 3. idle timeout extension, and 4. safe shutdown of the ECS worker task.