Send Docs Feedback

Quota policy


Use the Quota policy to configure the number of request messages that an app is allowed to submit to an API over the course of an hour, day, week, or month.

Don't use Quota to shield against overall traffic spikes. For that, use the Spike Arrest policy. See Spike Arrest policy.

Need help deciding which rate limiting policy to use? See Comparing Quota, Spike Arrest, and Concurrent Rate Limit Policies.


While you can attach this policy anywhere in the flow, we recommend that you attach it in one of the following locations so that it can immediately check the quota count before allowing the message flow to continue.

ProxyEndpoint TargetEndpoint
    PreFlow Flow PostFlow PreFlow Flow PostFlow    
    PostFlow Flow PreFlow PostFlow Flow PreFlow    


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

<Quota name="MyQuota">
  <Identifier ref="request.header.clientId"/> 
  <Allow count="10000"/>

Use this sample code to enforce a quota of 10,000 calls. The policy starts and stops the counter based on the interval and unit of time of the timestamp for the first request message received by the API proxy.

Because the TimeUnit is hour, the quota counter will start at the top of each hour and count until the end of the hour. So imagine that the counter starts at 2014-07-08 07:00:00, then resets to 0 at 2014-07-08 08:00:00 (1 hour from the start time). Now imagine that the first message is received at 2014-07-08 07:35:28. If the message count reaches 10,000 before 2014-07-08 08:00:00, calls beyond that count will be rejected until the count resets at the top of the hour.

The start time is the clock or calendar start time of the defined TimeUnit value, such as hour, day, week, or month. The end time is based on the elapsing of the Interval value in the defined TimeUnit.

If the counter reaches the 10,000-call quota before the end of the hour, calls beyond 10,000 will be rejected.

Note that the sample code does not include the type attribute in the Quota element. When no type is defined, the default value calendar is used. In this case, do not provide an explicit StartTime value. The counter will start based on the time at which the first message request is received by the API proxy. If you provide an explicit StartTime value, you will receive an error.

<Quota name="QuotaPolicy" type="calendar">
  <Identifier ref="request.header.clientId"/> 
  <StartTime>2014-02-18 10:00:00</StartTime>
  <Allow count="99"/>
  <MessageWeight ref="request.header.weight"/>

For a Quota with type set to calendar, you must define an explicit StartTime value. If you do not provide a StartTime value, you will receive an error. The Quota counter for each app is refreshed based on the Interval and TimeUnit that you set.

For example, the Quota of type calendar above begins counting at 10 am on February 18, 2014, and will refresh every 5 hours.

<Quota name="CheckQuota"> 
  <Interval ref="apiproduct.developer.quota.interval"/>
  <TimeUnit ref="apiproduct.developer.quota.timeunit"/>
  <Allow countRef="apiproduct.developer.quota.limit"/>
  <Identifier ref="client_id"/>

Dynamic Quotas enable you to configure a single Quota policy that enforces different Quota settings for different apps, based on the identity of the requesting app. (Another term for Quota settings in this context is "Service Plan". The dynamic Quota checks the apps' "Service Plan" and then enforces those settings.)

Dynamic Quota settings are populated at runtime by resolving an app identifier to an API product. The Identifier can be a field in the request that is unique to each app. For API proxies where OAuth is enforced, you can use client_id as the Identifier, as demonstrated in the sample policy below.

If an API Key is used to validate an inbound request, then, assuming that the policy is named "VerifyApiKey", then the dynamic Quota policy should be configured as follows:

<Quota name="ratelimiting.developer.quotas"> 
  <Identifier ref="request.queryparam.apikey" /> 
  <Interval ref="verifyapikey.VerifyApiKey.apiproduct.developer.quota.interval" /> 
  <TimeUnit ref="verifyapikey.VerifyApiKey.apiproduct.developer.quota.timeunit" /> 
  <Allow countRef="verifyapikey.VerifyApiKey.apiproduct.developer.quota.limit" /> 

The example above uses the variable client_id to identify the requesting app. This works as long as the request message contains a client_id (associated with an OAuth-enabled request).

Note that the value for verifyapikey.VerifyApiKey will vary based on the name of the OAuthV2 policy of type VerifyApiKey that is used to check the API key. If your policy is called, for example, KeyValidationPolicy, then the variable name will be verifyapikey.KeyValidationPolicy.

<Quota name="QuotaPolicy">
  <Allow count="100">
    <Class ref="accesstoken.developer_segment">
      <Allow class="platinum" count="10000"/>
      <Allow class="silver" count="1000" />

You can also set Quota limits dynamically by using a class-based Quota count. In the example above, a quota class is created from a custom attribute in the access token profile. (To make this work, you would need to add a custom attribute called developer_segment to your access token profiles.) If the value of the attribute developer_segment is platinum, the app presenting the access token is permitted 10000 requests per day, while silver is permitted 1000 requests per day.)

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.

