A flexible, fast and lightweight rate limiter that allows rate limiting of any action on a website.Doesn't work across a scaled deployment by design, but could easily be modified to work in this way if required.  By design chose to keep it to this model.Example usageIf an IP address requests more than 100 page views over a 60 second period it will throw an exception:var okToGo = RateLimiter.Check(Pageview,    Code.Helpers.Common.IP.GetUserIPAddress(),    new TimeSpan(0, 0, 60), 100);if(!okToGo) throw new HttpException(503, Rate limit exceeded);If an IP address requests more than 100 page views over a 60 second period or a page view within 200ms of the last page view it will throw an exception:var okToGo = RateLimiter.Check(Pageview,    IP. + Code.Helpers.Common.IP.GetUserIPAddress(),    new TimeSpan(0, 0, 60), 100,    new TimeSpam(0, 0, 0, 200);if(!okToGo) throw new HttpException(503, Rate limit exceeded);If a user sends more than 10 PM's in an hour, or a PM within 5 seconds of their last send:var okToGo = RateLimiter.Check(SendPM,    User. + User.ID,    new TimeSpan(1, 0, 0), 10,    new TimeSpam(0, 0, 5);if(!okToGo) throw new HttpException(503, Rate limit exceeded);Implementationpublic class RateLimiter{    /// <summary>    /// Perform a rate limit check    /// Copyright (c) 2016 Scirra Ltd    /// </summary>    /// <param name=actionName>Name of the action (eg PageView, or SendPM)</param>    /// <param name=requestIdentifier>Unique identifier for request, eg IP address or user ID</param>    /// <param name=period>A specified time period in which no more than maxActionsInPeriod can be performed</param>    /// <param name=maxActionsInPeriod>Max number of actions in given period</param>    /// <param name=minTimeBetweenActions>Optional, minimum time between actions.</param>    /// <returns></returns>    public static bool Check(string actionName, string requestIdentifier, TimeSpan period, int maxActionsInPeriod, TimeSpan? minTimeBetweenActions = null)    {        var limiter = GetRateLimiter(actionName, requestIdentifier, period, maxActionsInPeriod, minTimeBetweenActions);        if (limiter.CanPerformAction())        {            limiter.PerformAction();            return true;        }        return false;    }    private int ActionsInPeriod { get; set; }    private int MaxActionsInPeriod { get; set; }    private DateTime LastAction { get; set; }    private TimeSpan MinTimeBetweenActions { get; set; }    private RateLimiter(int maxActionsInPeriod, TimeSpan? minTimeBetweenActions = null)    {        ActionsInPeriod = 0;        LastAction = DateTime.MinValue;        MaxActionsInPeriod = maxActionsInPeriod;        if (minTimeBetweenActions == null) MinTimeBetweenActions = new TimeSpan(0);        else MinTimeBetweenActions = minTimeBetweenActions.Value;    }    private void PerformAction()    {        ActionsInPeriod++;        LastAction = DateTime.Now;    }    private bool CanPerformAction()    {        if (ActionsInPeriod >= MaxActionsInPeriod) return false;        if (LastAction.Add(MinTimeBetweenActions) > DateTime.Now) return false;        return true;    }    private static RateLimiter GetRateLimiter(string actionName, string requestIdentifier, TimeSpan period, int maxActionsInPeriod, TimeSpan? minTimeBetweenActions = null)    {        var cache = Caching.Controllers.LocalCacheController.Cache;        var cacheKey = GetRateLimiterCacheKey(actionName, requestIdentifier);        var limiter = cache[cacheKey];        if (limiter != null) return (RateLimiter)limiter;        var newLimiter = new RateLimiter(maxActionsInPeriod, minTimeBetweenActions);        cache.Add(            cacheKey, newLimiter, null,             DateTime.Now.Add(period),             Cache.NoSlidingExpiration,            CacheItemPriority.NotRemovable, null);        return (RateLimiter)cache[cacheKey];    }    private static string GetRateLimiterCacheKey(string actionName, string requestIdentifier)    {        return RateLimiter. + actionName + . + requestIdentifier;    }}
C# Rate Limiter
c#;asp.net