Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
title: "demand_control"
---

The `demand_control` configuration controls operation cost estimation, enforcement, and metadata
emission in Hive Router.

For conceptual guidance and rollout strategy, see
[Demand Control](/docs/router/security/demand-control).

## Options

### `enabled`

- **Type:** `boolean`
- **Default:** `false`

Enables demand-control cost evaluation.

### `mode`

- **Type:** `string`
- **Allowed values:** `enforce`, `measure`
- **Required:** yes

Controls how limits are applied:

- `enforce`: apply configured limits and reject/skip over-budget operations or subgraphs.
- `measure`: never reject requests; still compute costs, emit metrics, and set result codes.

### `include_extension_metadata`

- **Type:** `boolean`
- **Default:** `false`

When `true`, response `extensions.cost` includes cost metadata such as estimated cost, result code,
per-subgraph breakdown, formula-cache information, and actual-cost fields.

### `strategy`

Demand control currently supports one strategy variant: `static_estimated`.

#### `strategy.static_estimated.max`

- **Type:** `integer`
- **Format:** `uint64`
- **Minimum:** `0`
- **Required:** yes

Supergraph-wide maximum allowed cost.

In `mode: enforce`:

- If estimated cost exceeds `max`, request is rejected with `COST_ESTIMATED_TOO_EXPENSIVE`.
- If actual cost exceeds `max`, response includes `COST_ACTUAL_TOO_EXPENSIVE`.

In `mode: measure`, limits are not enforced but result codes still reflect over-limit evaluations.

#### `strategy.static_estimated.list_size`

- **Type:** `integer`
- **Format:** `uint`
- **Minimum:** `0`
- **Default:** unset

Fallback list-size assumption used for list-returning fields that do not define `@listSize`.

#### `strategy.static_estimated.actual_cost_mode`

- **Type:** `string`
- **Allowed values:** `by_subgraph`, `by_response_shape`
- **Default:** `by_subgraph`

Controls how actual cost is calculated:

- `by_subgraph`: Sums actual costs from subgraph responses.
- `by_response_shape`: Computes cost from the final response shape.

#### `strategy.static_estimated.subgraph`

Optional per-subgraph demand-control overrides.

##### `strategy.static_estimated.subgraph.all`

Defaults applied to all subgraphs unless overridden in `subgraph.subgraphs`.

###### `strategy.static_estimated.subgraph.all.max`

- **Type:** `integer`
- **Format:** `uint64`
- **Minimum:** `0`

Maximum allowed estimated cost per subgraph.

###### `strategy.static_estimated.subgraph.all.list_size`

- **Type:** `integer`
- **Format:** `uint`
- **Minimum:** `0`

Fallback list-size assumption per subgraph.

##### `strategy.static_estimated.subgraph.subgraphs`

Map of subgraph names to per-subgraph overrides.

###### `strategy.static_estimated.subgraph.subgraphs.<name>.max`

- **Type:** `integer`
- **Format:** `uint64`
- **Minimum:** `0`

Maximum allowed estimated cost for the named subgraph.

###### `strategy.static_estimated.subgraph.subgraphs.<name>.list_size`

- **Type:** `integer`
- **Format:** `uint`
- **Minimum:** `0`

Fallback list-size assumption for the named subgraph.

## Behavior

When demand control is enabled:

- The router estimates operation cost before execution.
- If global `strategy.static_estimated.max` is exceeded in `mode: enforce`, the request is rejected with
`COST_ESTIMATED_TOO_EXPENSIVE`.
- If subgraph-level limits are exceeded in `mode: enforce`, the router skips only over-budget subgraphs and continues
the rest of the plan. Skipped subgraphs return
`SUBGRAPH_COST_ESTIMATED_TOO_EXPENSIVE`.
- If actual cost exceeds `strategy.static_estimated.max`, response may include
`COST_ACTUAL_TOO_EXPENSIVE`.

## Precedence

1. Field-level directives (`@cost`, `@listSize`) apply first.
2. For list-size fallback:
- `strategy.static_estimated.subgraph.subgraphs.<name>.list_size`
- then `strategy.static_estimated.subgraph.all.list_size`
- then global `strategy.static_estimated.list_size`
3. For subgraph max cost:
- `strategy.static_estimated.subgraph.subgraphs.<name>.max`
- then `strategy.static_estimated.subgraph.all.max`
4. Global `strategy.static_estimated.max` is evaluated on full-operation estimated cost.

## Examples

### Measurement mode

```yaml title="router.config.yaml"
demand_control:
enabled: true
mode: measure
strategy:
static_estimated:
max: 1000
list_size: 10
include_extension_metadata: true
```

### Global enforcement

```yaml title="router.config.yaml"
demand_control:
enabled: true
mode: enforce
strategy:
static_estimated:
max: 500
list_size: 10
include_extension_metadata: true
```

### Subgraph-level enforcement

```yaml title="router.config.yaml"
demand_control:
enabled: true
mode: enforce
strategy:
static_estimated:
max: 5000
list_size: 10
subgraph:
all:
max: 1000
list_size: 20
subgraphs:
reviews:
max: 300
search:
max: 150
list_size: 5
```

### Actual-cost calculation

```yaml title="router.config.yaml"
demand_control:
enabled: true
mode: enforce
strategy:
static_estimated:
max: 500
actual_cost_mode: by_subgraph
include_extension_metadata: true
```
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"pages": ["index", "environment-variables", "expressions", "..."]
"pages": [
"index",
"environment-variables",
"expressions",
"demand_control",
"..."
]
}
Loading
Loading