<Quota async="false" continueOnError="false" enabled="true" name="Quota-3" type="calendar">
   <DisplayName>Quota 3</DisplayName>
   <Allow count="2000" countRef="request.header.allowed_quota"/>
   <Interval ref="request.header.quota_count">1</Interval>
   <TimeUnit ref="request.header.quota_timeout">month</TimeUnit>
   <StartTime>2014-7-16 12:00:00</StartTime>

<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

Use to set when the quota counter starts counting usage. If you do not explicitly define a type value, the quota configuration will default to calendar.

Valid values include:

  • calendar: Select to configure a quota based on an explicit start time. The Quota counter for each app is refreshed based on the <Interval> and <TimeUnit> values that you set. For a sample, see the Start Time tab in the Samples section.
  • rollingwindow: Select to configure a quota that uses a "rolling window" counter that advances by the time interval that you specify. You don't specify a <StartTime> value. Instead, the <StartTime> for the counter is the time when the first message is received from the client plus the interval that you define. A counter is kept for each client ID (consumer key). Thus, the counter will reset to zero when the <Interval> value you have defined has passed. This enables you to configure a quota in which an app is indefinitely allowed 1,000 requests every 24 hours.
  • flexi: Select to configure a quota that causes the counter to begin when the first request message is received from an app. The <StartTime> value is dynamic and every app has its own <StartTime> based on the the time when the first request is received. This enables you to provide Quotas that support one-week, one-month, or 6-month access to your API, customized for each app.
calendar Optional

The following attributes are common to all policy parent elements.

Attribute Description Default Presence

The internal name of the policy. Characters you can use in the name are restricted to: A-Z0-9._\-$ %. However, the Edge management UI enforces additional restrictions, such as automatically removing characters that are not alphanumeric.

Optionally, use the <DisplayName> element to label the policy in the management UI proxy editor with a different, natural-language name.

N/A Required

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

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

Note: This attribute does not make the policy execute asynchronously.

When set to true, policy execution is offloaded to a different thread, leaving the main thread free to handle additional requests. When the offline processing is complete, the main thread comes back and finishes handling the message flow. In some cases, setting async to true improves API proxy performance. However, overusing async can hurt performance with too much thread switching.

To use asynchronous behavior in API proxies, see JavaScript callouts.

false Optional

<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>


If you omit this element, the the value of the policy's name attribute is used.

Presence: Optional
Type: String


<Allow> element

Specifies a message count for the quota.

To set the allowable message count, use the attributes covered below.

<Allow count="2000" countRef="request.header.allowed_quota"/> 
Default: N/A
Presence: Optional
Type: Integer


Attribute Description Default Presence

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.

Note: If a countref attribute is specified for the Allow element, it takes precedence over the quota set by the Allow count attribute value.

2000 Optional

Use to specify a message count for a quota that takes precedence over the count attribute.

