Skip to content

Session Data (Non-Persistent)

PlayerState supports runtime-only data that replicates during play but is never persisted to the DataStore. Use session data for temporary state that should reset each time a player joins.

Quick Start

Add a session root to your DefaultData and use normal API calls. Session data syncs to clients but is never saved.

lua
-- DefaultData
session = {
    isChopping = false,
    isSprinting = false,
}

-- Server: set session state
PlayerState.SetPath(player, "session.isSprinting", true)

-- Client: read session state
local sprinting = PlayerState.GetPath("session.isSprinting")

What It Is

Session data (also called non-persistent or runtime-only data) lives at special roots such as session. PlayerState treats these roots differently:

  • Replicates during play — clients can read it and listeners fire when it changes
  • Never persisted — stripped from the save payload
  • Reset on load — cleaned on profile load and re-seeded from template defaults

Use it for activity flags, temporary UI state, minigame progress, or any value that should not survive rejoin or server restart.

Why Use It

Use CaseExample
Activity flagssession.isChopping, session.isSprinting, session.inCombat
Temporary progresssession.currentMinigameScore, session.questStep
UI / client statesession.selectedTab, session.tutorialStep
Per-session counterssession.killsThisSession, session.deathsThisSession

You get real-time sync and change listeners without bloat in the DataStore or save/load cost.

DefaultData Example

Define session roots in your template. They will be initialized from these defaults on every profile load:

lua
-- ReplicatedStorage.Libraries.PlayerState.DefaultData
return {
    Coins = 100,
    Level = 1,

    session = {
        isChopping = false,
        isSprinting = false,
        inCombat = false,
        currentMinigame = nil,
    },
}

Server: Set and Get

Use SetPath / GetPath (or Set / Get) the same way as persistent data:

lua
-- ServerScriptService
local PlayerState = require(game.ReplicatedStorage.Libraries.PlayerState.PlayerStateServer)

Players.PlayerAdded:Connect(function(player)
    PlayerState.Init(player)

    -- Set session state
    PlayerState.SetPath(player, "session.isSprinting", true)
    PlayerState.SetPath(player, "session.isChopping", false)

    -- Read it back
    local sprinting = PlayerState.GetPath(player, "session.isSprinting")
end)

Client: Read and Listen

Clients read session data like any other path. It is available as soon as the profile is loaded:

lua
-- LocalScript
local PlayerState = require(game.ReplicatedStorage.Libraries.PlayerState.PlayerStateClient)

local sprinting = PlayerState.GetPath("session.isSprinting")
print("Is sprinting:", sprinting)

PlayerState.OnChanged("session.isSprinting", function(newValue, oldValue)
    print("Sprinting changed:", oldValue, "->", newValue)
end)

Save Behavior

Session roots are never persisted:

  • Stripped from the save payload before writing to the DataStore
  • Restored in-memory from template defaults after save
  • On load, runtime roots are cleaned and re-seeded from DefaultData

You do not need to do anything special. PlayerState handles this automatically.

Common Mistakes

Using SetOfflineData for Session Paths

SetOfflineData writes to the persistent profile. It blocks runtime-only paths such as session.* and will warn or fail for those writes.

lua
-- ❌ WRONG: session data cannot be set offline
PlayerState.SetOfflineData(userId, "session.isSprinting", true)

-- ✅ Use SetPath when the player is in-server only
PlayerState.SetPath(player, "session.isSprinting", true)

Session data only exists while the player has an active profile session. There is no offline equivalent.

Mixing Session and Persistent Data

Keep session and persistent data clearly separated by root:

lua
-- ✅ Clear separation
session = { isSprinting = false }
Stats = { TotalPlayTime = 0, LastLogin = 0 }

-- ❌ Avoid putting session state inside persistent roots
Stats = { TotalPlayTime = 0, isSprinting = false }

Expecting Session Data After Rejoin

Session data resets on every join. Do not rely on it across sessions:

lua
-- Session data is per-session only
PlayerState.SetPath(player, "session.killsThisSession", 10)
-- Player leaves and rejoins -> session.killsThisSession is 0 again

Troubleshooting

ProblemCauseFix
Session data not syncing to clientClient may not be readyUse PlayerState.IsReady() before reads
SetOfflineData fails for session pathRuntime roots are not persistedUse SetPath when player is in-game only
Session values persist after rejoinWrong root usedEnsure data is under session (or configured runtime root)

PlayerState - High-Performance Roblox Data Management