—Rate this article—
 

Quota policy

Quota policy

About | Samples | Element reference | Flow variables | Error codes | Schemas | Usage notes | Related topics

What

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.

Where

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    
Request          
                Response
    PostFlow Flow PreFlow PostFlow Flow PreFlow    

Samples

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

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

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.

For example, let's say that the first message is received at 2014-07-08 07:35:28. The quota counter will start at 2013-07-08 07:00:00 and the counter will stop and reset to 0 at 2013-07-08 08:00:00 (1 hour from the start time). 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. It also does not include a StartTime element. When no StartTime is defined, the counter starts based on the time at which the first message request is received by the API proxy.

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

In the calendar Quota, you define an explicit start time. 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"/>
</Quota>

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" /> 
</Quota>

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">
  <Interval>1</Interval>
  <TimeUnit>day</TimeUnit>
  <Allow count="100">
    <Class ref="accesstoken.developer_segment">
      <Allow class="platinum" count="10000"/>
      <Allow class="silver" count="1000" />
    </Class>
  </Allow>
</Quota>

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>
   <Distributed>false</Distributed>
   <Synchronous>false</Synchronous>
   <TimeUnit ref="request.header.quota_timeout">month</TimeUnit>
   <StartTime>2014-7-16 12:00:00</StartTime>
   <AsynchronousConfiguration>
      <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
      <SyncMessageCount>5</SyncMessageCount>
   </AsynchronousConfiguration>
   <Identifier/> 
   <MessageWeight/> 
   <PreciseAtSecondsLevel/>
</Quota>

<Quota> attributes

<Quota async="false" continueOnError="false" enabled="true" name="Quota-3" type="calendar">
Attribute Description Default Presence
async

Set to true to specify that the policy should be run in a thread pool different than the pool servicing the request/response flow. Default is false.

Note: This setting is only used for for internal optimization. Contact Apigee support at the Support Portal for more information.

false Optional
continueOnError

Most policies are expected to return an error when a failure occurs (for example, when a Quota is exceeded). By setting this attribute to true, Flow execution continues on failure.

false Optional
enabled Determines whether a policy is enforced or not. If set to false, a policy is 'turned off', and not enforced (even though the policy remains attached to a Flow). true Optional
name

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
type

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

<DisplayName> element

A natural-language name that labels the policy in the management UI proxy editor. If omitted, the policy name attribute is used.

<DisplayName>Custom label used in UI</DisplayName>
Default: Policy name attribute value.
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

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.

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
countRef

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

Attributes

Attribute Description Default Presence
ref

 

request.header.quota_count Optional

<Distributed> element

Set to true to specify that a central counter should be maintained and continuously updated by all Apigee Edge management servers.

For example, if the quota limit is 10 messages per hour and 2 servers are assigned, the quota count total is continuously updated on both servers. 

Note: This setting does not apply to Apigee Edge free trial accounts, since all Quota counts in the Cloud are, by default, distributed.

<Distributed>false</Distributed>
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.

<Synchronous>false</Synchronous>
Default: false
Presence: Optional
Type: Boolean

<TimeUnit> element

Use to specify the unit of time 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.

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

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

String.

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

Attributes

Attribute Default Presence
ref request.header.quota_timeout Optional

<StartTime> element

Use only for quota policies with type set to calendar.

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: Optional
Type:

String in ISO 8601 date and time format.

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

<AsynchronousConfiguration>
   <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
<!-- or -->
   <SyncMessageCount>5</SyncMessageCount>
</AsynchronousConfiguration>
Default: 10 seconds, but not set in XML
Presence: Optional, except when <Synchronous> is set to false.
Type:

Integer

<AsynchronousConfiguration>/<SyncIntervalInSeconds> element

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

<AsynchronousConfiguration>
   <SyncIntervalInSeconds>20</SyncIntervalInSeconds>
</AsynchronousConfiguration>
Default: 20
Presence: Optional
Type:

Integer

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

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

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

Default: 5
Presence: Optional
Type:

Integer

<Identifier> element

Quotas are counted for individual apps. Use the <Identifier> element to uniquely identify an individual client app.

<Identifier ref="request.header.client_id"/>
Default: N/A
Presence: Optional
Type:

String

Attributes

Attribute Description Default Presence
ref

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 AccessEntity policy to retrieve the appropriate API product settings. For more information, see Retrieve API product settings using GetAPIProduct.

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

Integer

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

<PreciseAtSecondsLevel>true</PreciseAtSecondsLevel>
Default: N/A
Presence: Optional
Type:

Boolean

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}.class.total.exceed.count 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
QuotaViolation

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.

 

Schemas

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.

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, 2013-02-04 represents February 4, 2013.

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 2013-02-04 24:00:00 is the same date and time as 2013-02-05 00:00:00. The latter is usually the preferred notation.

Related topics

Reset Quota policy

Spike Arrest policy

Comparing Quota, Spike Arrest, and Concurrent Rate Limit Policies

Help or comments?

  • Something's not working: See Apigee Support
  • Something's wrong with the docs: Click Send Feedback in the lower right.
    (Incorrect? Unclear? Broken link? Typo?)