---
type: api
title: Throttle a reindex operation
description: Change the maximum number of documents to index per second for a particular reindex operation.
url: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/elasticsearch/v9/operation/operation-reindex-rethrottle
resource: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/elasticsearch/v9/operation/operation-reindex-rethrottle
products:
  - Elasticsearch
---

# Throttle a reindex operation

Availability: 2.4+

## Paths

- `POST` `/_reindex/{task_id}/_rethrottle`

- [Api key auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/v9/authentication#apikeyauth)
- [Basic auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/v9/authentication#basicauth)
- [Bearer auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/v9/authentication#bearerauth)

#### Path Parameters

- `task_id` (string Id)
  The task identifier, returned when creating a reindex task, or by listing tasks via
`GET /_reindex` or `GET /_tasks`.
In stack, can be either the original task ID or the task ID of the relocated task.

## Description

Change the maximum number of documents to index per second for a particular reindex operation.
For example, to unthrottle to unlimited documents per second:

```
POST _reindex/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1
```

Rethrottling that speeds up the query takes effect immediately.
Rethrottling that slows down the query will take effect after completing the current batch of documents.
This behavior prevents scroll timeouts.

This API follows reindex tasks across node-shutdown relocations, so callers can keep using
the original task ID throughout the lifetime of the operation.
The relocated task ID is also accepted and is followed transparently.
In either case, returned task IDs and timings reflect the original task, not its relocated successor.

The rethrottle may not have been applied to any tasks if either `node_failures` or `task_failures` are non-empty, or if the response contains
no successfully rethrottled tasks — that is, no entries under `nodes` (returned with the default
`group_by=nodes` in stack) or under `tasks` (returned in serverless, or in stack with
`group_by=none` or `group_by=parents`).

## Query String Parameters

- `requests_per_second` (number)
  The maximum number of documents to index per second, across the entire reindex operation (including slices).
It can be either `-1` to turn off throttling or any decimal number like `1.7` or `12` to throttle to that level.
- `group_by` (enum GroupBy · default: nodes)
  The way to group the tasks in the response.
We recommend setting this to `none`, which provides the cleanest response format.

Supported values include:
  - `nodes`: Group tasks by node ID.
  - `parents`: Group tasks by parent task ID.
  - `none`: Do not group tasks.
  Values: `nodes`, `parents`, `none`

## Response

`application/json`

- `node_failures` ([] ErrorCause)
  Node-level failures encountered while applying the rethrottle request.
Will return a `failed_node_exception` wrapping a `no_such_node_exception`,
if a node handling the task either never existed, or has left the cluster, and one of the following is true:
1. The task has completed.
2. The task cannot be found.

Note: Rethrottle handles relocations, so it should succeed if the task can be found and has not completed.
  - `type` (string)
    The type of error
  - `reason` (union string) — nullable
    A human-readable explanation of the error, in English.
    One of: `string`
  - `stack_trace` (string)
    The server stack trace. Present only if the `error_trace=true` parameter was sent with the request.
  - `caused_by` ({} ErrorCause) — recursive
    Same fields as `node_failures`
  - `root_cause` ([] ErrorCause) — recursive
    Same fields as `node_failures`
  - `suppressed` ([] ErrorCause) — recursive
    Same fields as `node_failures`
- `task_failures` ([] TaskFailure)
  Per-task failures encountered while applying the rethrottle.
If a rethrottle is attempted during a relocation handoff, the failure object reports `status: SERVICE_UNAVAILABLE` (the HTTP response itself is still `200 OK`).
In this case, the request can be retried until success.
  - `task_id` (number)
  - `node_id` (string)
  - `status` (string)
  - `reason` ({} ErrorCause)
    - `type` (string)
      The type of error
    - `reason` (union string) — nullable
      A human-readable explanation of the error, in English.
      One of: `string`
    - `stack_trace` (string)
      The server stack trace. Present only if the `error_trace=true` parameter was sent with the request.
    - `caused_by` ({} ErrorCause) — recursive
      Same fields as `reason` in `task_failures`
    - `root_cause` ([] ErrorCause) — recursive
      Same fields as `reason` in `task_failures`
    - `suppressed` ([] ErrorCause) — recursive
      Same fields as `reason` in `task_failures`
- `nodes` (map string to ReindexNode)
  Tasks grouped by node, returned only when `group_by=nodes` (the default).
  Map values ({} ReindexNode)
  - `attributes` (map string to string)
  - `host` (string)
  - `ip` (string)
  - `name` (string Name)
  - `roles` (NodeRoles)
    Values: `master`, `data`, `data_cold`, `data_content`, `data_frozen`, `data_hot`, `data_warm`, `client`, `ingest`, `ml`, `voting_only`, `transform`, `remote_cluster_client`, `coordinating_only`
  - `transport_address` (string)
  - `tasks` (map string to ReindexTask)
    Map values ({} ReindexTask)
    - `action` (string)
    - `cancellable` (boolean)
    - `cancelled` (boolean)
    - `description` (string)
    - `id` (number)
    - `node` (string Name)
    - `running_time_in_nanos` (DurationValueUnitNanos)
    - `start_time_in_millis` (EpochTimeUnitMillis)
    - `status` ({} ParentReindexStatus)
      - `slices` ([] ReindexStatus)
        - `slice_id` (number)
          The slice ID
        - `batches` (number)
          The number of scroll responses pulled back by the reindex.
        - `created` (number)
          The number of documents that were successfully created.
        - `deleted` (number)
          The number of documents that were successfully deleted.
        - `noops` (number)
          The number of documents that were ignored because the script used for the reindex returned a `noop` value for `ctx.op`.
        - `requests_per_second` (number)
          The number of requests per second effectively executed during the reindex.
        - `retries` ({} Retries)
          The number of retries attempted by reindex. `bulk` is the number of bulk actions retried and `search` is the number of search actions retried.
          - `bulk` (number)
            The number of bulk actions retried.
          - `search` (number)
            The number of search actions retried.
        - `throttled` (string Duration)
        - `throttled_millis` (DurationValueUnitMillis)
          Number of milliseconds the request slept to conform to `requests_per_second`.
        - `throttled_until` (string Duration)
        - `throttled_until_millis` (DurationValueUnitMillis)
          This field should always be equal to zero in a `_reindex` response.
It only has meaning when using the Task API, where it indicates the next time (in milliseconds since epoch) a throttled request will be executed again in order to conform to `requests_per_second`.
        - `total` (number)
          The number of documents that were successfully processed.
        - `updated` (number)
          The number of documents that were successfully updated, for example, a document with same ID already existed prior to reindex updating it.
        - `version_conflicts` (number)
          The number of version conflicts that reindex hits.
        - `cancelled` (string)
          The reason for cancellation if the slice was canceled
      - `slice_id` (number)
        The slice ID
      - `batches` (number)
        The number of scroll responses pulled back by the reindex.
      - `created` (number)
        The number of documents that were successfully created.
      - `deleted` (number)
        The number of documents that were successfully deleted.
      - `noops` (number)
        The number of documents that were ignored because the script used for the reindex returned a `noop` value for `ctx.op`.
      - `requests_per_second` (number)
        The number of requests per second effectively executed during the reindex.
      - `retries` ({} Retries)
        The number of retries attempted by reindex. `bulk` is the number of bulk actions retried and `search` is the number of search actions retried.
        - `bulk` (number)
          The number of bulk actions retried.
        - `search` (number)
          The number of search actions retried.
      - `throttled` (string Duration)
      - `throttled_millis` (DurationValueUnitMillis)
        Number of milliseconds the request slept to conform to `requests_per_second`.
      - `throttled_until` (string Duration)
      - `throttled_until_millis` (DurationValueUnitMillis)
        This field should always be equal to zero in a `_reindex` response.
It only has meaning when using the Task API, where it indicates the next time (in milliseconds since epoch) a throttled request will be executed again in order to conform to `requests_per_second`.
      - `total` (number)
        The number of documents that were successfully processed.
      - `updated` (number)
        The number of documents that were successfully updated, for example, a document with same ID already existed prior to reindex updating it.
      - `version_conflicts` (number)
        The number of version conflicts that reindex hits.
      - `cancelled` (string)
        The reason for cancellation if the slice was canceled
    - `type` (string)
    - `headers` (HttpHeaders)
- `tasks` (ReindexTasks)
  The tasks that were successfully rethrottled.
Always returned in serverless.
Returned with `group_by=none` or `group_by=parents` in stack.
## Code Examples

#### Console

```console
POST _reindex/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1
```

#### JavaScript

```javascript
const response = await client.reindexRethrottle({
  task_id: "r1A2WoRbTwKZ516z6NEs5A:36619",
  requests_per_second: "-1",
});
```

#### Python

```python
resp = client.reindex_rethrottle(
    task_id="r1A2WoRbTwKZ516z6NEs5A:36619",
    requests_per_second="-1",
)
```

#### curl

```curl
curl -X POST "$ELASTICSEARCH_URL/_reindex/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1" \
  -H "Authorization: ApiKey $ELASTIC_API_KEY"
```

#### Java

```java
client.reindexRethrottle(r -> r
    .requestsPerSecond(-1.0F)
    .taskId("r1A2WoRbTwKZ516z6NEs5A:36619")
);
```

#### C#

```c#
var response = await client
    .ReindexRethrottleAsync(taskId: "r1A2WoRbTwKZ516z6NEs5A:36619", d1 => d1
        .RequestsPerSecond(-1f)
    );
```

#### PHP

```php
$resp = $client->reindexRethrottle([
    "task_id" => "r1A2WoRbTwKZ516z6NEs5A:36619",
    "requests_per_second" => "-1",
]);
```

#### Ruby

```ruby
response = client.reindex_rethrottle(
  task_id: "r1A2WoRbTwKZ516z6NEs5A:36619",
  requests_per_second: "-1"
)
```

## Response Examples

#### Successful rethrottle

A successful response from `POST _reindex/{task_id}/_rethrottle?requests_per_second=10`. This is the response shape always returned in serverless, and in stack only when `group_by=none`. Task IDs and timings reflect the original task across node-shutdown relocations.

```json
{
  "tasks": [
    {
      "node": "r1A2WoRbTwKZ516z6NEs5A",
      "id": 36619,
      "type": "transport",
      "action": "indices:data/write/reindex",
      "status": {
        "total": 11500,
        "updated": 0,
        "created": 4000,
        "deleted": 0,
        "batches": 4,
        "version_conflicts": 0,
        "noops": 0,
        "retries": {
          "bulk": 0,
          "search": 0
        },
        "throttled_millis": 0,
        "requests_per_second": 10.0,
        "throttled_until_millis": 0
      },
      "description": "reindex from [my-source-index] to [my-dest-index]",
      "start_time_in_millis": 1762190000000,
      "running_time_in_nanos": 4200000000,
      "cancellable": true,
      "headers": {}
    }
  ]
}
```

#### Task ID's node is not in the cluster

A successful response from `POST _reindex/{task_id}/_rethrottle` when the task ID's node is not in the cluster (for example, the node was shut down without relocation, or the task ID was never valid). The empty `tasks` array and `failed_node_exception` wrapping a `no_such_node_exception` indicate the task is gone.

```json
{
  "node_failures": [
    {
      "type": "failed_node_exception",
      "reason": "Failed node [non_existing_node]",
      "node_id": "non_existing_node",
      "caused_by": {
        "type": "no_such_node_exception",
        "reason": "No such node [non_existing_node]",
        "node_id": "non_existing_node"
      }
    }
  ],
  "tasks": []
}
```

#### Rethrottle during relocation (HTTP 200)

While the HTTP status remains `200 OK`, a rethrottle sent during a node-shutdown relocation handoff can return `task_failures` with `status: SERVICE_UNAVAILABLE` and a `status_exception` cause. Retry with the same task ID; the retry follows the relocated task until it succeeds.

```json
{
  "task_failures": [
    {
      "task_id": 36619,
      "node_id": "r1A2WoRbTwKZ516z6NEs5A",
      "status": "SERVICE_UNAVAILABLE",
      "reason": {
        "type": "status_exception",
        "reason": "cannot rethrottle, task is being relocated"
      }
    }
  ],
  "tasks": {}
}
```

