> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revoengine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Job concurrency

> Limit simultaneous Job executions with a shared key and bounded waiting.

Protect a shared resource with a Job template concurrency limit. If two templates use the same key and a limit of two, they share those two slots. Additional Jobs wait for admission.

## Explore the behavior

### Six Jobs, limited capacity

`·   per key`

Next step

**O** Orders**I** InvoicesDashed boxes are available slots

**/ slots in use** ·  waiting ·  finished

<details>
  <summary>Change key or limit</summary>

  Limit per key
  Reset
</details>

Illustration of ordinary admission. A waiting Job has no slot and has not failed. The example steps do not specify timing or execution order.

## Configure the template

Set this object under the Job template's `options.concurrency`:

```json theme={null}
{
  "key": "warehouse_sync",
  "limit": 2,
  "retryDelaySeconds": 30
}
```

Set the same key and limit on every template that uses the warehouse account. In Job History, a Job waiting for capacity remains pending with a concurrency wait reason. Once capacity is available, it can execute without creating a retry child.

## Configuration reference

| Field | Type | Default | Meaning |
| - | - | - | - |
| `key` | string | No keyed admission | Shared bucket in the instance. Use letters, digits, underscores and hyphens. |
| `limit` | integer | 1 when a key is set | Maximum admitted executions; 1–1000. |
| `retryDelaySeconds` | integer | 30 | Delay before a waiting Job retries admission; 1–3600 seconds. |
| `ttl` | integer | Legacy preference | Accepted for compatibility; ordinary Jobs use a managed renewable lease. |

The key is a configured string. It is not an expression evaluated against each Event payload. Giving all account imports the literal key `accountId` puts them in one bucket; it does not create one bucket per account.

## Choose the key deliberately

Use the same key and limit on templates that must share capacity. Different keys create independent buckets. A key such as `warehouse_sync` communicates the protected system; a key named only after a template can accidentally let several templates overload that same system.

See [key design](https://docs.revoengine.com/patterns/coordination-keys.md) for the difference between capacity and duplicate protection.

## Waiting, retry and recovery

Waiting for capacity is separate from a Job's retry policy after terminal `ERROR`. Ordinary Job leases are managed while execution is active; raising legacy `ttl` does not extend an abandoned execution's permit. Operator force-run or configured automatic-retry bypass can intentionally skip template concurrency, so review those policies before treating the configured limit as unconditional.

This limit controls Job admission, not requests per second and not UI refresh ordering. For a bounded section of low-code, use [explicit concurrency admission](https://docs.revoengine.com/patterns/low-code-concurrency.md). See [Job history](https://docs.revoengine.com/operate/jobs.md) to inspect the wait reason and execution outcome.

## Example: serialize invoice work

The synthetic invoice pipeline uses `asterion_invoice_pipeline` and limit **1**. All Jobs using this same key share that slot: the key does not isolate each order. The pictured UI also shows a legacy TTL preference of **180 seconds**. Ordinary Jobs use the managed renewable lease described above; that field does not set their active lease duration. The separate execution timeout is **120 seconds**.

The retry policy allows **3 total attempts**, starts with a **5-second** minimum backoff and caps it at **60 seconds**. **Skip concurrency** is off, so a retry still competes for the template's slot. These sample values are configuration choices, not universal defaults or a timing guarantee.

![Invoice Job with shared concurrency key, limit one, TTL 180 seconds and three total retry attempts](https://mintcdn.com/revoengine/njykHfc8fKjssLB-/images/asterion/job-concurrency-retry.jpg?fit=max\&auto=format\&n=njykHfc8fKjssLB-\&q=85\&s=5d997151b0b779ccfa5550122c724294)

Concurrency controls overlap; retry controls later attempts after failure. Neither guarantees one business effect.

<details>
  <summary>Read screenshot at full size</summary>

  Scroll horizontally and vertically to read the original detail, or [open the original image](https://docs.revoengine.com/images/asterion/job-concurrency-retry.jpg). Keyboard users can focus the image area and use the arrow keys.

  ![Invoice Job with shared concurrency key, limit one, TTL 180 seconds and three total retry attempts](https://docs.revoengine.com/images/asterion/job-concurrency-retry.jpg)
</details>

For per-customer isolation, deliberately choose a key containing that customer's stable business identity in a supported keyed execution path. For one invoice per order, also use a unique business key and recover the existing invoice receipt; a different concurrency key alone cannot prevent duplicates.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.