---
title: Concurrency limits
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > Concurrency limits
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# Concurrency limits

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `cicd-github-concurrency-limits` 

**Provider:** GitHub

**Platform:** CICD

**Severity:** Low

**Category:** Best Practices

#### Learn More{% #learn-more %}

- [Provider Reference](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)

### Description{% #description %}

Workflows and jobs without concurrency controls can pile up redundant, overlapping runs that waste CI/CD compute, lengthen queue times, and delay feedback when commits or pull request updates land in quick succession. Set the `concurrency` property to an object with a `group` and an explicit `cancel-in-progress` value, so the behavior for overlapping runs is a deliberate choice rather than an implicit default.

Use `cancel-in-progress: true` where only the latest commit matters, such as pull request builds, tests, and linting. GitHub then cancels the in-progress run for the same concurrency group instead of running duplicates. Use `cancel-in-progress: false` for workflows that must not be interrupted mid-flight, such as deployments and release publishing, where new runs should queue behind the current one. This rule accepts either value.

The rule flags workflows or jobs that omit `concurrency` entirely, set it to a bare string, or provide a `group` with no `cancel-in-progress` key at all. Reusable-only workflows, meaning those triggered solely by `workflow_call`, are exempt because their callers should define concurrency to avoid deadlocks and premature cancellations.

Secure configuration example:

```yaml
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
```

## Compliant Code Examples{% #compliant-code-examples %}

```yaml
# Workflow with proper concurrency control
name: Workflow with Concurrency Control
on: pull_request

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test
---
# Reusable workflow (should be skipped)
name: Reusable Workflow
on: workflow_call

concurrency:
  group: reusable-${{ github.ref }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm build
---
# Job-level concurrency with cancel-in-progress
name: Job Level Concurrency
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    concurrency:
      group: test-${{ github.ref }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v4
      - run: npm test
---
# Reusable workflow call (should be skipped)
name: Workflow Calling Reusable
on: push

concurrency:
  group: caller-${{ github.ref }}
  cancel-in-progress: true

jobs:
  call-reusable:
    uses: ./.github/workflows/reusable.yml
---
# Deploy workflow explicitly opting out of cancellation
name: Deploy Application
on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-deploy-${{ github.ref }}
  cancel-in-progress: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh
---
# Job-level concurrency explicitly opting out of cancellation
name: Job Level Deploy
on: push

jobs:
  deploy:
    runs-on: ubuntu-latest
    concurrency:
      group: deploy-${{ github.ref }}
      cancel-in-progress: false
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```yaml
name: Workflow without Cancel in Progress
on: pull_request

# Workflow-level concurrency without cancel-in-progress
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test
---
# Job-level concurrency without cancel-in-progress
name: Job Level Concurrency
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    concurrency:
      group: test-${{ github.ref }}
    steps:
      - uses: actions/checkout@v4
      - run: npm test
---
# Missing concurrency at both levels
name: No Concurrency
on: pull_request

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run deploy
```

```yaml
# String-based concurrency (bare string, no cancel-in-progress)
name: String Concurrency
on: push

concurrency: ci-${{ github.ref }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm build
```
