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

# Backfill permissions

A backfill reruns a Dag for a historical date range. On Astro Private Cloud (APC), the APC API issues a JWT for each user when they access the Airflow UI or API. The JWT carries the user's mapped Airflow role and the corresponding permissions. Airflow enforces backfill access against those permissions.

This page describes the APC-specific role mapping and how to grant, revoke, and audit backfill access. For general Airflow concepts, CLI flags, and UI behavior, see the related Astronomer Learn guides:

* [Rerun Airflow Dags and tasks (Airflow 2.x)](/docs/learn/2.x/rerunning-dags#backfill)
* [Rerun Airflow Dags and tasks (Airflow 3.x)](/docs/learn/rerunning-dags#backfill)

For general user role assignment outside the backfill scope, see [Manage users on Astro Private Cloud](/docs/astro-private-cloud/v-2-x/manage-platform-users) and the [User roles and permissions reference](/docs/astro-private-cloud/v-2-x/role-permission-reference).

## Permission model

### APC API deployment role to Airflow role

When a user opens the Airflow UI or API for a Deployment, the APC API maps the user's deployment-level role to an Airflow role and encodes the matching permission set in the JWT.

| APC API role        | Airflow role | Backfill access                    |
| ------------------- | ------------ | ---------------------------------- |
| `DEPLOYMENT_VIEWER` | Viewer       | `read`                             |
| `DEPLOYMENT_EDITOR` | User         | `read`, `create`, `edit`, `delete` |
| `DEPLOYMENT_ADMIN`  | Admin        | `read`, `create`, `edit`, `delete` |

<Note>
  A user with `WORKSPACE_ADMIN` on the parent Workspace, or `SYSTEM_ADMIN` at the system level, inherits Admin-equivalent backfill access on every Deployment in scope. You don't need to grant a deployment-level role on top.
</Note>

### Backfill actions

The `backfill` resource supports four actions.

| Action   | Description                                                 |
| -------- | ----------------------------------------------------------- |
| `read`   | View backfill status and history                            |
| `create` | Create new backfills                                        |
| `edit`   | Modify an existing backfill, such as pausing or resuming it |
| `delete` | Cancel a backfill                                           |

### How permission changes propagate

The APC API issues a JWT when the user accesses the Airflow UI. The JWT lifetime is controlled by the `jwt.authDuration` APC config and defaults to 24 hours. A role change takes effect when the APC API issues a new JWT, typically on the user's next sign-in or token refresh. Until then, the existing JWT continues to grant the previous permissions, so a role change can take up to 24 hours to reach an active session. To force the change immediately, have the user sign out and sign back in.

## Prerequisites

* The user has `DEPLOYMENT_EDITOR` or `DEPLOYMENT_ADMIN` on the target Deployment, or an inherited role from the Workspace or system level.
* The Dag exists and is unpaused.
* The target date range is valid for the Dag's schedule.

## Trigger a backfill

The trigger mechanism depends on the Airflow version running in your Deployment.

<Tabs>
  <Tab title="Airflow 2.x">
    Airflow 2 doesn't expose a backfill action in the UI. Use the Airflow CLI from a machine that can reach the Deployment.

    ```bash wrap theme={null}
    airflow dags backfill \
      --start-date 2026-01-01 \
      --end-date 2026-01-31 \
      --reset-dagruns \
      <dag-id>
    ```

    The `--reset-dagruns` flag deletes existing backfill-related Dag runs in the range and starts a fresh set. To rerun only failed tasks instead, use `--rerun-failed-tasks`. For a walkthrough with examples, see [Rerun Airflow Dags and tasks](/docs/learn/2.x/rerunning-dags#backfill).
  </Tab>

  <Tab title="Airflow 3.x">
    You can trigger an Airflow 3 backfill from the UI, the CLI, or the REST API.

    **Use the Airflow UI**

    <Steps>
      <Step title="Open the Dag's details">
        Navigate to the Dag in the Airflow UI and open its details page.
      </Step>

      <Step title="Trigger a backfill">
        Click **Trigger**, then select **Backfill** in the dialog.
      </Step>

      <Step title="Configure the run">
        Set the start date, end date, and reprocessing behavior, then submit.
      </Step>
    </Steps>

    **Use the Airflow CLI**

    ```bash wrap theme={null}
    airflow backfill create \
      --dag-id <dag-id> \
      --from-date 2026-01-01 \
      --to-date 2026-01-31 \
      --reprocess-behavior failed
    ```

    The `--reprocess-behavior` flag accepts `none`, `failed`, or `completed`. For a walkthrough with examples, see [Rerun Airflow Dags and tasks](/docs/learn/rerunning-dags#backfill).

    **Use the Airflow REST API**

    ```bash wrap theme={null}
    curl -X POST \
      "https://<deployment-url>/api/v2/backfills" \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "dag_id": "<dag-id>",
        "from_date": "2026-01-01T00:00:00Z",
        "to_date": "2026-01-31T00:00:00Z",
        "reprocess_behavior": "failed"
      }'
    ```

    This endpoint requires `backfill.create`, which `DEPLOYMENT_EDITOR` and `DEPLOYMENT_ADMIN` provide. For automated backfills triggered by CI or scheduled jobs, use a Deployment service account with `DEPLOYMENT_EDITOR` rather than a personal user token.
  </Tab>
</Tabs>

## Manage backfill access

Backfill access uses the standard APC role-assignment flow. For the full reference, see [Manage users on Astro Private Cloud](/docs/astro-private-cloud/v-2-x/manage-platform-users). The examples in this section show the calls scoped to backfill use cases.

### Grant or change a role

<Tabs>
  <Tab title="APC API">
    Use the `deploymentAddUserRole` GraphQL mutation to add a user, or `deploymentUpdateUserRole` to change an existing user's role.

    ```graphql wrap theme={null}
    mutation {
      deploymentAddUserRole(
        deploymentId: "<deployment-id>"
        email: "<user-email>"
        role: DEPLOYMENT_EDITOR
      ) {
        id
      }
    }
    ```

    Use `role: DEPLOYMENT_VIEWER` to restrict a user to read-only access instead.
  </Tab>

  <Tab title="Astro CLI">
    ```bash wrap theme={null}
    astro deployment user add \
      --deployment-id=<deployment-id> \
      --email=<user-email> \
      --role=DEPLOYMENT_EDITOR
    ```

    To change an existing user's role, use `astro deployment user update` with `--deployment-id` and `--role`.
  </Tab>
</Tabs>

### Restrict to read-only access

Use the same APC API or Astro CLI commands with `role: DEPLOYMENT_VIEWER` (or `--role=DEPLOYMENT_VIEWER`). The user can view backfill status and history but can't create, modify, or cancel backfills.

### Revoke access

To remove a user from the Deployment entirely, use the APC `deploymentRemoveUserRole` mutation or `astro deployment user remove`.

<Tabs>
  <Tab title="APC API">
    Use the `deploymentRemoveUserRole` mutation to remove a user from a Deployment entirely:

    ```graphql wrap theme={null}
    mutation {
      deploymentRemoveUserRole(
        deploymentId: "<deployment-id>"
        email: "<user-email>"
      ) {
        id
      }
    }
    ```

    After the role binding is removed, the user retains their previous access until their JWT expires (up to 24 hours by default).
  </Tab>

  <Tab title="Astro CLI">
    ```bash wrap theme={null}
    astro deployment user remove \
      --deployment-id=<deployment-id> \
      --email=<user-email>
    ```
  </Tab>
</Tabs>

After the role binding is removed, the user retains their previous backfill capabilities until their JWT expires. See [How permission changes propagate](#how-permission-changes-propagate).

## Monitor backfills

### Use the Airflow UI

Backfill runs appear in the Dag's run list with a `backfill` run-type label, alongside scheduled and manually triggered runs.

### Query the metadata database

Backfill Dag runs are stored in the `dag_run` table with `run_type = 'backfill'`.

```sql wrap theme={null}
SELECT dag_id, run_type, state, start_date, end_date
FROM dag_run
WHERE run_type = 'backfill'
ORDER BY start_date DESC;
```

<Note>
  Direct access to the metadata database is typically restricted to platform operators on APC. If you don't have direct access, use the Airflow UI or the Airflow REST API instead.
</Note>

## Troubleshoot

### Access denied when creating a backfill

The user has `DEPLOYMENT_VIEWER`, which only grants `backfill.read`. Promote them with `deploymentUpdateUserRole`:

Use the `deploymentUpdateUserRole` mutation to change an existing user's role on a Deployment, for example to promote a `DEPLOYMENT_VIEWER` to `DEPLOYMENT_EDITOR`:

```graphql wrap theme={null}
mutation {
  deploymentUpdateUserRole(
    deploymentId: "<deployment-id>"
    email: "<user-email>"
    role: DEPLOYMENT_EDITOR
  ) {
    id
  }
}
```

### Backfills aren't visible to a user

The user has no role on the Deployment. Add them with at least `DEPLOYMENT_VIEWER`. If the user holds `WORKSPACE_VIEWER` and still can't see the Deployment, confirm the Deployment is in the same Workspace.

### A role change hasn't taken effect

The user is still presenting their existing JWT, which keeps the previous permissions until it expires. The default JWT lifetime is 24 hours. Have the user sign out and sign back in to force APC to issue a fresh token. If they authenticate through SSO, ensure the IdP session is also refreshed.

## Best practices

* Assign `DEPLOYMENT_EDITOR` to operators who run backfills regularly. Reserve `DEPLOYMENT_ADMIN` for users who also manage Deployment configuration.
* Assign `DEPLOYMENT_VIEWER` to stakeholders who only need to monitor Dag runs.
* Use a Deployment service account with `DEPLOYMENT_EDITOR` for automated backfills triggered from CI or scheduled jobs, rather than a personal user token.
* Audit backfill activity by querying `dag_run.run_type = 'backfill'` or by reviewing the Dag's run list.
* Test large historical backfills in a non-production Deployment first.
* Set worker concurrency and Dag-level `max_active_runs` to limit the load a backfill places on the Deployment.
