class TokenBucket {
constructor(capacity, refillRatePerSec) {
this.capacity = capacity;
this.refillRate = refillRatePerSec;
this.tokens = capacity;
this.lastRefill = Date.now();
module Middleware
class RateLimiter
def initialize(app, redis:, limit:, window:)
@app = app
@limiter = SlidingWindowLimiter.new(redis: redis, limit: limit, window: window)
@limit = limit
require "securerandom"
require "digest"
class SlidingWindowLimiter
Result = Struct.new(:allowed, :count, :remaining)
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
<?php
namespace App\Services\RateLimit;
use Illuminate\Support\Facades\Redis;
from django.core.cache import cache
class RateLimiter:
def __init__(self, scope, limit, window_seconds):
self.scope = scope
class LastSeenTracker
THROTTLE = 5.minutes
PENDING_KEY = "pending:last_seen".freeze
class << self
def touch(user_id, at: Time.current)
package ratelimit
import (
"sync"
"time"
)
-- KEYS[1] = bucket key
-- ARGV: capacity, refillPerSec, now(ms), cost, ttl(sec)
local capacity = tonumber(ARGV[1])
local refill = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local cost = tonumber(ARGV[4])
class CounterBuffer
DELTA_HASH = "counter:deltas".freeze
READ_RESET = <<~LUA.freeze
local v = redis.call('HGET', KEYS[1], ARGV[1])
if v then redis.call('HDEL', KEYS[1], ARGV[1]) end
-- KEYS[1] = bucket key
-- ARGV[1] = capacity, ARGV[2] = refill_per_sec, ARGV[3] = now (float seconds)
local capacity = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
<?php
declare(strict_types=1);
namespace App\Security;