Concurrency control
Concurrency control prevents multiple workflow instances from running simultaneously, protecting shared resources and preventing conflicts.
Schema
See Schema Reference for the complete #Concurrency definition.
Fields
group (required)
Concurrency group identifier. Workflows with the same group cannot run concurrently.
Type: string (non-empty)
Supports expressions: Yes
Example:
concurrency:
group: production-deploy
With expressions:
concurrency:
group: train-${{ .inputs.model_type }}
cancel_in_progress (optional)
Controls behavior when a new workflow arrives while another is running in the same group.
Type: bool
Default: false
Values:
true: Cancel running workflow, start new one immediately.false: Queue new workflow (max 1 running + 1 pending, newer replaces pending).
Example:
concurrency:
group: model-training
cancel_in_progress: true
Behavior
Queue Mode (cancel_in_progress: false)
- Maximum: 1 running + 1 pending workflow.
- New arrivals replace pending workflow (keeps newest).
- When running completes, pending starts.
Queue timeout: A run does not wait in the queue indefinitely. A run that stays in STATE_QUEUED longer than the orchestrator's maximum queued duration (configurable via dispatch.maxQueuedDuration, default 3h; 0 disables the limit) is force-cancelled. Like a concurrency cancellation, this is recorded as a failed run (STATE_FAILED) with failure_reason = RUN_FAILURE_REASON_CANCELED.
Cancel Mode (cancel_in_progress: true)
- New workflow cancels running workflow.
- No queue — newest always runs.
Examples
Model Deployment
Ensure only one model deployment at a time:
id: deploy-model
concurrency:
group: production-deploy
jobs:
deploy:
steps:
- run: python deploy_model.py --env production
Per-Model Training
Allow concurrent training of different models, but serialize same-model training:
id: train-model
inputs:
model_type:
type: string
required: true
concurrency:
group: train-${{ .inputs.model_type }}
jobs:
train:
steps:
- run: python train.py --model ${{ .inputs.model_type }}
Experiment with Cancel
For experiments where only the latest hyperparameters matter:
id: hyperparameter-tuning
inputs:
experiment_id:
type: string
concurrency:
group: experiment-${{ .inputs.experiment_id }}
cancel_in_progress: true
jobs:
tune:
steps:
- run: python tune.py --experiment ${{ .inputs.experiment_id }}
Interaction with Other Features
cancel_on_failure: There is no distinct cancelled run state. A concurrency cancellation is recorded as a failed run (state STATE_FAILED) with failure_reason = RUN_FAILURE_REASON_CANCELED. The failure_reason is what distinguishes a cancellation from an ordinary failure, and cancellations do not trigger cancel_on_failure in other workflows.
Expressions: Concurrency groups support .inputs and .env expressions. .secrets references are rejected at validation time because group values are persisted and queried, so they must not carry secret material.
- Submit and view feedback for this page
- Send feedback about H2O Workflows to cloud-feedback@h2o.ai