Priority System
Handlers run in ascending priority order — lower number fires first. Handlers at the same priority run in registration order.
Named aliases
| Name | Value | Use for |
|---|---|---|
"first" | 0 | Critical operations that must run before anything else — DataStore saves, security checks |
"high" | 25 | Early processing — inventory cleanup, session teardown |
"normal" | 50 | Default — general game logic, UI updates |
"low" | 75 | Non-critical work that should follow core logic |
"last" | 100 | Logging, analytics, telemetry — always after everything else |
Numbers and aliases are interchangeable. Use whichever is clearer:
Hook("PlayerRemoving", "first", function(player)
DataStore:Save(player) -- priority 0 — runs first
end)
Hook("PlayerRemoving", 10, function(player)
Inventory:Wipe(player) -- priority 10 — after save
end)
Hook("PlayerRemoving", "normal", function(player)
Party:Remove(player) -- priority 50 — mid
end)
Hook("PlayerRemoving", "last", function(player)
Analytics:LogLeave(player) -- priority 100 — always last
end)
Why priority matters
Without priority, the order handlers run in depends on when :Connect was called — which is effectively the order your scripts happened to require their modules. That order is fragile: a new module added to the game changes it.
A concrete example where order breaks things: if your inventory cleanup runs before your DataStore save, the save writes an empty inventory. Priority prevents this class of bug entirely by making order explicit and stable regardless of require order.
50 ("normal"). If ordering between two handlers doesn't matter, omit priority on both — they'll still run consistently relative to handlers that do declare a priority.See also
← Hook · Subscribing | Hook(), Once, Off, Clear · Signal Catalog | all mapped Roblox events