Question web API rate limit throttling

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
361
Programming Experience
10+
Hi,

A customer wants me to set some limits on my web API.
  1. Limit the number of requests in a predefined amount of time, for example in a minute a terminal can make 1 request at max.
  2. Limit the daily total of the purchase. A terminal (client) can purchase 100$ at max.
I googled and found some articles like this one (throttling). I wonder what is the best way of implementing such limits into my web API? What are your suggestions?

Best Regards.
 
The approach given there is pretty good for a naive approach. Are you running into an issue, or are you just looking for other approaches?
 
Last edited:
A bit of advice about the code presented in that tutorial: It's a good approach when you running on only a single server. When your application needs to scale out to running on multiple machines, you'll need to re-think the use of that static ConcurrentDictionary<>. Recall that static variables are only in the memory of the app pool. Since you'll have app pools running on your code on multiple machines, how will you get this shared state to go across machines? The old approach was to use AppFabric, but MS has abandoned that.

I just realized, even on the single server, there is an issue with that throttling approach given there. If the sys admin performs an IISReset, or if somebody manages to crash the app pool, then a brand new instance of the app pool will be started up. New instance means that the past never happened so anybody who had exceeded their limits previously doesn't look like they exceeded their limits.

As for the daily total throttling, the best durable way to do this check is to actually recompute the totals from your database. Trying to keep this in memory is prone to error. Like as I mentioned above, consider the IISReset or application crash. Also consider that IIS's default settings is to spin down an app pool if it's been idle for 20 minutes. So any daily total you may have in memory will be lost when the app pool is shutdown. You'll need no recompute anywhich way. Yes, you could cut down on the database hits by doing some in memory caching, but you'll need to balance this out with the complexity this will add to your code.
 
@Skydiver thank you for your reply.

A bit of advice about the code presented in that tutorial: It's a good approach when you running on only a single server. When your application needs to scale out to running on multiple machines, you'll need to re-think the use of that static ConcurrentDictionary<>. Recall that static variables are only in the memory of the app pool. Since you'll have app pools running on your code on multiple machines, how will you get this shared state to go across machines? The old approach was to use AppFabric, but MS has abandoned that.

For now, it is running on a single server. What should I use in the future if I have more than one server?

I just realized, even on the single server, there is an issue with that throttling approach given there. If the sys admin performs an IISReset, or if somebody manages to crash the app pool, then a brand new instance of the app pool will be started up. New instance means that the past never happened so anybody who had exceeded their limits previously doesn't look like they exceeded their limits

I already accepted this risk.
 
Redis seems to be the popular solution for farm wide communication of state. I recall when memcached used to be king. That may entail more headaches getting this configured, but if your applications reaches that point of needing to scale out instead of scale up, you might be able to afford to time and complexity of setting this up.

But if you want something more traditional, look at ASP.NET session state as a way to communicate state across the farm. You'll want the non-inproc memory session state implementations like SQL, or a state server, or AppFabric, etc.
 
Thank you @Skydiver. I am using a Windows 2012 web server and SQL database server. Since I don't know about Redis, would you please tell me how can I use Redis in my situation? I read some articles but couldn't figure out.
 
My recommendation is not to cross the bridge until you get there. If you are on a single machine platform keep your current throttling approach. Just leave something in your backlog saying that throttling needs to be re-visited when the system needs to be scaled out.
 
Back
Top Bottom