{"id":"jeremy84100/ratelimiter","name":"ratelimiter","scope":"jeremy84100","platform":"roblox","description":"Hardened, zero-allocation O(1) RateLimiter engine for Roblox.","version":"3.2.7","latest":"3.2.7","versions":["3.2.2","3.2.3","3.2.4","3.2.5","3.2.7"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"368afa887261cc9c8d0699dba2bffb38759cb87de96bd54e74d5eff611e4e670","likes":0,"downloads":0,"install":"forest install jeremy84100/ratelimiter","url":"https://forest.dev/p/roblox/jeremy84100/ratelimiter","files":"https://api.forest.dev/ai/package/roblox/jeremy84100/ratelimiter/files","readme":"<div align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/lucide-icons/lucide/main/icons/shield-check.svg\" width=\"96\" alt=\"RateLimiter logo\">\n\n  # RateLimiter\n  *High-performance, engine-grade security for Roblox backends*\n\n  [![Version](https://img.shields.io/badge/version-3.2.7-blue?style=flat-square)](https://github.com/Jeremy84100/RateLimiter)\n  [![Platform](https://img.shields.io/badge/Roblox-00A2FF?style=flat-square&logo=roblox&logoColor=white)](https://roblox.com)\n  [![Luau](https://img.shields.io/badge/Luau-Strict-FF5A0E?style=flat-square)](https://luau-lang.org)\n  [![Performance](https://img.shields.io/badge/Performance-Zero--Allocation-brightgreen?style=flat-square)](https://github.com/Jeremy84100/RateLimiter)\n\n  ⭐ If you like this project, star it on GitHub!\n\n  [Key Features](#key-features) • [Installation](#installation) • [Quick Start](#quick-start) • [Architecture](#architecture--performance)\n\n</div>\n\n**RateLimiter** is a strictly-typed, synchronous security framework designed for Roblox environments requiring extreme performance. It replaces traditional $O(n)$ memory-heavy loops with pure mathematical algorithms and a **True $O(1)$ Circular Buffer**, ensuring constant execution time even under massive request volumes. Zero yielding, zero thread exhaustion.\n\n## Key Features\n\n- **Algorithmic Purity:** Choose between Debounce, $O(1)$ RateLimit (Circular Buffer), and Token Bucket algorithms.\n- **Composite Limiting:** Chain multiple time-windows simultaneously (e.g., Burst + Sustained limits).\n- **RemoteProtector:** A zero-allocation wrapper to instantly secure `RemoteEvent` instances.\n- **Escalation Matrix:** Automatically scale punishment durations for persistent attackers.\n- **Anti-Deco Persistence:** Seamless MemoryStoreService integration to persist player bans across sessions.\n- **Weighted Requests:** Charge different \"costs\" for different actions sharing the same limit pool.\n\n## Installation\n\n### Wally (Recommended)\nAdd this to your `wally.toml`:\n```toml\n[dependencies]\nRateLimiter = \"jeremy84100/ratelimiter@3.2.7\"\n```\n\n### Manual\n1. Download the latest release from the repository.\n2. Place the `RateLimiter` module into `ServerStorage` or `ReplicatedStorage`.\n\n## Quick Start\n\n### 1. Securing Remote Events (RemoteProtector)\nThe most common use case. Secure server endpoints against spam and brute-force attacks instantly.\n\n```lua\nlocal RateLimiter = require(path.to.RateLimiter)\n\n-- Allow 10 requests per second. Ban for 120s after 3 strikes.\nlocal protector = RateLimiter.RemoteProtector.new(10, 1, 3, 120)\n\nprotector:Connect(game.ReplicatedStorage.DataEvent, function(player, actionData)\n    -- This code ONLY runs if the player is within their strict limits.\n    print(player.Name .. \" performed a secured action.\")\nend)\n```\n\n### 2. Burst & Sustained Limits (Composite Mode)\nPrevent bots from maintaining a constant maximum request rate over long periods by combining multiple time windows.\n\n```lua\n-- Allow 15 fast inputs (Burst) AND max 100 inputs per minute (Sustained)\nlocal limiter = RateLimiter.new({\n    {max = 15, window = 1},\n    {max = 100, window = 60}\n}, nil, RateLimiter.Mode.Composite)\n\nlimiter:Execute(function()\n    print(\"Action allowed under both time windows.\")\nend)\n```\n\n### 3. Weighted Requests & Token Bucket\nHandle actions that consume varying amounts of backend resources.\n\n```lua\n-- Bucket holds 100 max tokens, regenerates 10 tokens per second\nlocal bucket = RateLimiter.new(100, 10, RateLimiter.Mode.TokenBucket)\n\nlocal function heavyDatabaseSave()\n    print(\"Saving...\")\nend\n\n-- Consume 25 tokens for a heavy request\nbucket:ExecuteWithCost(25, heavyDatabaseSave)\n```\n\n> [!TIP]\n> Use `ExecuteWithCost` for actions like spawning complex models, firing projectiles, or generating terrain to accurately represent the server load.\n\n### 4. Player Persistence (Anti-Combat Log/Deco)\nEnsure that malicious users cannot reset their cooldowns or punishments by rejoining the server.\n\n```lua\nlocal playerLimiter = RateLimiter.PlayerLimiter(5, 1, RateLimiter.Mode.RateLimit)\n\n-- Link to MemoryStoreService. Punishments will now persist globally!\nplayerLimiter:EnablePersistence(\"GlobalAction_X\")\n\n-- Use ExecuteFor to track requests per player\nplayerLimiter:ExecuteFor(somePlayer, function()\n    print(\"Player successfully requested action.\")\nend)\n```\n\n> [!IMPORTANT]  \n> If you need to dynamically update a player's capacity (e.g., they purchased a VIP Gamepass), use `limiter:SetCapacity(newTokens, newRefillRate)`. This updates their limits mathematically without destroying their current state or allocations.\n\n## Architecture & Performance\n\nTraditional rate limiters on Roblox rely on `table.insert` and `table.remove`, causing memory allocations and garbage collection spikes. If a player spams requests, traditional limits yield (`task.wait`), leading to thread exhaustion and server crashes.\n\n**RateLimiter** is built differently:\n1. **$O(1)$ Complexity:** The `RateLimit` mode utilizes a static, pre-allocated Circular Buffer. It advances a head/tail pointer rather than resizing arrays.\n2. **Synchronous Execution:** The engine is 100% yield-free. Requests are evaluated instantly. If a limit is breached, the execution is dropped, saving CPU cycles.\n3. **Zero-Allocation Hot Paths:** When executing secured functions, no anonymous closures or temporary tables are generated in memory.\n\n---\n*Built for professional, high-concurrency Roblox experiences.*","readmeTruncated":false}