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
DefaultDatakeys and paths inGet,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 LeaderstatsOrderinPlayerStateConfig.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. ConfigurationSkipUnchangedWritesinPlayerStateConfig.Server (off by default). When on, setting a value to what it already is skips replication andOnChanged. 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,CacheCleanupIntervalandMaxCacheSizeare still accepted but no longer do anything. OnChangedandOnSharedChangeddispatch 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.
BatchUpdateValueswith the same path more than once now applies every operation, so two+5onCoinsadds 10 instead of 5.- Wiping a player's data no longer makes legacy DataStore migration run again on their next join.
sessionand other non-saved data no longer read as nil while an autosave is running, and changes made during a save are kept.BeforeReleaseandBeforeSaveno longer fire twice for the same player during server shutdown.- Changing
info.pathinside anOnChangedcallback no longer affects other listeners or later writes to that path. GetOfflineDatacalled 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.
Incrementon 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.OnErrorreports 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
andPlayerStateClient:GetLeaderboard()right after their data loads, instead of getting an empty result until the nextGetLeaderboardInfo()SyncIntervaltick.
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.
| Before | After | |
|---|---|---|
| Server overall | 825K ops/sec | 1.09M ops/sec |
| Client overall | 3.97M ops/sec | 5.61M ops/sec |
Client Get / GetPath / GetFromDict | 0.19 / 0.21 / 0.32 μs | 0.10 / 0.17 / 0.14 μs |
Client GetShared / GetSharedPath | 0.44 / 0.36 μs | 0.10 / 0.18 μs |
| Client first read of a new path | 0.87 μs | 0.15 μs |
Client OnChanged dispatch, 50 listeners (25 matching) | 20.45 μs | 10.03 μs |
Client GetLeaderboard | 1.03 μs | 0.63 μs |
Server Set / SetPath / SetValues | 2.04 / 2.11 / 3.66 μs | 1.83 / 1.78 / 3.00 μs |
Server OnChanged exact / prefix listeners | 1.15 / 1.76 μs | 0.51 / 0.87 μs |
Server SetPath with 100 listeners on the same root | 170.10 μs | 77.35 μs |
| Server-only data filtering on load | 20.66 μs | 11.58 μs |
Server Clone | 0.21 μs | 0.14 μs |
Server array ops / BatchSetValues | 1.75 / 0.84 μs | 2.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
OnChangedandOnSharedChangednow fire when a parent path is replaced or set withSetValues, soreaches anSetValues(player, {Coins = 5})listener.OnChanged("Coins")- Path listeners and
GetPathnow work with array indices, e.g.andOnChanged("Items.3").GetPath("Items.1")
Changed
SetPathnow creates missing parent tables on both the server and the client instead of behaving differently depending on whether leaderstats are configured.- Client
OnChangednow always returns a connection, even when called before data is ready, and warns on invalid arguments like the server does. GetOfflineDatacalled 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
OnChangedandOnSharedChangedlisteners were never released. - Fixed
requireof the Wally package erroring on both server and client. - Fixed leaderboard writes that failed being retried endlessly and flooding the output with
ValueNotNumericerrors. - Fixed leaderboard scores sometimes being written stale or lost at server shutdown.
- Fixed
GetLeaderboardwith a limit above 100 returning nothing. - Fixed
OnChangedcallbacks 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 (
sessionand 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
CleanExtraFieldswas on. - Fixed legacy migration merging arrays index by index instead of replacing them.
- Fixed a stale batched value overwriting a newer
Seton 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
SetSharedchanging shared data without replicating.
Performance
Measured with the built-in benchmarks in Studio, same operations before and after.
| Before | After | |
|---|---|---|
| Server overall | 866K ops/sec | 903K ops/sec |
| Client overall | 3.09M ops/sec | 4.16M ops/sec |
Client Get / GetPath | 0.28 / 0.31 μs | 0.20 / 0.22 μs |
Client GetFromDict | 0.31 μs | 0.19 μs |
Client GetAll | 0.23 μs | 0.07 μs |
Client GetLeaderboard | 0.74 μs | 0.22 μs |
Server Set / Increment | 1.96 / 2.12 μs | 1.87 / 1.87 μs |
| Server dictionary operations | 1.66 μs | 1.44 μs |
| Server-only data filtering on load | 49.7 μs | 14.3 μs |
Feature highlights
Shared session and server-only data
Shared session — Server-wide non-persistent state for the current server, replicated to every client in that server. Configure via
Server.SharedSessionin PlayerStateConfig. Server APIs includeSetShared,GetShared,SetSharedPath,GetSharedPath,SetSharedValues,OnSharedChanged,GetSharedReplica,GetSharedAll, andIsSharedReady. Client APIs includeGetShared,GetSharedPath,OnSharedChanged,GetSharedReplica,GetSharedAll, andIsSharedReady(reads wait until the shared Replica is ready, similar to profile data). Shared session guide · Server API · Client APIServer-only player data —
ServerOnlyRoots(for example a top-level"Server"root) persist inprofile.Databut are stripped before the player Replica, so they never replicate to clients.SetOfflineDatacan target those paths where appropriate. Server-only data · Data visibility
Session (per-player, non-persistent) and migration
Session data — Runtime-only roots such as
sessionreplicate during play but do not persist.RuntimeNonPersistentRootsin 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).
MigrationResultreports 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:
- Server
OnChanged— Replica-backed listeners per player. Change subscription BatchUpdateValues— Batch numeric increment/decrement-style updates. BatchUpdateValuesIsPlayerDataReady— Non-blocking profile + Replica readiness check. DetailsBatchSetValues/FlushBatch— Bulk updates with optional flush. Server API- Leaderstats — Automatic integration when configured in DefaultData / config.
ClearPathCache(server) — Clears the server path-parse cache; for debugging. The clientis kept for compatibility, but client reads have no value cache since v2.0.1.ClearCache()- Array & dictionary helpers —
AddToArray,SetInDict, and related operations. GetOfflineData(client) — Saved profile snapshot for another user via RemoteFunction. Client API- Client
OnChanged— Action-aware change info (Set,TableInsert, etc.), global"."listener,for gated reads.IsReady()
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. On leave, runs beforeSaveData()BeforeSave. BeforeRelease()