โ† All guides
2025-05-01ยท6 min read

How to Make a Roblox DataStore (Save Player Data)

Learn how to save and load player data in Roblox Studio using DataStoreService. Step-by-step guide with working Luau code examples for beginners.

What is a DataStore?

A DataStore is how you save player data between sessions in Roblox. Without it, everything resets when the player leaves โ€” their cash, level, inventory, all gone. DataStores let you store that data permanently on Roblox's servers.

Setting Up DataStoreService

First, make sure API Services are enabled in your game. Go to Game Settings โ†’ Security โ†’ Enable Studio Access to API Services.

Then in a Script inside ServerScriptService:

local DataStoreService = game:GetService("DataStoreService")
local db = DataStoreService:GetDataStore("PlayerData_v1")

The string "PlayerData_v1" is just a name โ€” you can call it anything. Adding a version number (v1, v2) is good practice so you can reset data later if needed.

Saving Data When the Player Leaves

game.Players.PlayerRemoving:Connect(function(player)
    local cash = player.leaderstats and player.leaderstats:FindFirstChild("Cash")
    if cash then
        local ok, err = pcall(function()
            db:SetAsync(player.UserId, { Cash = cash.Value })
        end)
        if not ok then
            warn("Failed to save data for " .. player.Name .. ": " .. err)
        end
    end
end)

Always wrap DataStore calls in pcall. DataStores can fail โ€” the server might be busy, the player might disconnect mid-save, anything. If you don't use pcall, a failed save will crash your script entirely.

Loading Data When the Player Joins

game.Players.PlayerAdded:Connect(function(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player

    local cash = Instance.new("IntValue")
    cash.Name = "Cash"
    cash.Value = 0
    cash.Parent = leaderstats

    local ok, data = pcall(function()
        return db:GetAsync(player.UserId)
    end)

    if ok and data then
        cash.Value = data.Cash or 0
    end
end)

Auto-Save Every 60 Seconds

Players sometimes crash or get disconnected before PlayerRemoving fires. Add a backup auto-save:

task.spawn(function()
    while task.wait(60) do
        for _, player in ipairs(game.Players:GetPlayers()) do
            local cash = player.leaderstats and player.leaderstats:FindFirstChild("Cash")
            if cash then
                pcall(function()
                    db:SetAsync(player.UserId, { Cash = cash.Value })
                end)
            end
        end
    end
end)

Common DataStore Mistakes

Using player.Name instead of player.UserId โ€” Names can change. UserId is permanent. Always use UserId as your key.

Not using pcall โ€” DataStore calls can fail. Always wrap them.

Saving too often โ€” DataStores have rate limits. Don't save on every coin collected or every kill. Save on PlayerRemoving and auto-save every 60 seconds.

Not versioning your data โ€” If you change what you save (add a new stat), old data won't have it. Always use or defaultValue when reading: data.Cash or 0.

Ready to Use

Want a complete working DataStore script you can drop right in? Check out our DataStore Save & Load script โ€” fully commented and tested.

Ready-made scripts for your game

Browse our free library of copy-paste Luau scripts โ€” no setup needed.

Browse Script Library โ†’
More guides
Roblox Scripting for Beginners: Complete 2025 Guide8 min read โ†’How to Make a Roblox Shop System (Buy Items with Cash)7 min read โ†’Roblox NPC Scripting Guide: Pathfinding, Dialogue & More7 min read โ†’