Http 429 as default status code for Quota policy violation

2 5 6,743

The default status code returned by Apigee's quota policy on quota violation (when quota is exceeded) is "Http 500 Internal Server Error". Below is an example of a quota policy failure message:

< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Date: Fri, 06 May 2016 20:16:25 GMT
< Server: Apigee Router
< Content-Length: 159
< Connection: keep-alive
<
{"fault":{"faultstring":"Rate limit quota violation. Quota limit  exceeded. Identifier : _default","detail":{"errorcode":"policies.ratelimit.QuotaViolation"}}

Since many of our customers wanted a non-5xx error code for quota policy violation, we introduced a new feature which allows you to override the default 500 status code with a 429 status code. This can be done by setting an organization level feature flag: features.isHTTPStatusTooManyRequestEnabled

PUT /v1/o/myorg

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Organization type="paid" name="myorg">
    <DisplayName>myorg</DisplayName>
    <Properties>
        <Property name="features.isHTTPStatusTooManyRequestEnabled">true</Property>
    </Properties>
</Organization>

Note: This is a management api call that can only be made with system admin credentials, so cloud customers should reach out to Apigee Support to have this changed.

This flag would turn the default response code of the quota policy to "HTTP/1.1 429 Too Many Requests" as follows:

< HTTP/1.1 429 Too Many Requests
< Content-Type: application/json
< Date: Fri, 06 May 2016 20:55:39 GMT
< Server: Apigee Router
< Content-Length: 159
< Connection: keep-alive
<
{"fault":{"faultstring":"Rate limit quota violation. Quota limit  exceeded. Identifier : _default","detail":{"errorcode":"policies.ratelimit.QuotaViolation"}}}

This has already been there in our platform for a while, and now we want to turn on the 429 status as the default, which means whether or not you have the org level feature flag the quota policy would return a 429 status code instead of 500. This is the desired behaviour and eliminates the need for customers to call Apigee Support to get the changes done.

This can break existing proxy bundles where customers may be checking for the http status and returning specific error messages or performing custom actions like generating an "email alert", or "logging to syslog" or other such actions. Those bundles would need to be modified in order to check for the new status code. Please note that change would not impact error or error description or any of the flow variables that get set during the quota violation, the only change is the Http status code that you see above.

If you have clients connecting to your API that depend on the 500 status code to trigger a retry or other custom logic, you could continue to have the existing behaviour by introducing a "RaiseFault" policy as demonstrated below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="RaiseFaultQuotaFailure">
    <DisplayName>RaiseFaultQuotaFailure</DisplayName>
    <Properties/>
    <FaultResponse>
        <Set>
            <Headers/>
            <Payload contentType="application/json"/>
            <StatusCode>500</StatusCode>
            <ReasonPhrase>Internal Server Error</ReasonPhrase>
            <Payload>\{"fault":\{"faultstring":"Rate limit quota violation. Quota limit  exceeded.","detail":\{"errorcode":"policies.ratelimit.QuotaViolation"}}}</Payload>
        </Set>
    </FaultResponse>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

Feel free to put in your own json response payload instead of the standard one depending on what your client is expecting. You can add this RaiseFault policy in the fault rules with a condition which matches the Quota violation. Refer to the flow below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <FaultRules>
        <FaultRule name="QuotaVialotion">
            <Step>
                <Name>RaiseFaultQuotaFailure</Name>
                <Condition>fault.name = "QuotaViolation"</Condition>
            </Step>
        </FaultRule>
    </FaultRules>
    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>QuotaPolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <Flows/>
    <HTTPProxyConnection>
        <BasePath>/quota/429</BasePath>
        <Properties/>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

This should make sure that your proxy still responds with a 500 Internal Server Error even though Apigee Edge turned on the default 429 response code. Sample response from the modified proxy:

< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Date: Fri, 06 May 2016 21:23:03 GMT
< Server: Apigee Router
< Content-Length: 137
< Connection: keep-alive
<
{"fault":{"faultstring":"Rate limit quota violation. Quota limit  exceeded.","detail":{"errorcode":"policies.ratelimit.QuotaViolation"}}}

This change is going to be rolled out soon, so you can start making your proxy changes now. If your clients expect a "HTTP/1.1 429 Too Many Requests" error and you have already enabled that using the org level feature flag then you DO NOT need to take any action. For folks who want to continue to get a "500 Internal Server Error" response when the quota violation happens, they need to make the changes suggested above.

I am also attaching the sample api proxy incase it helps folks to try out the changes themselves before applying them on the actual proxies.quota429-rev1-2016-05-06.zip

Comments
williamking
Participant V

@arghya das When can cloud customers expect to see the 429 status as the default?

Not applicable

I too am curious when this will be activated by default for Edge Cloud. The original post states "soon", but appears to be over 8 months old and our testing shows that "500" is still being returned.

Not applicable

"This change is going to be rolled out soon"

2½ years later and it's still not rolled out.

Any idea as to when this is going to be implemented?

dchiesa1
Staff

The change has been rolled out, though this behavior may still not be "the default". You can set the flag on your org if it's not enabled.

gilsonsm
Staff

For information on handling HTTP 429 faults in Apigee API Monitoring, see:

https://docs.apigee.com/api-monitoring/faq?skip_cache=true#4292

Stephen

Version history
Last update:
‎05-06-2016 02:28 PM
Updated by: