Skip to content

Tenant quotas

Each tenant has its own limits: quotas on how much work it may do, and size limits on how large its deployments, variables and requests may be. You set them when you create the tenant and change them at any time through the tenant API (PUT /v2/tenants/{tenantId} with a quotas or a limits object; see Managing tenants); the console’s Tenants area shows and changes the quotas. A change takes effect without a restart, on every node, for the next request. A new tenant starts with no quotas until you set some: a quota that is not set is left out of the tenant’s quotas, and the console shows it as No limit.

The limits are enforced exactly: all of a tenant’s work runs in its home partition, which keeps the tenant’s counts in memory and checks each command against them before it is applied.

FieldWhat it limits
activeInstanceLimitProcess instances of the tenant running at the same time. Only new instances created through the API are refused; instances started inside a process (by a call activity, or by a message, signal or timer start event) count towards the total but are never refused
createsPerSecNew process instances per second
jobsPerSecJobs handed to workers per second
feelBudgetThe work one expression evaluation may do
timerArmRateTimers fired per second. Timers over the rate fire a little later; nothing fails
broadcastAdmissionSignal broadcasts per second
mailboxBoundRequests of the tenant waiting in its partition to be carried out, across all its instances: when that many are already waiting, the next one is refused. It protects the partition’s other tenants from a burst
weightNot a limit: the tenant’s share of its partition’s processing time when several tenants are busy at once. A tenant with weight 2 gets twice the time of a tenant with weight 1. Default 1

Every value is a whole number; weight is at least 1. A request that names an unknown field, or a negative number, is refused and changes nothing.

Terminal window
curl -X PUT https://bpm.example.com/v2/tenants/acme \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"quotas": {"activeInstanceLimit": 10000, "createsPerSec": 500, "jobsPerSec": 1000}}'

Apart from the two exceptions above, a command that would go over a limit is refused and changes nothing. It answers 429 with the problem type urn:bpm:error:quota-exhausted, a detail that names the limit, and a Retry-After header in whole seconds.

A signal or message that matches many waiting instances reaches all of them in one command. The tenant’s activeInstanceLimit bounds how many that can be, and broadcastAdmission how often it can happen.

Lowering a limit below current usage does not stop running instances. It blocks new instances until enough running ones finish and usage is below the new limit.

To see how close a tenant is to its activeInstanceLimit, read the tenant (GET /v2/tenants/{tenantId}, or the tenant search): runningInstances is how many of its instances are running now, call-activity children included, as the reporting tables count them. It can trail the engine by a moment, so it can briefly differ from the count the limit is checked against. The console’s Tenants list shows it as Running, next to the Limit. Embedded mode answers null.

Every tenant also has three size limits, in the limits object of the same request. Unlike the quotas they always have a value: a new tenant gets the engine’s own limits.

FieldWhat it limitsA new tenant
maxDeploymentBytesThe size of one deployment: its files and their names together4 MiB (4194304)
maxVariablesBytesThe variables one process instance holds, all its scopes together, each value counted as its compact JSON32 MiB (33554432)
maxBatchSizeHow many items one request may carry or ask for: the jobs one activation hands out, the files of one deployment or one document upload, the instructions of one modification or migration1,000

A size limit can only lower what the engine accepts anyway: at most 4 MiB and 100 files per deployment (see Request and model limits) and 32 MiB of variables per instance. A higher value is kept, but the engine’s own limit still applies.

What happens at a size limit:

  • A deployment larger than maxDeploymentBytes, or with more files than maxBatchSize, is refused while it is read, as soon as it goes over.
  • A command that would leave a process instance holding more variables than maxVariablesBytes is refused: starting an instance, setting variables, completing or failing a job or throwing an error with variables, publishing or correlating a message, broadcasting a signal, completing a user task, and modifying or migrating an instance. The check counts everything the command causes at once, including the steps the process takes right after it, such as the output mappings of the task it completes. Work the engine does later on its own, such as a timer firing, is bounded by the engine’s 32 MiB; past that, the instance gets an incident.
  • A job activation that asks for more jobs than maxBatchSize gets at most maxBatchSize of them; the rest are handed out on the next activation.
  • A document upload, or an instance modification or migration, with more items than maxBatchSize is refused.

A refused request answers 413 with the problem type urn:bpm:error:tenant-limit-exceeded and a detail that names the limit, for example the command would leave process instance 2251799813685251 with 40213 bytes of variables, more than the tenant’s limit maxVariablesBytes of 32768 bytes; nothing was changed. A refused request changed nothing: send it again once the limit is raised, or with less data.

Terminal window
curl -X PUT https://bpm.example.com/v2/tenants/acme \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"limits": {"maxVariablesBytes": 1048576, "maxBatchSize": 200}}'

A change names only the limits it changes, each a whole number of at least 1; an unknown field is refused and changes nothing. The new value applies to the next request on every node.

Lowering maxVariablesBytes below what running instances already hold does not stop them. They run on to their end, and a command that does not make their variables larger (a task completed without variables, a variable replaced by a smaller value, a cancellation) still applies. Only a command that would make such an instance hold more is refused.

Searches are not affected by maxBatchSize: each search has its own page limit.

The same page of the console, and the same request, also set how long the tenant’s history is kept (retention); see How long history is kept.