Skip to content

Performance Tips

Server-side patterns that keep saves fast, replication predictable, and memory stable.

Batch writes

Prefer one batch over many single writes when updating several fields at once.

lua
-- Prefer this
PlayerState.SetValues(player, {
    Coins = newCoins,
    Level = newLevel,
    Experience = newExp,
})

-- Over many separate Set calls in the same frame

See Batch operations.

Paths and cache

  • Reuse path strings in hot loops instead of building "Stats." .. name every time.
  • Call ClearPathCache() only when debugging or after large schema changes—not every frame.

See Cache.

Return values

Write APIs return boolean. Treat false as a real outcome, not noise.

  • Log or warn with context (player, path, reason if known).
  • Do not assume the Replica updated when the call failed.
  • Common causes: invalid player, leaderstats path blocked, ViewedUser read-only in Studio.

Leaderstats

  • Change source data (e.g. Coins, Stats.Score) and let PlayerState sync leaderstats.
  • Do not write directly to leaderstats instances or paths that map to them.

See Leaderboard & leaderstats.

Change listeners

  • Listen on the narrowest path ("Coins", "Plot.Likes"), not ".", unless debugging.
  • Disconnect OnChanged when the player leaves or the feature is destroyed.

See Change listeners and Best practices — memory.

Lifecycle events

GoalUse
Leave-only world → profile writesBeforeRelease
Logic on SaveData() and leaveBeforeSave
After session ended (read-only)ProfileUnloaded

Do not use Players.PlayerRemoving + GetPath for final saves—the profile may already be released.

See Events.

PlayerState - High-Performance Roblox Data Management