For example, the element <Allow count="2000" countRef="request.header.allowed_quota"/> has a count header (countRef="request.header.allowed_quota") along with the count value of 2000.

request.header.allowed_quota Optional

<Interval> element

Use to specify the interval of time (in hours, minutes, or days as defined by TimeUnit) applicable to the quota.

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

<Interval ref="request.header.quota_count">1</Interval>
Default: 1
Presence: Required
Type: Integer


Attribute Description Default Presence


request.header.quota_count 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.

If you set Distributed to true, you cannot use a TimeUnit value of second.

<TimeUnit ref="request.header.quota_timeout">month</TimeUnit>
Default: month
Presence: Required


Select from second, minute, hour, day, or month.


Attribute Default Presence
ref request.header.quota_timeout Optional

<StartTime> element

You must provide an explicit StartTime when type is explicitly set to calendar. Use only for quota policies with type explicitly set to calendar. If you provide an explicit StartTime value when no type value is provided, you will receive an error.

Use to specify the date and time when the quota counter will begin counting, regardless of whether any requests have been received from any apps.

<StartTime>2014-7-16 12:00:00</StartTime>
Default: <current date> 12:00:00
Presence: Provide only when type is explicitly set to calendar.

String in ISO 8601 date and time format.

<Distributed> element

Set to true to specify that a central counter should be maintained and continuously synchronized across all Apigee Edge message processors.

For example, if the quota limit is 10 messages per hour and 2 message processors are being used, the quota count total is continuously updated on both message processors. 

Default: false
Presence: Optional
Type: Boolean

<Synchronous> element

Set to true to update the distributed quota counter synchronously. This means that the update to the counter will be made at the same time the API call is quota-checked. Set to true if it is essential that you not allow any API calls over the quota.

Know that by implementing synchronous updates to the counter, there is the potential for performance impacts and lower throughputs.

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.

Default: false
Presence: Optional
Type: Boolean

<AsynchronousConfiguration> element

