This page applies to Apigee and Apigee hybrid.
View Apigee Edge documentation.
The SpikeArrest policy protects against traffic surges with the <Rate>
element. This
element throttles the number of requests processed by an API proxy and sent to a backend,
protecting against performance lags and downtime.
This policy is a Standard policy and can be deployed to any environment type. For information on policy types and availability with each environment type, see Policy types.
The difference between SpikeArrest and Quota
The Quota policy configures the number of request messages that a client app is allowed to submit to an API over the course of an hour, day, week, or month. The Quota policy enforces consumption limits on client apps by maintaining a distributed counter that tallies incoming requests.
Use Quota to enforce business contracts or SLAs with developers and partners, rather than for operational traffic management. Use SpikeArrest to protect against sudden spikes in API traffic. See also Comparing Quota and SpikeArrest policies.
Videos
These videos discuss use cases for this policy:
Why You Need It
Compare Quota Policy
<SpikeArrest>
element
Defines the SpikeArrest policy.
Default Value | See Default Policy tab, below |
Required? | Optional |
Type | Complex object |
Parent Element | n/a |
Child Elements |
<Identifier> <MessageWeight> <Rate> (Required)<UseEffectiveCount> |
Syntax
The <SpikeArrest>
element uses the following syntax:
<SpikeArrest continueOnError="[false|true]" enabled="[true|false]" name="policy_name" > <DisplayName>display_name</DisplayName> <Properties/> <Identifier ref="flow_variable"/> <MessageWeight ref="flow_variable"/> <Rate ref="flow_variable">rate[pm|ps]</Rate> <UseEffectiveCount>[false|true]</UseEffectiveCount> </SpikeArrest>
Default Policy
The following example shows the default settings when you add a SpikeArrest policy to your flow in the UI:
<SpikeArrest async="false" continueOnError="false" enabled="true" name="Spike-Arrest-1"> <DisplayName>Spike Arrest-1</DisplayName> <Properties/> <Identifier ref="request.header.some-header-name"/> <MessageWeight ref="request.header.weight"/> <Rate>30ps</Rate> <UseEffectiveCount>false</UseEffectiveCount> </SpikeArrest>
This element has the following attributes that are common to all policies:
Attribute | Default | Required? | Description |
---|---|---|---|
name |
N/A | Required |
The internal name of the policy. The value of the Optionally, use the |
continueOnError |
false | Optional | 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. See also:
|
enabled |
true | 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. |
async |
false | Deprecated | This attribute is deprecated. |
Examples
The following examples show some of the ways in which you can use the SpikeArrest policy:
Example 1
The following example sets the rate to five per second:
<SpikeArrest name="Spike-Arrest-1"> <Rate>5ps</Rate> <UseEffectiveCount>false</UseEffectiveCount> </SpikeArrest>
This sample policy allows a maximum of 5 requests per second. Via smoothing, it is enforced as a maximum of one request for every 200 millisecond (1000/5) interval.
Example 2
The following example sets the rate to 12 per minute:
<SpikeArrest name="Spike-Arrest-1"> <Rate>12pm</Rate> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
This sample policy allows a maximum of 12 requests per minute at the rate of one request per 5 second (60/12) interval. If there is more than one request in the 5 second interval, such requests are allowed (no smoothing) provided the number of requests is less than the configured rate limit of 12 per minute.
Example 3
The following example restricts requests to 12 per minute (one request allowed every five seconds, or 60/12):
<SpikeArrest name="Spike-Arrest-1"> <Rate>12pm</Rate> <Identifier ref="client_id" /> <MessageWeight ref="request.header.weight" /> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
In addition, the <MessageWeight>
element accepts a custom value (the
weight
header) that adjusts message weights for specific apps or clients. This
provides additional control over throttling for entities that are identified with the
<Identifier>
element.
Example 4
The following example instructs SpikeArrest to look for a runtime value set via the
request that is passed in as the request.header.runtime_rate
flow variable:
<SpikeArrest name="Spike-Arrest-1"> <Rate ref="request.header.runtime_rate" /> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
The value of the flow variable must be in the form of intpm
or
intps
.
To try this example, execute a request like the following:
curl http://myorg-myenv.apigee.net/price -H 'runtime_rate:30ps'
Child element reference
This section describes the child elements of <SpikeArrest>
.
<DisplayName>
Use in addition to the name
attribute to label the policy in the
management UI proxy editor with a different, more natural-sounding name.
The <DisplayName>
element is common to all policies.
Default Value | N/A |
Required? | Optional. If you omit <DisplayName> , the value of the
policy's name attribute is used. |
Type | String |
Parent Element | <PolicyElement> |
Child Elements | None |
The <DisplayName>
element uses the following syntax:
Syntax
<PolicyElement> <DisplayName>POLICY_DISPLAY_NAME</DisplayName> ... </PolicyElement>
Example
<PolicyElement> <DisplayName>My Validation Policy</DisplayName> </PolicyElement>
The <DisplayName>
element has no attributes or child elements.
<Identifier>
Lets you choose how to group the requests so that the SpikeArrest policy can be applied based on the client. For example, you can group requests by developer ID, in which case each developer's requests will count towards their own SpikeArrest rate and not all requests to the proxy.
Use in conjunction with <MessageWeight>
element for more fine-grained
control over request throttling.
If you leave the <Identifier>
element empty, one rate limit is enforced for all requests
into that API proxy.
Default Value | n/a |
Required? | Optional |
Type | String |
Parent Element |
<SpikeArrest>
|
Child Elements | None |
Syntax
<SpikeArrest continueOnError="[false|true]" enabled="[true|false]" name="policy_name" > <Identifier ref="flow_variable"/> </SpikeArrest>
Example 1
The following example applies the SpikeArrest policy per developer ID:
<SpikeArrest name="Spike-Arrest-1"> <Identifier ref="developer.id"/> <Rate>42pm</Rate/> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
The following table describes the attributes of <Identifier>
:
Attribute | Description | Default | Presence |
---|---|---|---|
ref |
Identifies the variable by which SpikeArrest groups incoming requests. You can use any flow variable to indicate a unique client, such those available with the VerifyAPIKey policy. You can also set custom variables using the JavaScript policy or the AssignMessage policy. | n/a | Required |
This element is also discussed in this Apigee Community post.
<MessageWeight>
Specifies the weighting defined for each message. Message weight modifies the impact of a single request on the calculation of the SpikeArrest rate. Message weight can be any flow variable, such as an HTTP header, query parameter, form parameter, or message body content. You can also use custom variables using the JavaScript policy or the AssignMessage policy.
Use in conjunction with <Identifier>
to further throttle requests by
specific clients or apps.
For example, if the SpikeArrest <Rate>
is 10pm
, and an app submits
requests with a weight of 2
, then only five messages per minute are permitted from
that client because each request counts as 2.
Default Value | n/a |
Required? | Optional |
Type | Integer |
Parent Element |
<SpikeArrest>
|
Child Elements | None |
Syntax
<SpikeArrest continueOnError="[false|true]" enabled="[true|false]" name="policy_name" > <MessageWeight ref="flow_variable"/> </SpikeArrest>
Example 1
The following example restricts requests to 12 per minute (one request allowed every five seconds, or 60/12):
<SpikeArrest name="Spike-Arrest-1"> <Rate>12pm</Rate> <Identifier ref="client_id" /> <MessageWeight ref="request.header.weight" /> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
In this example, <MessageWeight>
accepts a custom value (the weight
header in the request) that adjusts message weights for specific clients. This
provides additional control over throttling for entities that are identified with the
<Identifier>
element.
The following table describes the attributes of <MessageWeight>
:
Attribute | Description | Presence | Default |
---|---|---|---|
ref |
Identifies the flow variable that contains the message weight for the specific client. This can be any flow variable, such as an HTTP query param, header, or message body content. For more information, see Flow variables reference. You can also set custom variables using the JavaScript policy or the AssignMessage policy. | Required | N/A |
<Rate>
Specifies the rate at which to limit traffic spikes (or bursts) by setting the number of
requests that are allowed in per minute or per second intervals. You can also use this element in
conjunction with <Identifier>
and <MessageWeight>
to
smoothly throttle traffic at runtime by accepting values from the client. Use the
<UseEffectiveCount>
element to set the rate limiting algorithm used by the policy.
See the SpikeArrest section of the Limits page for the maximum rate limits you can specify.
Default Value | n/a |
Required? | Required |
Type | Integer |
Parent Element |
<SpikeArrest>
|
Child Elements | None |
Syntax
You can specify rates in one of the following ways:
- A static rate that you specify as the body of the
<Rate>
element - A variable value, which can be passed by the client; identify the
name of the flow variable using the
ref
attribute
<SpikeArrest continueOnError="[false|true]" enabled="[true|false]" name="policy_name" > <Rate ref="flow_variable">rate[pm|ps]</Rate> </SpikeArrest>
Valid rate values (either defined as a variable value or in the body of the element) must conform to the following format:
intps
(number of requests per second, smoothed into intervals of milliseconds)intpm
(number of requests per minute, smoothed into intervals of seconds)
The value of int must be a positive, non-zero integer.
Example 1
The following example sets the rate to five requests per second:
<SpikeArrest name="Spike-Arrest-1"> <Rate>5ps</Rate> <UseEffectiveCount>false</UseEffectiveCount> </SpikeArrest>
The policy smoothes the rate to one request allowed every 200 milliseconds (1000/5).
Example 2
The following example sets the rate to 12 requests per minute:
<SpikeArrest name="Spike-Arrest-1"> <Rate>12pm</Rate> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
This example policy smoothes the rate to one request allowed every five seconds (60/12).
The following table describes the attributes of <Rate>
:
Attribute | Description | Presence | Default |
---|---|---|---|
ref |
Identifies a flow variable that specifies the rate. This can be any flow
variable, such as an HTTP query parameter, header, or message body content, or a value
such as a KVM. For more information, see Flow variables reference.
You can also use custom variables using the JavaScript policy or the AssignMessage policy. If you define both For example: <Rate ref="request.header.custom_rate">1pm</Rate> In this example, if the client does not pass a You can use If you specify a value for |
Optional | n/a |
<UseEffectiveCount>
This element lets you choose between distinct spike arrest algorithms by setting the
value to true
or false
, as explained below:
true
If set to true
, SpikeArrest is distributed in a region. That means
request counts are synchronized across message processors (MPs) in a region. In addition, a "sliding window"
rate limiting algorithm is employed. This
algorithm provides consistent rate limit behavior and does not "smooth" the number of incoming
requests that can be sent to the backend. If a burst of requests are sent in a short time interval,
they are allowed as long as they do not exceed the configured
rate limit, as set in the <Rate>
element. For example:
<SpikeArrest name="Spike-Arrest-1"> <Rate>12pm</Rate> <Identifier ref="client_id" /> <MessageWeight ref="request.header.weight" /> <UseEffectiveCount>true</UseEffectiveCount> </SpikeArrest>
false (default)
If set to false
(the default),
the SpikeArrest policy uses a "token bucket" algorithm that smooths traffic spikes by
dividing the rate limit that you specify into smaller intervals. A drawback of
this approach is that multiple legitimate requests coming in over a short time
interval can potentially be denied.
For example, say you enter a rate of 30pm (30 requests per minute). In testing, you might think you could send 30 requests in 1 second, as long as they came within a minute. But that's not how the policy enforces the setting. If you think about it, 30 requests inside a 1-second period could be considered a mini spike in some environments.
- Per-minute rates get smoothed into full requests allowed in intervals
of seconds.
For example, 30pm gets smoothed like this:
60 seconds (1 minute) / 30pm = 2-second intervals, or 1 request allowed every 2 seconds. A second request inside of 2 seconds will fail. Also, a 31st request within a minute will fail. - Per-second rates get smoothed into full requests allowed in intervals
of milliseconds.
For example, 10ps gets smoothed like this:
1000 milliseconds (1 second) / 10ps = 100-millisecond intervals, or 1 request allowed every 100 milliseconds. A second request inside of 100ms will fail. Also, an 11th request within a second will fail.
Default Value | False |
Required? | Optional |
Type | Boolean |
Parent Element |
<SpikeArrest>
|
Child Elements | None |
The following table describes the attributes of the <UseEffectiveCount>
element:
Attribute | Description | Default | Presence |
---|---|---|---|
ref |
Identifies the variable that contains the value of <UseEffectiveCount> . This can be
any flow variable, such as an HTTP query param, header, or message body content. For more
information, see Flow variables reference. You can also set custom variables
using the JavaScript policy or the AssignMessage policy. |
n/a | Optional |
Flow variables
When a SpikeArrest policy executes, the following flow variable is populated:
Variable | Type | Permission | Description |
---|---|---|---|
ratelimit.policy_name.failed |
Boolean | Read-Only | Indicates whether or not the policy failed (true or
false ). |
For more information, see Flow variables reference.
Error reference
This section describes the fault codes and error messages that are returned and fault variables that are set by Apigee 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 and Handling faults.
Runtime errors
These errors can occur when the policy executes.
Fault code | HTTP status | Cause | Fix |
---|---|---|---|
policies.ratelimit.FailedToResolveSpikeArrestRate |
500 |
This error occurs if the reference to the variable containing the rate setting
within the <Rate> element cannot be resolved to a value within the SpikeArrest
policy. This element is mandatory and used to specify the spike arrest rate in
the form of intpm or intps . |
build |
policies.ratelimit.InvalidMessageWeight |
500 |
This error occurs if the value specified for the <MessageWeight> element through
a flow variable is invalid (a non-integer value). |
build |
policies.ratelimit.SpikeArrestViolation |
429 |
The rate limit is exceeded. |
Deployment errors
These errors can occur when you deploy a proxy containing this policy.
Error name | Cause | Fix |
---|---|---|
InvalidAllowedRate |
If the spike arrest rate specified in the <Rate> element of the SpikeArrest
policy is not an integer or if the rate does not have ps or pm as a suffix,
then the deployment of the API proxy fails. |
build |
Fault variables
These variables are set when a runtime error occurs. For more information, see What you need to know about policy errors.
Variables | Where | Example |
---|---|---|
fault.name="fault_name" |
fault_name is the name of the fault, as listed in the Runtime errors table above. The fault name is the last part of the fault code. | fault.name Matches "SpikeArrestViolation" |
ratelimit.policy_name.failed |
policy_name is the user-specified name of the policy that threw the fault. | ratelimit.SA-SpikeArrestPolicy.failed = true |
Example error response
Shown below is an example error response:
{ "fault":{ "detail":{ "errorcode":"policies.ratelimit.SpikeArrestViolation" }, "faultstring":"Spike arrest violation. Allowed rate : 10ps" } }
Example fault rule
Shown below is an example fault rule to handle a SpikeArrestViolation
fault:
<FaultRules> <FaultRule name="Spike Arrest Errors"> <Step> <Name>JavaScript-1</Name> <Condition>(fault.name Matches "SpikeArrestViolation") </Condition> </Step> <Condition>ratelimit.Spike-Arrest-1.failed=true</Condition> </FaultRule> </FaultRules>
The current HTTP status code for exceeding a rate limit set by a Quota or SpikeArrest policy is 429 (Too Many Requests).
To change the HTTP status code to 500 (Internal Server Error), set the features.isHTTPStatusTooManyRequestEnabled
property
to false
using the Update organization properties API.
For example:
curl -u email:password -X POST -H "Content-type:application/xml" http://apigee.googleapis.com/v1/organizations/myorg -d \ "<Organization type="trial" name="MyOrganization"> <Properties> <Property name="features.isHTTPStatusTooManyRequestEnabled">true</Property> . . . </Properties> </Organization>"
Schemas
Each policy type is defined by an XML schema (.xsd
). For reference, policy schemas
are available on GitHub.
Related topics
- Quota policy: Quota policy, to limit traffic on individual clients
- Rate-limiting for a rate limiting overview
- Comparing Quota and SpikeArrest policies