Performance Tips
Client-side patterns for responsive UI without fighting replication or leaking listeners.
Readiness
Get/GetPathwait until data is ready—no manual wait loop required for normal UI.- Use
when you want to skip work (hide UI, show placeholder) before data exists.IsReady() - For bulk UI setup, check
once, then read paths—not once per label.IsReady()
See Status — IsReady.
Listen on specific paths
Avoid a global "." listener unless you are debugging.
- One listener per UI concern:
"Coins","Inventory","Plot.Likes". - In a global listener, branch on
info.actionandinfo.path—do not repaint the whole HUD every time.
lua
-- Narrow
PlayerState.OnChanged("Coins", updateCoinsLabel)
-- Debug only
PlayerState.OnChanged(".", onAnyChange)See Change listeners.
Disconnect listeners
Every OnChanged (and shared-session listener) should be disconnected when:
- The local player leaves.
- The UI instance is destroyed.
- The feature is torn down (shop closed, plot unloaded).
lua
local conn = PlayerState.OnChanged("Coins", updateCoins)
gui.Destroying:Connect(function()
if conn then conn:Disconnect() end
end)Safe reads
- Use
orfallbacks:PlayerState..Get("Coins") or 0 - Validate shape before iterating:
typeof(inventory) == ".table" - Do not assume nested tables exist—check
GetPathfornil.
lua
local inventory = PlayerState.GetPath("Inventory")
if typeof(inventory) ~= "table" then
inventory = {}
endDo not mutate returned tables
Get / GetPath can return references to replicated data.
- Mutating the table locally can change shared state unintentionally.
- Use
when you need a local copy to edit offline in UI code.Clone() - To change saved data, use your server remotes—the client API is read-only.
lua
-- Risky
local t = PlayerState.GetPath("Settings")
t.MusicEnabled = false
-- Safer for local UI logic
local t = PlayerState.Clone(PlayerState.GetPath("Settings"))See Common pitfalls.
Reads are live
Get,GetPath,GetFromDict,GetSharedandGetSharedPathread the replicated data directly, so they always return the latest value (even inside your own Replica listeners). There is no client value cache to tune.is kept for compatibility and has little or no effect.ClearCache()
See Cache.
Listener cost
OnChanged/OnSharedChangeddispatch is about twice as fast as before, and listeners cost nothing when none are connected.- Connecting or disconnecting listeners (including from inside another listener) is cheap.
Shared session
- Prefer
before reading shared session in UI.IsSharedReady() - Use specific
OnSharedChangedpaths instead of listening to everything.
See Shared session.