Skip to content

What's new ​

These docs track PlayerState v2.0.1 for the Creator Store model. Install or update the model there; this site documents behaviour and API surface.

Release notes come first, followed by the main feature highlights. For how data is scoped and replicated, start with Concepts and the data visibility model.

Docs layout: The API reference is split into topic pages under Server, Client, and Types—bookmark deep links that used #sections may need updating.

v2.0.1 (2026-11-02) ​

Added ​

  • Studio autocomplete for your data. Studio now autocompletes your DefaultData keys and paths in Get, Set, GetPath, SetPath, OnChanged, Increment, and the array and dictionary functions, on both server and client, with no type annotations needed. Shared session keys and leaderboard stat names autocomplete too. Requires the New Type Solver; any string still works as before. Installation
  • LeaderstatsOrder in PlayerStateConfig.Server sets the order leaderstats appear in the player list, as a list of display names, e.g. LeaderstatsOrder = {"💰 Coins", "⭐ Level"}. Stats not in the list follow in alphabetical order. Configuration
  • SkipUnchangedWrites in PlayerStateConfig.Server (off by default). When on, setting a value to what it already is skips replication and OnChanged. Configuration

Changed ​

  • Leaderstats now appear in a consistent order instead of an arbitrary one, and a stat no longer moves to the end of the player list when it switches between whole and decimal values.
  • Client reads (Get, GetPath, GetFromDict, GetShared, GetSharedPath) now read the live data directly, so they are faster and always return the latest value, even inside your own Replica listeners. CacheDuration, CacheCleanupInterval and MaxCacheSize are still accepted but no longer do anything.
  • OnChanged and OnSharedChanged dispatch is about twice as fast on both server and client, and connecting or disconnecting many listeners is cheaper.
  • Leaderboards keep a small DataStore write budget reserve for your game's own OrderedDataStore writes.
  • After a failed leaderboard fetch, PlayerState waits about 10 seconds before trying again and returns the last known results in the meantime. It also skips fetching when the read budget is empty.
  • When a batch writes the same leaderboard stat several times, only the final value is sent to the leaderboard.

