End customer rate limiting using SpikeArrest or Quota policy

We're looking to limit requests made by an end user on a per minute basis to protect against malicious attacks. (e.g. 100 requests/min)

I've seen the documentation and the SpikeArrest policy is recommended for this use case. We can't use the username alone as an identifier for SpikeArrest as our clients sometimes make concurrent requests to our APIs.

So we're thinking of using the SpikeArrest policy with the username + URL as an identifier and this will effectively protect some of the APIs but not all of them. Some of the URIs would contain path variable IDs (imagine something like /store/item/Ba521316NC) resulting in a different identifier each time so this URL can still be prone to traffic bursts. We could add something specifically for those kind of URIs but we are looking for a more generic way of doing this that would scale well as more endpoints are added. It's looking like that is our only option now.

I know of the Quota policy that seems to fit exactly what we need from a technical perspective and we could just specify the username as an identifier and be done with it. Though I read from documentation that it is computationally expensive and not ideal for dealing traffic management. I imagine it would not scale well when keeping track of counts of hundreds of thousands of end users.

Is there a better or some proven way of implementing this?

Solved Solved
0 2 150
1 ACCEPTED SOLUTION

In X and hybrid, the SpikeArrest will work nicely for this use-case. In Edge it probably will not be able to do what you desire.

we're thinking of using the SpikeArrest policy with the username + URL as an identifier and this will effectively protect some of the APIs but not all of them. Some of the URIs would contain path variable IDs (imagine something like /store/item/Ba521316NC) resulting in a different identifier each time so this URL can still be prone to traffic bursts. We could add something specifically for those kind of URIs but we are looking for a more generic way of doing this that would scale well as more endpoints are added. It's looking like that is our only option now.

There is a "flow.name" context variable that you may want to use - this is the name you specify in the API Proxy. The URI path may be one of many URIs that follow a specific pattern, but the flow would be the same. That may be a way you can have a consistent identifier across similar URIs. Consider that.

I know of the Quota policy that seems to fit exactly what we need from a technical perspective and we could just specify the username as an identifier and be done with it. Though I read from documentation that it is computationally expensive and not ideal for dealing traffic management. I imagine it would not scale well when keeping track of counts of hundreds of thousands of end users.

Quota works a little differently, and may be acceptable. It is "more expensive" than SpikeArrest in that it requires I/O to a persistent store to synchronize counts across all users. It scales well, but delivers "eventually consistency" semantics. In a distributed scenario with a rate limit of 100/minute, a Quota policy may allow more than 100 calls, maybe 110, maybe 118, because of its eventual consistency behavior. This may or may not be acceptable to you. I suggest that you test this to see if it delivers the performance and behavior you want.

View solution in original post

2 REPLIES 2

In X and hybrid, the SpikeArrest will work nicely for this use-case. In Edge it probably will not be able to do what you desire.

we're thinking of using the SpikeArrest policy with the username + URL as an identifier and this will effectively protect some of the APIs but not all of them. Some of the URIs would contain path variable IDs (imagine something like /store/item/Ba521316NC) resulting in a different identifier each time so this URL can still be prone to traffic bursts. We could add something specifically for those kind of URIs but we are looking for a more generic way of doing this that would scale well as more endpoints are added. It's looking like that is our only option now.

There is a "flow.name" context variable that you may want to use - this is the name you specify in the API Proxy. The URI path may be one of many URIs that follow a specific pattern, but the flow would be the same. That may be a way you can have a consistent identifier across similar URIs. Consider that.

I know of the Quota policy that seems to fit exactly what we need from a technical perspective and we could just specify the username as an identifier and be done with it. Though I read from documentation that it is computationally expensive and not ideal for dealing traffic management. I imagine it would not scale well when keeping track of counts of hundreds of thousands of end users.

Quota works a little differently, and may be acceptable. It is "more expensive" than SpikeArrest in that it requires I/O to a persistent store to synchronize counts across all users. It scales well, but delivers "eventually consistency" semantics. In a distributed scenario with a rate limit of 100/minute, a Quota policy may allow more than 100 calls, maybe 110, maybe 118, because of its eventual consistency behavior. This may or may not be acceptable to you. I suggest that you test this to see if it delivers the performance and behavior you want.

Thanks @dchiesa1! We also consulted with our Apigee point of contact. The SA ultimately proposed the same thing though eventual consistency was never mentioned. We'll take note of it.