Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.
Save data
Games often need to store persistent data between sessions, such as a player's level, game points, money, inventory items, location, and more.
This tutorial shows how to create a basic data store, save player data, and read the data back into a player session.
Enable Studio access
By default, games tested in Studio cannot access data stores, so you must first enable them:
- Publish the game.
- Open Studio's File ⟩ Experience Settings window.
- In the Security section, turn on Enable Studio Access to API Services and click Save.
Create a data store
Data stores require a unique name. This example creates a data store named PlayerGold that saves each player's gold in persistent storage:
Create a
ScriptwithinServerScriptServicecalled GoldManager.
Data stores are managed by
DataStoreService, so get the service:local DataStoreService = game:GetService("DataStoreService")Call
DataStoreService:GetDataStore()with the string"PlayerGold". This method accesses the PlayerGold data store if it already exists. If it doesn't exist, the method creates a new data store and names it PlayerGold.local DataStoreService = game:GetService("DataStoreService") local goldStore = DataStoreService:GetDataStore("PlayerGold")
Save data
A data store is essentially a dictionary, like a Luau table. Each value in the data store is indexed by a unique key, which might be the player's unique UserId or simply a named string.
Player Data Example
| Key | Value |
|---|---|
| `31250608` | `50` |
| `351675979` | `20` |
| `505306092` | `78000` |
Promo Examples
| Key | Value |
|---|---|
| `ActiveSpecialEvent` | `SummerParty2` |
| `ActivePromoCode` | `BONUS123` |
| `CanAccessPartyPlace` | `true` |
To save player data in the data store:
Create a variable named
playerUserIDfor the data store key. Then, useplayerGoldto store a player's starting gold amount.local DataStoreService = game:GetService("DataStoreService") local goldStore = DataStoreService:GetDataStore("PlayerGold") -- Data store key and value local playerUserID = 505306092 local playerGold = 250To save data into the
PlayerGolddata store, callSetAsyncwithin a protected call, passing the key and value variables previously created.local DataStoreService = game:GetService("DataStoreService") local goldStore = DataStoreService:GetDataStore("PlayerGold") -- Data store key and value local playerUserID = 505306092 local playerGold = 250 -- Set data store key local success, error = pcall(function() goldStore:SetAsync(playerUserID, playerGold) end) if not success then warn(error) end
Functions like SetAsync() are network calls that may occasionally fail. As shown above, LuaGlobals.pcall() is used to detect and handle when such failures occur.
In its most basic form, LuaGlobals.pcall() accepts a function and returns two values:
- The status, which is
trueif the function executed without errors, orfalseotherwise. - The return value of the function or an error message.
The sample above checks status on line 13. If SetAsync() fails for any reason, the sample displays the error in the Output window.
Note
Be careful to not send requests to data stores too often. Requests on a data store key are placed in a queue and, if the queue fills up, additional requests are dropped.
A common mistake may be updating a player's gold data every time they collect a gold piece. Instead, store the player's gold in a variable and only update the data store occasionally, such as with a periodic auto-save and/or when the player leaves the game.
Read data
To read data from a data store, call GetAsync() with the desired key name.
local DataStoreService = game:GetService("DataStoreService")
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Data store key and value
local playerUserID = 505306092
local playerGold = 250
-- Set data store key
local setSuccess, errorMessage = pcall(function()
goldStore:SetAsync(playerUserID, playerGold)
end)
if not setSuccess then
warn(errorMessage)
end
-- Read data store key
local getSuccess, currentGold = pcall(function()
return goldStore:GetAsync(playerUserID)
end)
if getSuccess then
print(currentGold)
end To test the script, initiate a playtest and notice the currentGold value printed to the Output window. Note that it may take a couple seconds, as the functions must connect to data store servers.
Read and save automatically
The previous script works, but has a fundamental problem: it includes hard-coded values for playerUserID and playerGold, so it doesn't support multiple players with different amounts of gold. A more realistic solution reads the gold value when the player connects to the game and then saves it when the player leaves. This approach means connecting the data store calls to events from the Players service.
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Add gold values for each player to a local table to avoid hitting the data
-- store repeatedly.
local playerGold = {}
local function incrementGold(player, amount)
playerGold[player.UserId] += amount
end
local function onPlayerAdded(player)
-- Read data store key
local success, storedGold = pcall(function()
return goldStore:GetAsync(player.UserId)
end)
if success then
local currentGold
if storedGold then
currentGold = storedGold
else
currentGold = 0
end
playerGold[player.UserId] = currentGold
print(currentGold)
end
-- Test incrementing gold
incrementGold(player, 5)
end
local function onPlayerRemoving(player)
-- Set data store key
local success, err = pcall(function()
goldStore:SetAsync(player.UserId, playerGold[player.UserId])
end)
if not success then
warn(err)
end
-- Clean up entry so that the table doesn't grow for the lifespan of the server
playerGold[player.UserId] = nil
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving) Read and save character position
To save player position, you work with the Character rather than the Player, but the principle is similar. This time, create a Script within ServerScriptService called PositionManager:
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Workspace = game:GetService("Workspace")
local playerPositionStore = DataStoreService:GetDataStore("PlayerPositionStore")
local function positionHandler(player)
-- Load position on character add
player.CharacterAdded:Connect(function(character)
local success, coords = pcall(function()
return playerPositionStore:GetAsync(player.UserId)
end)
local position = Vector3.new(coords[1], coords[2], coords[3])
if success and position then
character:PivotTo(CFrame.new(position))
print("Loaded player position!")
else
warn("Failed to load position for player " .. player.Name .. ". Placing in default position.")
end
-- Handle player respawn on death
local humanoid = character:FindFirstChildOfClass("Humanoid")
humanoid.Died:Connect(function()
local spawnLocation = Workspace:FindFirstChild("SpawnLocation")
character:PivotTo(spawnLocation.CFrame)
end)
end)
-- Save position on character removal
player.CharacterRemoving:Connect(function(character)
local position = character:GetPivot().Position
local success, err = pcall(function()
playerPositionStore:SetAsync(player.UserId, {position.X, position.Y, position.Z})
print("Saved player position!")
end)
if not success then
warn("Failed to save position for player " .. player.Name .. ": " .. err)
end
end)
end
Players.PlayerAdded:Connect(positionHandler) This script adds a new data store, playerPositionStore. Because data stores only store basic types rather than objects, you have to store X, Y, and Z coordinates as individual numbers rather than a single Vector3 or CFrame value. As you test your game, move your character around. Note how your character returns to the same position the next time you test your game.
Sample project
Now that you understand basic data store usage, test it out in the Gold Rush sample game. You can also edit the game in Studio and explore the enhanced GoldManager script, which displays gold as part of the UI and includes auto-saving.