SecurityIntermediate

Rate-Limited & Type-Safe Shop

A purchase remote protected by two layers of middleware spam rejected before it's even validated.

RateLimiterTypeCheckerMiddleware
ServerScriptService/Services/PurchaseService.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Owl = require(ReplicatedStorage.OwlKnit.Owl)
local RateLimiter = Owl.Util.RateLimiter
local TypeChecker = Owl.Util.TypeChecker
 
local PurchaseService = Owl.CreateService({
    Name = "PurchaseService",
    Middleware = {
        Inbound = {
            -- 1. Reject spam fast, before paying the cost of type-checking
            RateLimiter.strict(3, 1, "PurchaseService"),
            -- 2. Then validate the shape of what's left
            TypeChecker.args("string", "number"),
        },
    },
    Client = {},
})
 
function PurchaseService:OwlInit()
end
 
function PurchaseService:OwlStart()
end
 
function PurchaseService.Client:BuyItem(plr: Player, itemId: string, quantity: number): boolean
    local token = Owl.GetPlrToken(plr)
    if not token then return false end
 
    -- > // itemId is guaranteed a string, quantity a number, TypeChecker already rejected anything else
    return processItemPurchase(plr, itemId, quantity)
end
 
return PurchaseService
What's happening here
  • Middleware order matters: RateLimiter.strict runs first, so a spammed request is dropped before TypeChecker ever inspects its arguments.
  • RateLimiter.strict enables progressive penalties out of the box repeated spam escalates from a warning to a kick to a temporary ban.
  • TypeChecker.args("string", "number") means BuyItem's body can trust itemId and quantity's types without a single manual check.