Skip to main content
By default every worker serves every project from one shared queue. When one busy project floods it, everyone else waits. Worker groups fix that. A group is a named pool of workers with its own dedicated queue. Assign a project to a group and its runs get reserved workers no other project can take. Worker groups: projects map to dedicated queues, each backed by its own reserved worker pool, while ungrouped projects share a best-effort queue

Floor vs. ceiling

  • A worker group is a floor: capacity reserved for a project that nobody else can use.
  • A soft cap is a ceiling: an optional per-project limit on how much a project can use. See Manage Concurrency for details.
Use both together to guarantee capacity for busy projects and cap the rest.

How it works

A worker joins a group by setting its group ID at startup. AP_WORKER_GROUP_SCOPE selects the group’s scope:
  • Project group — AP_WORKER_GROUP_SCOPE=project (the default). Assign individual projects to it from Platform Admin → Operations → Workers → Worker groups.
  • Flow group — AP_WORKER_GROUP_SCOPE=flow. Pins individual flows to it, regardless of which group (if any) their project is in. See Assigning flows to a group.
  • Platform group — AP_WORKER_GROUP_SCOPE=platform (or the legacy AP_PROJECT_WORKER=false). Serves the whole platform’s runs; used for dedicated/canary fleets.
A group’s scope is fixed by whichever scope its workers connect with — a label can’t take both project and flow assignments at once, so give project and flow pools distinct AP_WORKER_GROUP_ID values.
AP_PROJECT_WORKER (true/false) still works as the legacy project-vs-platform toggle, but AP_WORKER_GROUP_SCOPE is the current setting and the only way to request the flow scope.
Grouped workers must set:
Routing runs to worker group queues is done by the project rate limiter, so the app server must run with AP_PROJECT_RATE_LIMITER_ENABLED=true. Without it, assigned projects keep using the shared queue and grouped workers stay idle.
Once a project is assigned to a group, its flow and webhook runs are routed to that group’s dedicated queue (project-<group-name>-jobs) and picked up only by workers carrying the matching AP_WORKER_GROUP_ID with scope project. If no worker in the group is online, runs wait in the group queue until one connects — they are never executed by shared workers. Changing a project’s assignment — to a group, between groups, or back to shared — also moves its waiting runs to the new queue. Projects without a group keep drawing from the shared queue. A flow pinned to a group works the same way, but on its own queue (flow-<group-name>-jobs), picked up only by workers with scope flow. A flow’s own pin always wins over its project’s group — pin a flow to send just that flow’s runs elsewhere without moving the rest of the project.

Assigning projects to a group

You can assign a project to a project group in two ways:
  • UI — go to Platform admin → Operations → Workers → Worker groups (/platform/workers/groups) and pick the group for each project.
  • API — set workerGroupId on the project via the projects API. Use the bare group name (the same value as the group’s AP_WORKER_GROUP_ID); pass null to unassign and return the project to the shared queue.
The same request also sets maxConcurrentJobs — the project’s concurrency limit (the soft-cap ceiling). It’s the maximum number of flow runs the project executes at once:
  • Omit it (or send null) and the project uses the default: min(plan limit, group slots) — i.e. it can use the group’s full reserved capacity, up to the plan’s limit.
  • Set a number to cap the project below that. The value is clamped to the group’s slot count (a project can’t run more concurrently than its pool can serve).

Assigning flows to a group

Pin individual flows to a flow group when only a few flows — not their whole project — need dedicated capacity (more memory, a GPU, a specific region). A pinned flow’s runs route to that group even if its project is on the shared queue or assigned elsewhere; unpin it and the flow falls back to its project’s group, or the shared queue.
  • UI — go to Platform admin → Operations → Workers → Worker groups (/platform/workers/groups), open a flow group, and add flows to it by searching across projects.
  • API — POST /v1/worker-groups/assignments/flows with a platform API key:
Pass workerGroupId: null to unpin flows and return them to their project’s group. If workers are currently online under that group label with the project scope, assigning a flow to it is rejected — a label serves one scope at a time.