Fixed ​

  • PlayerState's own scripts no longer show type errors in Script Analysis when your place uses the New Type Solver with strict mode.
  • BatchUpdateValues with the same path more than once now applies every operation, so two +5 on Coins adds 10 instead of 5.
  • Wiping a player's data no longer makes legacy DataStore migration run again on their next join.
  • session and other non-saved data no longer read as nil while an autosave is running, and changes made during a save are kept.
  • BeforeRelease and BeforeSave no longer fire twice for the same player during server shutdown.
  • Changing info.path inside an OnChanged callback no longer affects other listeners or later writes to that path.
  • GetOfflineData called from the client now rejects NaN, infinite and fractional user ids instead of erroring or spending DataStore requests.
  • The "StartSession failed" warning no longer appears when a player leaves while their data is still loading.
  • Increment on an invalid player now warns instead of printing.
  • A save that can never succeed (data over 4 MB, or values DataStores can't store) no longer retries forever and blocks server shutdown. ProfileStore.OnError reports it instead.
  • MessagingService outages no longer throw errors from ProfileStore; they log a warning instead.
  • A request from another server to end a session is no longer dropped when it arrives within 6 seconds of a save request, so rejoining across servers is faster.
  • List inserts and removals inside a batch now reach clients in the same order as the other changes in that batch.
  • Nested replicas are now cleaned up on the client when their parent is destroyed.
  • Connecting or disconnecting a Replica listener from inside another listener no longer errors on the client.
  • A player who leaves mid-join is no longer kept as "ready" on the server.
  • Players who join after the first player can now read PlayerStateClient:GetLeaderboard() and GetLeaderboardInfo() right after their data loads, instead of getting an empty result until the next SyncInterval tick.

Performance ​

Measured with the built-in benchmarks in Studio, same operations before and after. Single runs; small values vary by about ±0.05 μs between runs.

BeforeAfter
Server overall825K ops/sec1.09M ops/sec
Client overall3.97M ops/sec5.61M ops/sec
Client Get / GetPath / GetFromDict0.19 / 0.21 / 0.32 μs0.10 / 0.17 / 0.14 μs
Client GetShared / GetSharedPath0.44 / 0.36 μs0.10 / 0.18 μs
Client first read of a new path0.87 μs0.15 μs
Client OnChanged dispatch, 50 listeners (25 matching)20.45 μs10.03 μs
Client GetLeaderboard1.03 μs0.63 μs
Server Set / SetPath / SetValues2.04 / 2.11 / 3.66 μs1.83 / 1.78 / 3.00 μs
Server OnChanged exact / prefix listeners1.15 / 1.76 μs0.51 / 0.87 μs
Server SetPath with 100 listeners on the same root170.10 μs77.35 μs
Server-only data filtering on load20.66 μs11.58 μs
Server Clone0.21 μs0.14 μs
Server array ops / BatchSetValues1.75 / 0.84 μs2.08 / 1.19 μs

Server array ops and BatchSetValues are slightly slower because each write now gets its own path copy, which fixes the info.path bug above.

v2.0.0 (2026-10-31) ​

Added ​

Changed ​

  • SetPath now creates missing parent tables on both the server and the client instead of behaving differently depending on whether leaderstats are configured.
  • Client OnChanged now always returns a connection, even when called before data is ready, and warns on invalid arguments like the server does.
  • GetOfflineData called from the client no longer returns server-only or session data, is rate limited per player, and caches offline results briefly.
  • Unstorable leaderboard scores (NaN, infinity, or numbers beyond the OrderedDataStore range) are skipped with a single warning instead of retrying forever.
  • Client reads and server dictionary reads are faster, and listeners cost nothing when none are connected.

Fixed ​

  • Fixed a client memory leak where disconnected OnChanged and OnSharedChanged listeners were never released.
  • Fixed require of the Wally package erroring on both server and client.
  • Fixed leaderboard writes that failed being retried endlessly and flooding the output with ValueNotNumeric errors.
  • Fixed leaderboard scores sometimes being written stale or lost at server shutdown.
  • Fixed GetLeaderboard with a limit above 100 returning nothing.
  • Fixed OnChanged callbacks for a parent path receiving the old value after a nested change.
  • Fixed listeners silently stopping after a player's session was reloaded.
  • Fixed a second session takeover not being handled, which left players on a dead profile.
  • Fixed offline SetOfflineData/wipe messages being dropped when the player was loading on another server.
  • Fixed wiping data through a message modifying the default data template for every future player.
  • Fixed session data (session and leaderboard info) disappearing for the rest of a session after a failed autosave.
  • Fixed legacy data migration being marked complete when the old data couldn't be fetched, and re-running every join when CleanExtraFields was on.
  • Fixed legacy migration merging arrays index by index instead of replacing them.
  • Fixed a stale batched value overwriting a newer Set on the client.
  • Fixed leaderstats not updating when a parent table was replaced.
  • Fixed a memory leak for players who left before their data finished loading.
  • Fixed players being kicked or warned during server shutdown.
  • Fixed mutating a table passed to SetShared changing shared data without replicating.

Performance ​

Measured with the built-in benchmarks in Studio, same operations before and after.

BeforeAfter
Server overall866K ops/sec903K ops/sec
Client overall3.09M ops/sec4.16M ops/sec
Client Get / GetPath0.28 / 0.31 μs0.20 / 0.22 μs
Client GetFromDict0.31 μs0.19 μs
Client GetAll0.23 μs0.07 μs
Client GetLeaderboard0.74 μs0.22 μs
Server Set / Increment1.96 / 2.12 μs1.87 / 1.87 μs
Server dictionary operations1.66 μs1.44 μs
Server-only data filtering on load49.7 μs14.3 μs

Feature highlights ​

Shared session and server-only data ​

Session (per-player, non-persistent) and migration ​

  • Session data — Runtime-only roots such as session replicate during play but do not persist. RuntimeNonPersistentRoots in config lists top-level keys stripped before save.

  • Legacy data migration — Opt-in import from an old DataStore during profile load (strategies include Auto, Overwrite, KeepNew, Manual, and related options). MigrationResult reports when migration finishes (applied, legacy data, strategy, metadata). Migration guide

Other API highlights ​

Server and client references cover the full surface area; these are commonly called out:

Lifecycle events: BeforeRelease, BeforeSave, ProfileLoaded, ProfileUnloaded, MigrationResult. Events

  • BeforeRelease — Fires before a player's profile session is released on leave or server shutdown. Intended for leave-only final data writes (e.g. persisting world state into the profile). Does not fire on SaveData(). On leave, runs before BeforeSave. BeforeRelease()

PlayerState - High-Performance Roblox Data Management