Task queues
Background jobs delivered back to your own endpoint by Cloud Tasks, at a rate you declare - for work too long for one request, like sending a campaign page by page.
Background work delivered back to your own endpoint by Google Cloud Tasks, without holding a GCP credential.
When to use it
For work too long for one request - sending a campaign to 25,000 contacts, rebuilding a report, a long import. Split it into steps that each finish well inside a minute, and have each step enqueue the next. Do not put anything a person is waiting on through a queue: a sign-in code or a payment receipt is sent in the request that triggers it.
How it fits together
| Step | Who | What |
|---|---|---|
| Declare | Console | A queue: its name, the URL it delivers to, its rate and its retries. A queue that is not declared does not exist. |
| Enqueue | Your backend | POST /tasks with your API key - a workspace, a queue, a JSON payload, optionally a dedup name and a scheduleAt. |
| Deliver | Cloud Tasks | POSTs { workspaceId, queue, payload } to the declared URL with a Google-signed OIDC token. |
| Run | Your endpoint | Verify the token, do one step, enqueue the next, answer 2xx. Anything else is retried with backoff. |
The rate is the application's, not a workspace's
A queue is shared by every workspace you serve, and its declared rate caps all of them together. Fairness comes from the shape of the work: a job that holds one task in flight at a time (do a step, enqueue the next) interleaves with every other tenant's instead of queuing behind it. Enqueuing a thousand tasks for one tenant up front is how one customer's campaign delays everyone else's.
Deliveries are at least once
A task can arrive twice - a retry after a timeout that had in fact succeeded. Make every step safe to run again: derive ids from the step (campaign-42-page-3), and name the task the same way so a second enqueue of the same step answers duplicate rather than queuing it twice.
Verifying a delivery
Check the bearer token's signature against Google's keys, that email is the Connect invoker account the platform gives you, and that aud is your own origin - in that order, and before reading the body. verifyConnectTask(request) in @cosmoops/connect-sdk/server does all three. An unverified request on this URL is somebody else's.
Local development
A deployment with no task queue answers status: "unavailable", and nothing is queued. Keep a fallback - a scheduled sweep that does the same step - so work still moves where Cloud Tasks cannot reach you.
Endpoints
POST /api/v1/application/tasks
Enqueue a background task
Scope tasks:write · Rate limit 600 requests / min per API key
Put one task on a queue your application declared in Console, for a workspace that subscribes to you. Cloud Tasks then POSTs { workspaceId, queue, payload } to the queue's declared URL, carrying a Google-signed OIDC token, at the queue's declared rate.
You choose the payload and, optionally, when - never where: the URL is the queue's, on an origin you registered. workspaceId in the delivery is the one this call was gated on, whatever your payload says.
Dedup with name
A second enqueue with the same name for the same workspace answers status: "duplicate" and queues nothing. Name a self-chaining step after the step itself (campaign-42-page-3) and two runners racing to queue it produce one task. A name stays taken for a while after its task runs, so never reuse one for different work.
unavailable is not an error
A deployment with no task queue configured (local development) answers 200 with status: "unavailable". Fall back to whatever you would do without a queue.
Errors
validation_error (400 - an undeclared queue, a scheduleAt more than 30 days out, or a payload over 100 KB), conflict (409 - the queue's URL is no longer on a registered origin), forbidden (403 - key unknown, missing tasks:write, or that workspace does not subscribe to your application), unavailable (503 - the queue is declared but not provisioned yet; retry).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
queue | string | yes | |
payload | any | no | |
name | string | no | |
scheduleAt | date-time | no |
Responses
| Status | Meaning |
|---|---|
200 | Queued, a duplicate, or unavailable here |
400 | validation_error |
403 | forbidden |
409 | conflict |
429 | rate_limited |
503 | unavailable |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
status | queued | duplicate | unavailable | yes | |
scheduleAt | any | yes |
Push notifications
Put a notification on a member's lock screen. Connect holds the VAPID keys, the devices and the member's own preferences - your application supplies a title, a body and a path.
Workspaces
Which workspaces the signed-in user belongs to, switching between them, and who else is on the team.