Configures the synchronization interval amongst distributed quota counters when the policy is configured to make calls asynchronously (when <Synchronous> is 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.

<!-- or -->
Default: 10 seconds, but not set in XML
Presence: Optional, except when <Synchronous> is set to false.


<AsynchronousConfiguration>/<SyncIntervalInSeconds> element

Use to override the default asynchronous update interval of 10 seconds enforced by the AsynchronousConfiguration element.

Default: 20
Presence: Optional


<AsynchronousConfiguration>/<SyncMessageCount> element

Use to override the default asynchronous update interval of 10 seconds enforced by the AsynchronousConfiguration element.

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


This example specifies that the quota count is updated every 5 requests across all Apigee message processors.

Default: 5
Presence: Optional


<Identifier> element

Use the <Identifier> element to uniquely identify and apply quota against an individual client app or developer. You can use a variety of variables to indicate a unique developer or app, whether you're using custom variables or predefined variables, such as those available with the Verify API Key policy. See also the Variables reference.

If you don't use this element, all calls made to the API proxy are counted against the quota.

This element is also discussed in the following Apigee Community post:

<Identifier ref="client_id"/>
Default: N/A
Presence: Optional



Attribute Description Default Presence

For the Quota policy to work, each app requires a unique identifier that it presents with each request. The identifier can be customized. It can be any HTTP header, query parameter, form parameter, or message content that is unique to each consumer app.

You specify the token that will identify each app by using the <Identifier> element's ref attribute to define a reference to a variable.

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. For more information, see 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 may want calculate POST messages as being twice as "heavy" or expensive, as GET messages.

A value representing MessageWeight can be extracted from HTTP headers, query parameters, or an XML or JSON request payload.

For 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. The quota will be violated starting with the sixth message and messages will start being rejected.

Default: N/A
Presence: Optional


<PreciseAtSecondsLevel> element

Set to true to have the quota record to a precision of, or at intervals of, one second.

For example, use this setting when you have a quota with the TimeUnit element set to minutes and you need to ensure that the quota is counted and enforced by the second.

Set to false to have the quota record to a precision of, or at intervals of, one minute.

Default: N/A
Presence: Optional


Flow variables

The following predefined Flow variables are automatically populated when a Quota policy executes. For more information about Flow variables, see 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 counter
ratelimit.{policy_name}.exceed.count Long Read-Only Returns the count that exceeds the limit in the current counter
ratelimit.{policy_name}.total.exceed.count Long Read-Only Returns the total count that exceeds the limit, because the quota policy is attached
ratelimit.{policy_name}.expiry.time Long Read-Only Returns the time in milliseconds, which determines when the quota expires and new quota counter starts
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 that exceeds the limit in the class
ratelimit.{policy_name} Long Read-Only Returns the total count that exceeds the limit in the class, because the Quota policy is attached

Error codes

The default format for error codes returned by Policies is:

  "code" : " {ErrorCode} ",
  "message" : " {Error message} ",
  "contexts" : [ ]
Error Code Message

Rate limit quota violation. Quota limit exceeded.

InvalidMessageWeight Invalid message weight value {0}
ErrorLoadingProperties Error loading rate limit properties from {0}
FailedToResolveQuotaIntervalReference Failed to resolve quota interval reference {0} in quota policy {1}
InvalidQuotaInterval Invalid quota interval {0} in quota policy {1}
FailedToResolveQuotaIntervalTimeUnitReference Failed to resolve quota time unit reference {0} in quota policy {1}
InvalidQuotaTimeUnit Invalid quota time unit {0} in quota policy {1}
InvalidTimeUnitForDistributedQuota Invalid timeunit {0} for distributed quota
InvalidSynchronizeIntervalForAsyncConfiguration 'SyncIntervalInSeconds' should be a value greater than zero
InvalidSynchronizeMessageCountForAsyncConfiguration 'SyncMessageCount' should be a value greater than zero
InvalidAsynchronizeConfigurationForSynchronousQuota AsynchronousConfiguration is not valid for synchronous quota
InvalidQuotaType Invalid Quotatype:{0};Valid Types are calendar,rollingwindow,flexi
InvalidStartTime Invalid Starttime:{0}; Start Time should be of the format 'yyyy-MM-dd HH:mm:ss
StartTimeNotSupported Starttime is not supported for quotatype {0}. Starttime is supported only for 'calendar' based type

Apigee Edge organizations can be configured to return an HTTP status code of 429 (Too Many Requests) for all requests that exceed a rate limit set by a Quota policy. The default configuration returns an HTTP status code of 500 (Internal Server Error).

Contact Apigee Support to have the features.isHTTPStatusTooManyRequestEnabled property set to true for organizations for which you want Quota policy violations to return an HTTP status code of 429.

Edge for Private Cloud customers can set this property with the following API call:

curl -u email:password -X POST -H "Content-type:application/xml" http://host:8080/v1/o/myorg -d \
"<Organization type="trial" name="MyOrganization">
        <Property name="features.isHTTPStatusTooManyRequestEnabled">true</Property>


See our GitHub repository samples for the most recent schemas.

Usage notes

A Quota is an allotment of request messages that an app is allowed to submit to an API over the course of an hour, a day, a week, or a month. To support Quota enforcement, Apigee Edge maintains counters that tally the number of requests received from individual apps. 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.

While the Quota counts for a single API proxy can be distributed across message processors, Quota counts 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 applies to individual proxies only, and any distribution across message processors occurs only for an individual proxy.

When an app 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; the app is blocked from making additional requests 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.

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.

Time notation

All Quotas are set to the Coordinated Universal Time (UTC) time zone.

Quota time notation follows the international standard date notation defined in International Standard 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

For info on configuring API products with quota limits, see Create API products.

Related topics

Reset Quota policy

Spike Arrest policy

Comparing Quota, Spike Arrest, and Concurrent Rate Limit Policies

Help or comments?