You're viewing **Apigee Edge** documentation.  
[Go to the
**Apigee X** documentation](http://cloud.google.com/apigee/docs). info
![](https://docs.apigee.com/static/api-platform/images/icon_policy_quota.jpg)

### What

Use the Quota policy to configure the number of request messages that an API proxy allows over
a period of time, such as a minute, hour, day, week, or month. You can set the quota to be the
same for all apps accessing the API proxy, or you can set the quota based on:

- The product that contains the API proxy
- The app requesting the API
- The app developer
- Many other criteria

Don't use Quota to shield against overall traffic spikes. For that, use the Spike Arrest
policy. See [Spike Arrest
policy](https://docs.apigee.com/api-platform/reference/policies/spike-arrest-policy).

> [!IMPORTANT]
> **Tip:** Need help deciding which rate limiting policy to use? See [Comparing
> Quota, Spike Arrest, and Concurrent Rate Limit Policies](https://docs.apigee.com/api-platform/develop/comparing-quota-spike-arrest-and-concurrent-rate-limit-policies).

### Videos

These videos introduce quota management with the Quota policy:

### Intro (New Edge)

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/bzSDsKZy4Vw" width="640"></iframe>

### Intro (Classic Edge)

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/6bLSc7zi17o" width="640"></iframe>

### Dynamic Quota

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/z8Rj_VzSbh4" width="640"></iframe>

### Distributed \& Synchronous

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/3Vw-P5WdOyk" width="640"></iframe>

### Message Weight

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/QyiN1R5dqPE" width="640"></iframe>

### Calendar

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/R7EkzSuH2to" width="640"></iframe>

### Rolling Window

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/OrFTDTBzI-Y" width="640"></iframe>

### Flexi

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/0dSqfVwrjlc" width="640"></iframe>

### Conditional Quota

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/SGeyPSIP43s" width="640"></iframe>

### Flow Variables

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/-vsV59YKB_8" width="640"></iframe>

### Error Handling

<iframe allowfullscreen frameborder="0" height="390" src="https://www.youtube.com/embed/9m1-jkt1WTI" width="640"></iframe>

### Samples

These policy code samples illustrate how to start and end quota periods by:

### More Dynamic Quota

```
<Quota name="CheckQuota">
  <Interval ref="verifyapikey.verify-api-key.apiproduct.developer.quota.interval">1</Interval>
  <TimeUnit ref="verifyapikey.verify-api-key.apiproduct.developer.quota.timeunit">hour</TimeUnit>
  <Allow count="200" countRef="verifyapikey.verify-api-key.apiproduct.developer.quota.limit"/>
</Quota>
```

Dynamic quotas enable you to configure a single Quota policy that enforces different Quota
settings based on information passed to the Quota policy. Another term for Quota settings in
this context is "Service Plan". The dynamic Quota checks the apps' "Service Plan" and then
enforces those settings.

**Note**: If you specify both a value and a reference for an element,
then reference gets the priority. If reference does not resolve at runtime, then the value is
used.

For example, when you create an API product, you can optionally set the allowed quota
limit, time unit, and interval. However, setting these value on the API product does not
enforce their use in an API proxy. You must also add a Quota policy to the API proxy that
reads these values. See [Create API
products](https://docs.apigee.com/api-platform/publish/create-api-products) for more.

In the example above, the API proxy containing the Quota policy uses a VerifyAPIKey
policy, named `verify-api-key`, to validate the API key passed in a request. The
Quota policy then accesses the flow variables from the VerifyAPIKey policy to read the quota
values set on the API product. For more on VerifyAPIKey flow variables, see [Verify API Key policy](https://docs.apigee.com/api-platform/reference/policies/verify-api-key-policy).

Another option is to set custom attributes on individual developers or apps, and then read
those values in the Quota policy. For example, you want to set different quota values per
developer. In this case, you set custom attributes on the developer containing the limit,
time unit, and interval. You then reference these values in the Quota policy as shown
below:

```
<Quota name="DeveloperQuota">
  <Identifier ref="verifyapikey.verify-api-key.client_id"/>
  <Interval ref="verifyapikey.verify-api-key.developer.timeInterval"/>
  <TimeUnit ref="verifyapikey.verify-api-key.developer.timeUnit"/>
  <Allow countRef="verifyapikey.verify-api-key.developer.limit"/>
</Quota>
```

This example also uses the VerifyAPIKey flow variables to reference the custom attributes
set on the developer.

You can use any variable to set the parameters of the Quota policy. Those variables can
come from:

- Flow variables
- Properties on the API product, app, or developer
- A key value map (KVM)
- A header, query parameter, form parameter, etc

For each API proxy, you can add a Quota policy that either references the same variable as
all the other Quota policies in all the other proxies, or the Quota policy can reference
variables unique for that policy and proxy.

### Start Time

```
<Quota name="QuotaPolicy" type="calendar">
  <StartTime>2017-02-18 10:30:00</StartTime>
  <Interval>5</Interval>
  <TimeUnit>hour</TimeUnit>
  <Allow count="99"/>
</Quota>
```

For a Quota with `type` set to `calendar`, you must define an
explicit `<StartTime>` value. The time value is the GMT time, not local
time. If you do not provide a `<StartTime>` value for a policy of type
`calendar`, Edge issues an error.

The Quota counter for each app is refreshed based on the `<StartTime>`,
`<Interval>`, and `<TimeUnit>` values. For this
example, the Quota begins counting at 10:30 am GMT on February 18, 2017, and refreshes every
5 hours. Therefore, the next refresh is at 3:30 pm GMT on February 18, 2017.

### Access Counter

```
<Quota name="QuotaPolicy">
  <Interval>5</Interval>
  <TimeUnit>hour</TimeUnit>
  <Allow count="99"/>
</Quota>
```

An API proxy has access to the flow variables set by the Quota policy. You can access
these flow variables in the API proxy to perform conditional processing, monitor the policy
as it gets close to the quota limit, return the current quota counter to an app, or for other
reasons.

Because access the flow variables for the policy is based on the policies
`name` attribute, for the policy above named `QuotaPolicy` you
access its flow variables in the form:

- `ratelimit.QuotaPolicy.allowed.count`: Allowed count.
- `ratelimit.QuotaPolicy.used.count`: Current counter value.
- `ratelimit.QuotaPolicy.expiry.time`: UTC time when the counter resets.

There are many other flow variables that you can access, as described below.

For example, you can use the following AssignMessage policy to return the values of Quota
flow variables as response headers:

```
<AssignMessage async="false" continueOnError="false" enabled="true" name="ReturnQuotaVars">
    <AssignTo createNew="false" type="response"/>
    <Set>
        <Headers>
            <Header name="QuotaLimit">{ratelimit.QuotaPolicy.allowed.count}</Header>
            <Header name="QuotaUsed">{ratelimit.QuotaPolicy.used.count}</Header>
            <Header name="QuotaResetUTC">{ratelimit.QuotaPolicy.expiry.time}</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>
```

### First Request

```
<Quota name="MyQuota">
  <Interval>1</Interval>
  <TimeUnit>hour</TimeUnit>
  <Allow count="10000"/>
</Quota>
```

Use this sample code to enforce a quota of 10,000 calls per one hour. The policy resets
the quota counter at the top of each hour. If the counter reaches the 10,000-call quota
before the end of the hour, calls beyond 10,000 are rejected.

For example, if the counter starts at `2017-07-08 07:00:00`, then it resets to
0 at `2017-07-08 08:00:00` (1 hour from the start time). If the first message is
received at `2017-07-08 07:35:28` and the message count reaches 10,000
before `2017-07-08 08:00:00`, calls beyond that count are rejected until the
count resets at the top of the hour.

The counter reset time is based on the combination of `<Interval>` and
`<TimeUnit>`. For example, if you set `<Interval>` to
12 for a `<TimeUnit>` of hour, then the counter resets every twelve hours.
You can set `<TimeUnit>` to minute, hour, day, week, or month.

You can reference this policy in multiple places in your API proxy. For example, you could
place it on the Proxy PreFlow so it is executed on on every request. Or, you could place
it on multiple flows in the API proxy. If you use this policy in multiple places in the
proxy, it maintains a single counter that is updated by all instances of the policy.

Alternatively, you can define multiple Quota policies in your API proxy. Each Quota policy
maintains its own counter, based on the `name` attribute of the policy.

### Set identifier

```
<Quota name="QuotaPolicy" type="calendar">
  <Identifier ref="request.header.clientId"/>
  <StartTime>2017-02-18 10:00:00</StartTime>
  <Interval>5</Interval>
  <TimeUnit>hour</TimeUnit>
  <Allow count="99"/>
</Quota>
```

By default, a Quota policy defines a single counter for the API proxy, regardless of the
origin of a request. Alternatively, you can use the `<Identifier>` attribute
with a Quota policy to maintain separate counters based on the value of the
`<Identifier>` attribute.

For example, use the `<Identifier>` tag to define separate counters for
every client ID. On a request to your proxy, the client app then passes a header containing
the `clientID`, as shown in the example above.

You can specify any flow variable to the `<Identifier>` attribute. For
example, you could specify that a query param named `id` contains the unique
identifier:

```
<Identifier ref="request.queryparam.id"/>
```

If you use the VerifyAPIKey policy to validate the API key, or the OAuthV2 policies
with OAuth tokens, you can use information in the API key or token to define individual
counters for the same Quota policy. For example, the following
`<Identifier>` tag uses the `client_id` flow variable of a
VerifyAPIKey policy named `verify-api-key`:

```
<Identifier ref="verifyapikey.verify-api-key.client_id"></Identifier>
```

Each unique `client_id` value now defines its own counter in the Quota
policy.

### Class

```
<Quota name="QuotaPolicy">
  <Interval>1</Interval>
  <TimeUnit>day</TimeUnit>
  <Allow>
    <Class ref="request.header.developer_segment">
      <Allow class="platinum" count="10000"/>
      <Allow class="silver" count="1000" />
    </Class>
  </Allow>
</Quota>
```

You can set Quota limits dynamically by using a class-based Quota count. In this example,
the quota limit is determined by the value of the `developer_segment`
header passed with each request. That variable can have a value of `platinum`
or `silver`. If the header has an invalid value, the policy returns a quota
violation error.

> [!NOTE]
> **Note:** You cannot use both the `<Class>` and `<Identifier>` elements in the same Quota policy.

*** ** * ** ***

## About the Quota policy

A Quota is an allotment of request messages that an API proxy can handle over a time period,
such as minute, hour, day, week, or month. The policy maintains counters that tally the number of
requests received by the API proxy. This capability enables API providers to enforce limits on
the number of API calls made by apps over an interval of time. Using Quota policies you can, for
example, limit apps to 1 request per minute, or to 10,000 requests per month.

> [!NOTE]
> **Note:** When an API proxy reaches its Quota limit, subsequent API calls are rejected; Apigee Edge returns an error message for every request that exceeds the Quota. The Quota policy provides the ability to reset Quotas on-the-fly, after an app has exceeded its limit.

For example, if a Quota is defined as 10,000 messages per month, rate-limiting begins after
the 10,000th message. It doesn't matter whether 10,000 messages were counted on the first
day or the last day of that period; no additional requests area allowed until the Quota counter
automatically resets at the end of the specified time interval, or until the Quota is explicitly
reset using [Reset Quota
policy](https://docs.apigee.com/api-platform/reference/policies/reset-quota-policy).

A variation on Quota called SpikeArrest prevents traffic spikes (or bursts) that can
be caused by a sudden increase in usage, buggy clients, or malicious attacks. For more
information on SpikeArrest, see [Spike Arrest policy](https://docs.apigee.com/api-platform/reference/policies/spike-arrest-policy).

Quotas apply to individual API proxies and are not distributed among API proxies. For example,
if you have three API proxies in an API product, a single quota is not shared across all three
even if all three use the same quota policy configuration.

## Quota policy types

The Quota policy supports several different types of policies: default, `calendar`,
`flexi`, and `rollingwindow`. Each type defines when the quota counter
starts and when it resets, as shown in the following table:

| Time Unit | Default (or null) reset | calendar reset | flexi reset |
|---|---|---|---|
| minute | Start of next minute | One minute after `<StartTime>` | One minute after first request |
| hour | Top of next hour | One hour after `<StartTime>` | One hour after first request |
| day | Midnight GMT of the current day | 24 hours after `<StartTime>` | 24 hours after first request |
| week | Midnight GMT Sunday at the end of the week | One week after `<StartTime>` | One week after first request |
| month | Midnight GMT of the last day of the month | One month (28 days) after `<StartTime>` | One month (28 days) after first request |

> [!NOTE]
> **Note:** The policy also supports `second` as the time unit. However, `second` is only supported for non-distributed counters, as defined by `Distributed=false`. Instead of using `second`, Apigee recommends that you use the [SpikeArrest
> policy](https://docs.apigee.com/api-platform/reference/policies/spike-arrest-policy#how-spike-arrest-works) to limit spikes in request traffic at the second level.

For `type="calendar"`, you must specify the value of
`<StartTime>`.

The table does not list the value for the `rollingwindow` type. Rolling window
quotas work by setting the size of a quota "window", such as a one hour or one day window. When a
new request comes in, the policy determines if the quota has been exceeded in the past
"window" of time.

For example, you define a two hour window that allows 1000 requests. A new request
comes in at 4:45 PM.The policy calculates the quota count for the past two hour window,
meaning the number of requests since 2:45 PM. If the quota limit has not been exceeded in that
two-hour window, then the request is allowed.

One minute later, at 4:46 PM, another request comes in. Now the policy calculates the
quota count since 2:46 PM to determine if the limit has been exceeded.

For the `rollingwindow` type, the counter never resets, but is
recalculated on each request.

## Understanding quota counters

By default, a Quota policy maintains a single counter, regardless of how many times you
reference it in an API proxy. The name of the quota counter is based on
the `name` attribute of the policy.

For example, you create a Quota policy named `MyQuotaPolicy` with a limit of 5
requests and place it on multiple flows (Flow A, B, and C) in the API proxy. Even though it is
used in multiple flows, it maintains a single counter that is updated by all instances of the
policy:

- Flow A is executed -\> MyQuotaPolicy is executed and its counter = 1
- Flow B is executed -\> MyQuotaPolicy is executed and its counter = 2
- Flow A is executed -\> MyQuotaPolicy is executed and its counter = 3
- Flow C is executed -\> MyQuotaPolicy is executed and its counter = 4
- Flow A is executed -\> MyQuotaPolicy is executed and its counter = 5

The next request to any of the three flows is rejected because the quota counter has reached
its limit.

Using the same Quota policy in more than one place in an API proxy flow, which can
unintentionally cause Quota to run out faster than you expected, is an anti-pattern described in
[The Book of Apigee Edge Antipatterns](https://discuss.google.dev/t/the-book-of-apigee-edge-antipatterns-version-2-0/17348).

Alternatively, you can define multiple Quota policies in your API proxy and use a different
policy in each flow. Each Quota policy maintains its own counter, based on
the `name` attribute of the policy.

Or, use the
`<Class>` or `<Identifier>` elements in
the Quota policy to define multiple, unique counters in a single policy. By using these
elements, a single policy can maintain different counters based on the app making the request,
the app developer making the request, a client ID or other client identifier, and more. See the
examples above for more information on using the
`<Class>` or `<Identifier>` elements.

> [!NOTE]
> **Note:** Quota counters are scoped to the API proxy that contains the Quota policy. If multiple API proxies contain Quota policies with the same name, the counters are maintained separately.

## Time notation

All Quota times are set to the [Coordinated Universal
Time](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) (UTC) time zone.

Quota time notation follows the international standard date notation defined in International
Standard [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601).

Dates are defined as year, month, and day, in the following format: `YYYY-MM-DD`.
For example, `2015-02-04` represents February 4, 2015.

Time of day is defined as hours, minutes, and seconds in the following format:
`hours:minutes:seconds`. For example, `23:59:59` represents the time one
second before midnight.

Note that two notations, `00:00:00` and `24:00:00`, are available to
distinguish the two midnights that can be associated with one date. Therefore `2015-02-04
24:00:00` is the same date and time as `2015-02-05 00:00:00`. The latter is
usually the preferred notation.

## Getting quota settings from the API product configuration

You can set quota limits in API product configurations. Those limits don't automatically
enforce quota. Instead, you can reference product quota settings in a quota policy. Here are some
advantages of setting a quota on the product for quota policies to reference:

- Quota policies can use a uniform setting across all API proxies in the API product.
- You can make runtime changes to the quota setting on an API product, and quota policies that reference the value automatically have updated quota values.

For more information on using quota settings from an API product, see the "Dynamic Quota"
example above.[.](https://discuss.google.dev/t/how-do-the-quota-settings-on-an-api-product-interact-with-quota-policies-in-an-api-proxy/6852)

For info on configuring API products with quota limits, see [Create API products](https://docs.apigee.com/api-platform/publish/create-api-products).

## Element reference

Following are elements and attributes you can configure on this policy. Note that some element
combinations are mutually exclusive or not required. See the samples for specific usage. The
`verifyapikey.VerifyAPIKey.apiproduct.*` variables below are available by default when
a Verify API Key policy called "VerifyAPIKey" is used to check the app's API key in the request.
The variable values come from the quota settings on the API product that the key is associated
with, as described in [Getting quota settings from the API product
configuration](https://docs.apigee.com/api-platform/reference/policies/quota-policy#product).

```
<Quota async="false" continueOnError="false" enabled="true" name="Quota-3" type="calendar">
   <DisplayName>Quota 3</DisplayName>
   <Allow count="2000" countRef="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.limit"/>
   <Allow>
      <Class ref="request.queryparam.time_variable">
        <Allow class="peak_time" count="5000"/>
        <Allow class="off_peak_time" count="1000"/>
      </Class>
   </Allow>
   <Interval ref="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.interval">1</Interval>
   <TimeUnit ref="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.timeunit">month</TimeUnit>
   <StartTime>2017-7-16 12:00:00</StartTime>
   <Distributed>false</Distributed>
   <Synchronous>false</Synchronous>
   <AsynchronousConfiguration>
      <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
      <SyncMessageCount>5</SyncMessageCount>
   </AsynchronousConfiguration>
   <Identifier/>
   <MessageWeight/>
</Quota>
```

## \<Quota\> attributes

```
<Quota async="false" continueOnError="false" enabled="true" name="Quota-3" type="calendar">
```

The following attributes are specific to this policy.

| Attribute | Description | Default | Presence |
|---|---|---|---|
| type | Use to determine when and how the quota counter checks quota usage. See [Quota policy types](https://docs.apigee.com/api-platform/reference/policies/quota-policy#quotapolicytypes) for more information. If you omit a `` `type` `` value, the counter begins at the beginning of the minute/hour/day/week/month. Valid values include: - `calendar`: Configure a quota based on an explicit start time. The Quota counter for each app is refreshed based on the `<StartTime>`, `<Interval>`, and `<TimeUnit>` values that you set. - `rollingwindow`: Configure a quota that uses a "rolling window" to determine quota usage. With `rollingwindow`, you determine the size of the window with the `<Interval>` and `<TimeUnit>` elements; for example, 1 day. When a request comes in, Edge looks at the exact time of the request (say 5:01pm), counts the number of requests that came in between then and 5:01pm the previous day (1 day), and determines whether or not quota has been exceeded during that window. - `flexi`: Configure a quota that causes the counter to begin when the first request message is received from an app, and resets based on the `<Interval>, `and `<TimeUnit>` values. | calendar | Optional |

The following table describes attributes that are common to all policy parent elements:

| Attribute | Description | Default | Presence |
|---|---|---|---|
| `name` | The internal name of the policy. The value of the `name` attribute can contain letters, numbers, spaces, hyphens, underscores, and periods. This value cannot exceed 255 characters. Optionally, use the `<DisplayName>` element to label the policy in the management UI proxy editor with a different, natural-language name. | N/A | Required |
| `continueOnError` | Set to `false` to return an error when a policy fails. This is expected behavior for most policies. Set to `true` to have flow execution continue even after a policy fails. | false | Optional |
| `enabled` | Set to `true` to enforce the policy. Set to `false` to *turn off* the policy. The policy will not be enforced even if it remains attached to a flow. | true | Optional |
| `async` | This attribute is deprecated. | false | Deprecated |

## \<DisplayName\> element

Use in addition to the `name` attribute to label the policy in the
management UI proxy editor with a different, natural-language name.

```
<DisplayName>Policy Display Name</DisplayName>
```

| Default | N/A If you omit this element, the value of the policy's `name` attribute is used. |
| Presence | Optional |
| Type | String |
|---|---|

## \<Allow\> element

Specifies the count limit for the quota. If the counter for the policy reaches this limit
value, subsequent calls are rejected until the counter resets.

Shown below are three ways to set the `<Allow>` element:

```
<Allow count="2000"/>
```

```
<Allow countRef="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.limit"/>
```

```
<Allow count="2000" countRef="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.limit"/>
```

If you specify both `count` and `countRef`, then `countRef`
gets the priority. If `countRef` does not resolve at runtime, then the value of
`count` is used.

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | Integer |

### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| count | Use to specify a message count for the quota. For example, a `count` attribute value of 100, `Interval` of 1, and a `TimeUnit` of month specify a quota of 100 messages per month. | 2000 | Optional |
| countRef | Use to specify a flow variable containing the message count for a quota. `countRef` takes precedence over the `count` attribute. | none | Optional |

### \<Allow\>/\<Class\> element

The `<Class>` element lets you conditionalize the value
of the `<Allow>` element based on the value of a flow variable. For
each different `<Allow>` child tag of `<Class>`,
the policy maintains a different counter.

To use the` <Class>` element, specify a flow variable using the
`ref` attribute to the `<Class>` tag. Edge then uses the value of the
flow variable to select one of the `<Allow>` child tags to determine the allowed
count of the policy. Edge matches the value of the flow variable to the `class`
attribute of the `<Allow>` tag, as shown below:

```
<Allow>
  <Class ref="request.queryparam.time_variable">
    <Allow class="peak_time" count="5000"/>
    <Allow class="off_peak_time" count="1000"/>
  </Class>
</Allow>
```

In this example, the current quota counter is determined by the value of the
`time_variable` query param passed with each request. That variable can have a value
of `peak_time` or `off_peak_time`. If the query param contains an invalid
value, the policy returns a quota violation error.

> [!NOTE]
> **Note:** You cannot use both the `<Class>` and `<Identifier>` elements in the same Quota policy.

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | N/A |

#### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| ref | Use to specify a flow variable containing the quota class for a quota. | none | Required |

### \<Allow\>/\<Class\>/\<Allow\>
element

The `<Allow>` element specifies the limit for a quota counter
defined by the `<Class>` element. For each
different `<Allow>` child tag of `<Class>`, the
policy maintains a different counter.

For example:

```
<Allow>
  <Class ref="request.queryparam.time_variable">
    <Allow class="peak_time" count="5000"/>
    <Allow class="off_peak_time" count="1000"/>
  </Class>
</Allow>
```

In this example, the Quota policy maintains two quota counters named
of `peak_time` and `off_peak_time`.

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | N/A |

#### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| class | Defines the name of the quota counter. | none | Required |
| count | Specifies the quota limit for the counter. | none | Required |

## \<Interval\> element

Use to specify an integer (for example, 1, 2, 5, 60, and so on) that will be paired with the
`TimeUnit` you specify (minute, hour, day, week, or month) to determine a time
period during which Edge calculates quota use.

For example, an `Interval` of `24` with
a `TimeUnit` of `hour` means that the quota will be
calculated over the course of 24 hours.

```
<Interval ref="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.interval">1</Interval>
```

|---|---|
| **Default:** | none |
| **Presence:** | Required |
| **Type:** | Integer |

### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| ref | Use to specify a flow variable containing the interval for a quota. `ref` takes precedence over an explicit interval value. If both reference and value are specified, then reference gets the priority. If `ref` does not resolve at runtime, then the value is used. | none | Optional |

## \<TimeUnit\> element

Use to specify the unit of time applicable to the quota.

For example, an `Interval` of `24` with
a `TimeUnit` of `hour` means that the quota will be
calculated over the course of 24 hours.

```
<TimeUnit ref="verifyapikey.VerifyAPIKey.apiproduct.developer.quota.timeunit">month</TimeUnit>
```

|---|---|
| **Default:** | none |
| **Presence:** | Required |
| **Type:** | String. Select from `minute`, `hour`, `day`, `week`, or `month`. > [!NOTE] > **Note:** The policy also supports `second` as the time unit. However, `second` is only supported for non-distributed counters, as defined by `Distributed=false`. Instead of using `second`, Apigee recommends that you use the [SpikeArrest > policy](https://docs.apigee.com/api-platform/reference/policies/spike-arrest-policy#how-spike-arrest-works) to limit spikes in request traffic at the second level. |

### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| ref | Use to specify a flow variable containing the time unit for a quota. `ref` takes precedence over an explicit interval value. If the `ref` does not resolve at runtime, then the value is used. | none | Optional |

## \<StartTime\> element

When `type` is set to `calendar,` specifies the date
and time when the quota counter will begin counting, regardless of whether any requests have been
received from any apps.

> [!IMPORTANT]
> **Important:** If you omit the `<StartTime>` element from your Quota policy configuration, the quota period will start on the first day of the current month, by default.

For example:

```
<StartTime>2017-7-16 12:00:00</StartTime>
```

|---|---|
| **Default:** | none |
| **Presence:** | Required when `type` is set to `calendar`. |
| **Type:** | String in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time format. |

## \<Distributed\> element

An installation of Edge can use one or more Message Processors to process requests. Set this
element to `true` to specify that the policy should maintain a central
counter and continuously synchronize it across all Message Processors. The message processors
can be across availability zones and/or regions.

> [!NOTE]
> **Note:** If you have a paid account on Edge for the Cloud, you typically have multiple Message Processors in your installation, and that number can vary based on your traffic load. Free Edge accounts typically have two Message Processors.
>
> If you are an Edge for the Private Cloud customer, contact your Edge system administrator to
> determine the number of Message Processors.
>
> For example, if the quota limit is 10 messages per hour, and two Message Processors are
> being used, the quota count total is continuously updated by both Message Processors.

If you use the default value of `false`, then you might exceed your quota because
the count for each Message Processor is not shared:

```
<Distributed>true</Distributed>
```

To guarantee that the counters are synchronized, and updated on every request, set
`<Distributed>` and `<Synchronous>` to true:

```
<Distributed>true</Distributed>
<Synchronous>true</Synchronous>
```

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | Boolean |

## \<Synchronous\> element

Set to `true` to update a distributed quota counter synchronously. This
means that the update to the counter are made at the same time the quota is checked on a request
to the API. Set to `true` if it is essential that you not allow any API
calls over the quota.

> [!NOTE]
> **Note:** By implementing synchronous updates to the counter, there is the potential for performance impacts and lower throughputs. In some cases, use of `<Synchronous>` could cause the quota policy to fail to process some transactions.

Set to `false` to update the quota counter asynchronously. This means
that it is possible that some API calls exceeding the quota will go through, depending on when
the quota counter in the central repository is asynchronously updated. However, you will not face
the potential performance impacts associated with synchronous updates.

The default asynchronous update interval is 10 seconds. Use the
`AsynchronousConfiguration` element to configure this asynchronous behavior.

```
<Synchronous>false</Synchronous>
```

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | Boolean |

## \<AsynchronousConfiguration\> element

Configures the synchronization interval amongst distributed quota counters when the policy
configuration element `<Synchronous>` is either not present or present and set
to `false`.

You can synchronize either after a time period or a message count, using either the
`SyncIntervalInSeconds` or `SyncMessageCount` child elements.
They are mutually exclusive. For example,

```
<AsynchronousConfiguration>
   <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
</AsynchronousConfiguration>
```

or

```
<AsynchronousConfiguration>
   <SyncMessageCount>5</SyncMessageCount>
</AsynchronousConfiguration>
```

|---|---|
| **Default:** | SyncIntervalInSeconds = 10 seconds |
| **Presence:** | Optional; ignored when `<Synchronous>` is set to `true`. |
| **Type:** | Compound |

### \<AsynchronousConfiguration\>/\<SyncIntervalInSeconds\>
element

Use this to override the default behavior in which asynchronous updates are performed after an
interval of 10 seconds.

```
<AsynchronousConfiguration>
   <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
</AsynchronousConfiguration>
```

The sync interval must be \>= 10 seconds as described in the
[Limits](https://docs.apigee.com/api-platform/reference/limits#quota) topic.

|---|---|
| **Default:** | 10 |
| **Presence:** | Optional |
| **Type:** | Integer |

### \<AsynchronousConfiguration\>/\<SyncMessageCount\> element

Specifies the number of requests across all Apigee message processors between quota
updates.

```
<AsynchronousConfiguration>
   <SyncMessageCount>5</SyncMessageCount>
</AsynchronousConfiguration>
```

This example specifies that the quota count is updated every 5 requests across each Apigee
Edge message processor.

|---|---|
| **Default:** | n/a |
| **Presence:** | Optional |
| **Type:** | Integer |

## \<Identifier\> element

Use the `<Identifier>` element to configure the policy to create unique
counters based on a flow variable.

> [!NOTE]
> **Note:** Apigee recommends that you **do not** use the following variables for the quota identifier:
>
> - `developer.id`
> - `developer.app.id`
> - `company.id`
> The reason for avoiding the use of these variables is that these IDs are generated internally by Apigee and are not guaranteed to stay the same over time. Apigee could change the format or length of these IDs, for example.

You can create unique counters for characteristics defined by a flow variable. For example, you might use the developer email address to tie a quota to a specific developer. You can use a variety of variables to identify a quota, whether you're using custom variables or predefined variables, such as those available with the [Verify API Key policy](https://docs.apigee.com/api-platform/reference/policies/verify-api-key-policy). See also the [Variables reference](https://docs.apigee.com/api-platform/reference/variables-reference).

<br />

If you don't use this element, the policy uses a single counter that is applied against
the quota.

This element is also discussed in the following Apigee Community post: [Quota identifier across different policies](https://discuss.google.dev/t/quota-identifier-across-different-policies/85417).

```
<Identifier ref="verifyapikey.verify-api-key.client_id"/>
```

> [!NOTE]
> **Note:** You cannot use both the `<Class>` and `<Identifier>` elements in the same Quota policy.

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | String |

### Attributes

| Attribute | Description | Default | Presence |
|---|---|---|---|
| ref | Specifies a flow variable that identifies the counter to use for the request. The identifier can be an HTTP header, query parameter, form parameter, or message content that is unique to each app, app user, app developer, API product, or other characteristic. The `<Identifier>` most commonly used to uniquely identify apps is the `client_id`. The `client_id` is another name for the API key, or consumer key, that is generated for an app when it is registered in an organization on Apigee Edge. You can use this identifier if you have enabled API key or OAuth authorization policies for your API. In some circumstances, Quota settings must be retrieved where no `client_id` is available, such as when no security policy is in place. In those situations, you can use the Access Entity policy to retrieve the appropriate API product settings, then extract values using ExtractVariables, and then used the extracted context variable in the Quota policy. For more information, see [Access Entity policy](https://docs.apigee.com/api-platform/reference/policies/access-entity-policy). | N/A | Optional |

## \<MessageWeight\> element

Use to specify the weight assigned to each message. Use message weight to increase impact of
request messages that, for example, consume more computational resources than others.

For example, you want to count POST messages as being twice as "heavy" or expensive, as GET
messages. Therefore, you set the `MessageWeight` to 2 for a POST and 1 for a
GET. You can even set the `MessageWeight` to 0 so the request does not
affect the counter. In this example, if the quota is 10 messages per minute and
the `MessageWeight` for POST requests is `2`, then the quota will
permits 5 POST requests in any 10 minute interval. Any additional request, POST or GET,
before the counter resets are rejected.

A value representing `MessageWeight` must be specified by a flow
variable, and can be extracted from HTTP headers, query parameters, an XML or JSON request
payload, or any other flow variable. For example, you set it in a header named
`weight`:

```
<MessageWeight ref="message_weight"/>
```

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | Integer |

## Flow variables

The following predefined Flow variables are automatically populated when a Quota policy
executes. For more information about Flow variables, see [Variables reference](https://docs.apigee.com/api-platform/reference/variables-reference).

| Variables | Type | Permissions | Description |
|---|---|---|---|
| ratelimit.{policy_name}.allowed.count | Long | Read-Only | Returns the allowed quota count |
| ratelimit.{policy_name}.used.count | Long | Read-Only | Returns the current quota used within a quota interval |
| ratelimit.{policy_name}.available.count | Long | Read-Only | Returns the available quota count in the quota interval |
| ratelimit.{policy_name}.exceed.count | Long | Read-Only | Returns 1 after the quota is exceeded. |
| ratelimit.{policy_name}.total.exceed.count | Long | Read-Only | Returns 1 after the quota is exceeded. |
| ratelimit.{policy_name}.expiry.time | Long | Read-Only | Returns the UTC time in milliseconds which determines when the quota expires and new quota interval starts. When the Quota policy type is `rollingwindow`, this value is not valid because the quota interval never expires. |
| ratelimit.{policy_name}.identifier | String | Read-Only | Returns the (client) identifier reference attached to the policy |
| ratelimit.{policy_name}.class | String | Read-Only | Returns the class associated with the client identifier |
| ratelimit.{policy_name}.class.allowed.count | Long | Read-Only | Returns the allowed quota count defined in the class |
| ratelimit.{policy_name}.class.used.count | Long | Read-Only | Returns the used quota within a class |
| ratelimit.{policy_name}.class.available.count | Long | Read-Only | Returns the available quota count in the class |
| ratelimit.{policy_name}.class.exceed.count | Long | Read-Only | Returns the count of requests that exceeds the limit in the class in the current quota interval |
| ratelimit.{policy_name}.class.total.exceed.count | Long | Read-Only | Returns the total count of requests that exceeds the limit in the class across all quota intervals, so it is the sum of `class.exceed.count` for all quota intervals. |
| ratelimit.{policy_name}.failed | Boolean | Read-Only | Indicates whether or not the policy failed (true or false). |

## Error reference

This section describes the fault codes and error messages that are returned and fault variables that are set by Edge when this policy triggers an error.
This information is important to know if you are developing fault rules to
handle faults. To learn more, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors) and [Handling
faults](https://docs.apigee.com/api-platform/fundamentals/fault-handling).

### Runtime errors

These errors can occur when the policy executes.

> [!IMPORTANT]
> Need help resolving an error? Click in the Fix column for detailed troubleshooting information.

> [!IMPORTANT]
> **Tip:** Use [API Monitoring](https://docs.apigee.com/api-monitoring) to investigate fault codes and diagnose issues faster. See [Set up a policy fault code alert](https://docs.apigee.com/api-monitoring/alerts-notifications#fault-code-alert) for an example. See [Fault code reference](https://docs.apigee.com/api-monitoring/fault-codes) for a complete list of all fault codes that you can handle with API Monitoring.

| Fault code | HTTP status | Cause | Fix |
|---|---|---|---|
| `policies.ratelimit.FailedToResolveQuotaIntervalReference` | 500 | Occurs if the `<Interval>` element is not defined within the Quota policy. This element is mandatory and used to specify the interval of time applicable to the quota. The time interval can be minutes, hours, days, weeks, or months as defined with the `<TimeUnit>` element. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/runtime/quota-runtime-errors#failedtoresolvequotaintervalreference) |
| `policies.ratelimit.FailedToResolveQuotaIntervalTimeUnitReference` | 500 | Occurs if the `<TimeUnit>` element is not defined within the Quota policy. This element is mandatory and used to specify the unit of time applicable to the quota. The time interval can be in minutes, hours, days, weeks, or months. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/runtime/quota-runtime-errors#failedtoresolvequotaintervaltimeunitreference) |
| `policies.ratelimit.InvalidMessageWeight` | 500 | Occurs if the value of the `<MessageWeight>` element specified through a flow variable is invalid (a non-integer value). | [](https://docs.apigee.com/api-platform/troubleshoot/policies/runtime/quota-runtime-errors#invalidmessageweight) |
| `policies.ratelimit.QuotaViolation` | 500 | The quota limit was exceeded. | N/A |

### Deployment errors

> [!IMPORTANT]
> Need help resolving an error?Click in the Fix column for detailed troubleshooting information.

| Error name | Cause | Fix |
|---|---|---|
| `InvalidQuotaInterval` | If the quota interval specified in the `<Interval>` element is not an integer, then the deployment of the API proxy fails. For example, if the quota interval specified is 0.1 in the `<Interval>` element, then the deployment of the API proxy fails. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidquotainterval) |
| `InvalidQuotaTimeUnit` | If the time unit specified in the `<TimeUnit>` element is unsupported, then the deployment of the API proxy fails. The supported time units are `minute`, `hour`, `day`, `week`, and `month`. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidquotatimeunit) |
| `InvalidQuotaType` | If the type of the quota specified by the `type` attribute in the `<Quota>` element is invalid, then the deployment of the API proxy fails. The supported quota types are `default`, `calendar`, `flexi`, and `rollingwindow`. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidquotatype) |
| `InvalidStartTime` | If the format of the time specified in the `<StartTime>` element is invalid, then the deployment of the API proxy fails. The valid format is `yyyy-MM-dd HH:mm:ss`, which is the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time format. For example, if the time specified in the `<StartTime>` element is `7-16-2017 12:00:00` then the deployment of the API proxy fails. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidstarttime) |
| `StartTimeNotSupported` | If the `<StartTime>` element is specified whose quota type is not `calendar` type, then the deployment of the API proxy fails. The `<StartTime>` element is supported only for the `calendar` quota type. For example, if the `type` attribute is set to `flexi` or `rolling window` in the `<Quota>` element, then the deployment of the API proxy fails. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#starttimenotsupported) |
| `InvalidTimeUnitForDistributedQuota` | If the `<Distributed>` element is set to `true` and the `<TimeUnit>` element is set to `second` then the deployment of the API proxy fails. The timeunit `second` is invalid for a distributed quota. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidtimeunitfordistributedquota) |
| `InvalidSynchronizeIntervalForAsyncConfiguration` | If the value specified for the `<SyncIntervalInSeconds>` element within the `<AsynchronousConfiguration>` element in a Quota policy is less than zero, then the deployment of the API proxy fails. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidsynchronizeintervalforasyncconfiguration) |
| `InvalidAsynchronizeConfigurationForSynchronousQuota` | If the value of the `<AsynchronousConfiguration>` element is set to `true` in a Quota policy, which also has asynchronous configuration defined using the `<AsynchronousConfiguration>` element, then the deployment of the API proxy fails. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/deployment/quota-deployment-errors#invalidasynchronizeconfigurationforsynchronousquota) |

### Fault variables

These variables are set when this policy triggers an error. For more information, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors).

| Variables | Where | Example |
|---|---|---|
| `fault.name="fault_name"` | <var translate="no">fault_name</var> is the name of the fault, as listed in the [Runtime errors](https://docs.apigee.com/api-platform/reference/policies/quota-policy#runtime-errors) table above. The fault name is the last part of the fault code. | `fault.name Matches "QuotaViolation"` |
| `ratelimit.policy_name.failed` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `ratelimit.QT-QuotaPolicy.failed = true` |

### Example error response

> [!NOTE]
> **Note:** For error handling, the best practice is to trap the `errorcode` part of the error response. Do not rely on the text in the `faultstring`, because it could change.

```
{  
   "fault":{  
      "detail":{  
         "errorcode":"policies.ratelimit.QuotaViolation"
      },
      "faultstring":"Rate limit quota violation. Quota limit  exceeded. Identifier : _default"
   }
}
```

### Example fault rule

```
<FaultRules>
    <FaultRule name="Quota Errors">
        <Step>
            <Name>JavaScript-1</Name>
            <Condition>(fault.name Matches "QuotaViolation") </Condition>
        </Step>
        <Condition>ratelimit.Quota-1.failed=true</Condition>
    </FaultRule>
</FaultRules>
```

> [!NOTE]
> **Note:** Currently, the Quota policy returns a status code of 500 when it enforces a rate limit. If you use the Apigee-managed Edge service, and you would like to have your Quota policy return 429, contact [Apigee Edge Support](https://docs.apigee.com/api-platform/troubleshoot/support). to have the `features.isHTTPStatusTooManyRequestEnabled` property enabled. See [this community article](https://discuss.google.dev/t/http-429-as-default-status-code-for-quota-policy-violation/17548) for additional details.

> [!NOTE]
> **Private Cloud:** If you're an Edge for Private Cloud customer, you can set this property with the following API call:
>
> **Note**: When updating properties, you must pass all existing properties to the API,
> even if they are not being changed. If you omit properties in the payload, the properties are
> removed.
>
> ```
> curl -u email:password -X POST -H "Content-type:application/xml" \
>   http://edge-management-server:8080/v1/o/myorg \
>   -d '<Organization type="trial" name="MyOrganization">
>     <DisplayName>MyOrganization</DisplayName>
>     <Environments/>
>     <Properties>
>         <Property name="features.isHTTPStatusTooManyRequestEnabled">true</Property>
>     </Properties>
>   </Organization>'
> ```

## Schemas

> [!NOTE]
> **Sample:** See our [GitHub
> repository](https://github.com/apigee/api-platform-samples/tree/master/schemas/policy) samples for the most recent schemas.

## Related topics

[ResetQuota policy](https://docs.apigee.com/api-platform/reference/policies/reset-quota-policy)

[SpikeArrest
policy](https://docs.apigee.com/api-platform/reference/policies/spike-arrest-policy)

[Comparing
Quota, Spike Arrest, and Concurrent Rate Limit Policies](https://docs.apigee.com/api-platform/develop/comparing-quota-spike-arrest-and-concurrent-rate-limit-policies)