---
title: "Set per-tenant resource usage limits | Grafana Enterprise Metrics documentation"
description: "Set per-tenant resource usage limits Caution Managing resource limits with the Admin API is deprecated and will be removed in a future release of GEM. Instead, manage limits using runtime configuration in Grafana Mimir."
---

[Documentation](/docs/)![breadcrumb arrow](/static/assets/img/icons/grafana-icon-breadcrumb-arrow-gray.svg) [Grafana Enterprise Metrics](/docs/enterprise-metrics/latest/)![breadcrumb arrow](/static/assets/img/icons/grafana-icon-breadcrumb-arrow-gray.svg) [Manage](/docs/enterprise-metrics/latest/manage/)![breadcrumb arrow](/static/assets/img/icons/grafana-icon-breadcrumb-arrow-gray.svg) [Manage a tenant](/docs/enterprise-metrics/latest/manage/tenant-management/)![breadcrumb arrow](/static/assets/img/icons/grafana-icon-breadcrumb-arrow-gray.svg) Set per-tenant resource usage limits

Enterprise

## Set per-tenant resource usage limits

> Caution
> 
> Managing resource limits with the Admin API is deprecated and will be removed in a future release of GEM. Instead, manage limits using [runtime configuration in Grafana Mimir](/docs/mimir/v2.17.x/configure/about-runtime-configuration/).

Per-tenant resource limits can be used to ensure a single tenant cannot monopolize the resources of or threaten the stability of a Grafana Enterprise Metrics cluster. There are limits available to tune usage of all parts of the metric read and write paths. For a complete list of all available limits, refer to the [Grafana Mimir limits configuration](/docs/enterprise-metrics/latest/configure/config-gem/reference/#limits).

Using the [admin API](/docs/enterprise-metrics/latest/api/admin-api/) of Grafana Enterprise Metrics, you can set a *subset* of these per-tenant limits.

The following limits are supported via the admin API:

- `ingestion_rate`
- `ingestion_burst_size`
- `max_series_per_query`
- `max_global_series_per_user`
- `max_global_series_per_metric`
- `max_global_exemplars_per_user`
- `ruler_max_rules_per_rule_group`
- `ruler_max_rule_groups_per_tenant`
- `max_fetched_chunks_per_query`
- `max_fetched_series_per_query`
- `max_fetched_chunk_bytes_per_query`
- `compactor_blocks_retention_period`

## Setting limits via the admin API

Limits can be set using the admin API when creating a new tenant or when modifying an existing one.

Create a JSON payload, `test1.json`, for creating a new tenant that includes a subset of per-tenant limits.

JSON ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```json
{
  "name": "test1",
  "display_name": "Test Instance 1",
  "status": "active",
  "cluster": "enterprise-metrics-dev",
  "limits": {
    "max_series_per_query": 42000,
    "max_global_series_per_user": 42000,
    "compactor_blocks_retention_period": "24h"
  }
}
```

Use `curl` to POST the data to the admin API.

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
$ curl -u :$API_TOKEN localhost:8080/admin/api/v3/tenants \
    -X POST --data @test1.json
```

Read the newly created tenant.

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
curl -u :$API_TOKEN localhost:8080/admin/api/v3/tenants/test1 | jq
{
  "name": "test1",
  "display_name": "Test Instance 1",
  "created_at": "2020-07-13T17:37:59.341728283Z",
  "status": "active",
  "cluster": "enterprise-metrics-dev",
  "limits": {
    "ingestion_rate": 350000,
    "ingestion_burst_size": 350000,
    "max_series_per_query": 42000,
    "max_global_series_per_user": 42000,
    "max_global_series_per_metric": 300000,
    "max_global_exemplars_per_user": 0,
    "ruler_max_rules_per_rule_group": 0,
    "ruler_max_rule_groups_per_tenant": 0,
    "max_fetched_chunks_per_query": 0,
    "max_fetched_series_per_query": 0,
    "max_fetched_chunk_bytes_per_query": 0,
    "compactor_blocks_retention_period": "24h"
  }
}
```

Note that all available limit settings are populated, even ones that we did not include in our POST request. Any limit settings not included when a new tenant is created with *some* limit settings are populated from the global default limits. This also applies when limits are added to a tenant that previously did not have them: any limit settings that are not included will be populated from the global default limits.

## Removing limits via the admin API

Limits can be removed from a tenant using the admin API by modifying the tenant.

Create a JSON payload, `test1-update.json`, that doesn’t include the `limits` field.

JSON ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```json
{
  "display_name": "Test Instance 1",
  "status": "active",
  "cluster": "enterprise-metrics-dev"
}
```

Use `curl` to PUT the data to the admin API.

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
$ curl -u :$API_TOKEN localhost:8080/admin/api/v3/tenants/test1 \
    -X PUT --data @test1-update.json | jq
{
  "name": "test1",
  "display_name": "Test Instance 1",
  "created_at": "2020-07-13T17:37:59.341728283Z",
  "status": "active",
  "cluster": "enterprise-metrics-dev"
}
```

The modified tenant object is included in the update response.

## Limit sources

Limits applied to a tenant are only taken from a single location at a time:

- Per-tenant limits set by the [admin API](/docs/enterprise-metrics/latest/api/admin-api/), backfilled with global defaults.
- Per-tenant limits set by a [runtime configuration file](/docs/mimir/v2.17.x/configure/about-runtime-configuration/), backfilled with global defaults.
- Global default limits set by a [configuration file](/docs/enterprise-metrics/latest/configure/config-gem/reference/#limits).

These locations are checked for limits to apply to operations, in that order. Once a location for limits to apply to an operation is found, **no other locations are checked**. The effect of this is that if you set limits for a tenant using the admin API, any limit settings for *that* tenant in a runtime configuration file will be ignored.

## Implementation

Enforcing limits based on values set with the admin API requires periodically making requests to object storage (S3, GCS, etc.) to get the most up to date limits for each tenant. This means that based on the period you have configured to refresh tenant-based limits (1 minute by default), N GET requests and 1 LIST request will be made to object storage, where N is the number of tenants in your Grafana Enterprise Metrics cluster.
