Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
sentinelcore avatar

Roblox Datastores

  • 394 installs
  • 11 repo stars
  • Updated February 23, 2026
  • sentinelcore/roblox-skills

roblox-datastores is a Claude agent skill that implements Roblox DataStoreService patterns for saving, loading, and migrating player stats, inventory, and leaderboards for developers building server-side persistence with

About

roblox-datastores is a Claude Code skill from sentinelcore/roblox-skills that serves as a reference for Roblox DataStoreService server-side player data persistence. The skill covers GetDataStore and GetOrderedDataStore APIs, saving and loading player stats or inventory, building ordered leaderboards, handling data migration between game versions, diagnosing data loss issues, and adding auto-save with shutdown-safe write patterns. Roblox developers reach for roblox-datastores when implementing server scripts that must persist player progress beyond a single session without corrupting data on server close or version upgrades. The quick-reference table documents method signatures like DSS:GetDataStore(name, scope?) returning a GlobalDataStore and GetOrderedDataStore for leaderboard rankings. The skill targets Luau server developers shipping live Roblox experiences who need agent-guided DataStore patterns instead of trial-and-error persistence code. Guidance emphasizes server-authoritative writes, retry handling, and safe shutdown flushes to reduce player data loss incidents.

  • roblox-datastores
  • AI & Agent Building
  • AI-coding skill

Roblox Datastores by the numbers

  • 394 all-time installs (skills.sh)
  • +28 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #2,010 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sentinelcore/roblox-skills --skill roblox-datastores

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs394
repo stars11
Last updatedFebruary 23, 2026
Repositorysentinelcore/roblox-skills

How do you persist player data in Roblox DataStoreService?

Helps with ai & agent building tasks.

Who is it for?

Roblox server developers implementing player stats, inventory persistence, leaderboards, or data migration with DataStoreService.

Skip if: Client-only UI work, non-Roblox databases, or games that do not require cross-session player data persistence.

When should I use this skill?

A developer implements Roblox player data saving, leaderboards with ordered datastores, data migration between versions, or diagnoses DataStore data loss.

What you get

Server-side Luau persistence modules with save/load handlers, ordered leaderboard stores, migration logic, and auto-save shutdown routines.

  • DataStore save/load module
  • ordered leaderboard handler
  • migration and auto-save routines

By the numbers

  • Documents 2 core DataStoreService methods: GetDataStore and GetOrderedDataStore
  • Covers 5 persistence scenarios: stats, inventory, leaderboards, migration, and auto-save

Files

SKILL.mdMarkdownGitHub ↗

roblox-datastores

Reference for Roblox DataStoreService — saving, loading, and managing player data on the server.

Quick Reference

MethodSignatureNotes
GetDataStoreDSS:GetDataStore(name, scope?)Returns a GlobalDataStore
GetOrderedDataStoreDSS:GetOrderedDataStore(name, scope?)For leaderboards
GetAsyncstore:GetAsync(key)Returns value or nil
SetAsyncstore:SetAsync(key, value)No return value needed
UpdateAsyncstore:UpdateAsync(key, fn)Atomic read-modify-write
RemoveAsyncstore:RemoveAsync(key)Deletes key, returns old value
GetSortedAsyncorderedStore:GetSortedAsync(asc, pageSize)Returns DataStorePages

---

Basic Setup

-- Server Script (ServerScriptService)
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local playerStore = DataStoreService:GetDataStore("PlayerData_v1")

local DEFAULT_DATA = {
    coins = 0,
    level = 1,
    xp = 0,
}

---

Loading Data (GetAsync + pcall)

Always wrap datastore calls in pcall. They can fail due to network issues or rate limits.

local function loadData(player)
    local key = "player_" .. player.UserId
    local success, data = pcall(function()
        return playerStore:GetAsync(key)
    end)

    if success then
        local result = {}
        for k, v in pairs(DEFAULT_DATA) do result[k] = v end
        if data then
            for k, v in pairs(data) do result[k] = v end
        end
        return result
    else
        warn("Failed to load data for", player.Name, ":", data)
        return nil -- signal failure; do not give default data silently
    end
end

---

Saving Data (SetAsync vs UpdateAsync)

Use SetAsync for simple overwrites. Use UpdateAsync when the value must be based on the current stored value (e.g., incrementing a counter safely across servers).

-- Simple save
local function saveData(player, data)
    local key = "player_" .. player.UserId
    local success, err = pcall(function()
        playerStore:SetAsync(key, data)
    end)
    if not success then
        warn("Failed to save data for", player.Name, ":", err)
    end
end

-- Atomic increment with UpdateAsync
local function addCoinsAtomic(userId, amount)
    local key = "player_" .. userId
    pcall(function()
        playerStore:UpdateAsync(key, function(current)
            current = current or { coins = 0 }
            current.coins = current.coins + amount
            return current
        end)
    end)
end

---

Retry Logic

local MAX_RETRIES = 3
local RETRY_DELAY = 2

local function safeGet(store, key)
    for attempt = 1, MAX_RETRIES do
        local success, result = pcall(function()
            return store:GetAsync(key)
        end)
        if success then return true, result end
        warn(string.format("GetAsync attempt %d/%d failed: %s", attempt, MAX_RETRIES, result))
        if attempt < MAX_RETRIES then task.wait(RETRY_DELAY) end
    end
    return false, nil
end

---

Auto-Save: PlayerRemoving + BindToClose

Server shutdown without BindToClose silently discards unsaved data.

local sessionData = {} -- [userId] = data table

Players.PlayerAdded:Connect(function(player)
    local data = loadData(player)
    if data then
        sessionData[player.UserId] = data
    else
        player:Kick("Could not load your data. Please rejoin.")
    end
end)

Players.PlayerRemoving:Connect(function(player)
    local data = sessionData[player.UserId]
    if data then
        saveData(player, data)
        sessionData[player.UserId] = nil
    end
end)

-- Flush all sessions on server shutdown
game:BindToClose(function()
    for userId, data in pairs(sessionData) do
        local key = "player_" .. userId
        pcall(function()
            playerStore:SetAsync(key, data)
        end)
    end
end)

---

Ordered DataStores (Leaderboards)

Values must be positive integers.

local coinsLeaderboard = DataStoreService:GetOrderedDataStore("Coins_v1")

local function setLeaderboardScore(userId, coins)
    pcall(function()
        coinsLeaderboard:SetAsync("player_" .. userId, math.floor(coins))
    end)
end

local function getTopPlayers(count)
    local success, pages = pcall(function()
        return coinsLeaderboard:GetSortedAsync(false, count) -- false = descending
    end)
    if not success then return {} end

    local results = {}
    for rank, entry in ipairs(pages:GetCurrentPage()) do
        table.insert(results, { rank = rank, userId = entry.key, score = entry.value })
    end
    return results
end

---

Data Versioning / Migration

Include a _version field and migrate in the load path.

local CURRENT_VERSION = 2

local function migrateData(data)
    local version = data._version or 1
    if version < 2 then
        data.coins = data.gold or 0  -- renamed field
        data.gold = nil
        data._version = 2
    end
    return data
end

Use a versioned datastore name (PlayerData_v2) for breaking schema changes.

---

Common Mistakes

MistakeConsequenceFix
No pcall around datastore callsUnhandled error crashes the scriptAlways wrap in pcall
Saving on every Changed eventHits rate limits (60 + numPlayers×10 writes/min)Throttle; save on remove + periodic interval
No BindToClose handlerData lost on server shutdownAlways flush all sessions in BindToClose
Giving default data on load failurePlayer silently loses progressReturn nil on failure; kick or retry
SetAsync for atomic countersRace condition across serversUse UpdateAsync for read-modify-write
Storing Instances or functionsData silently dropsStore only strings, numbers, booleans, plain tables
Reusing datastore name after schema changeOld shape clashes with new codeAppend _v2, _v3 to name on breaking changes

Related skills

How it compares

Use roblox-datastores for Roblox cloud persistence; use general database skills when persistence runs outside the Roblox DataStoreService API.

FAQ

Which DataStoreService methods does roblox-datastores cover?

roblox-datastores documents DataStoreService:GetDataStore(name, scope?) for GlobalDataStore player persistence and GetOrderedDataStore(name, scope?) for leaderboard rankings. The skill provides quick-reference signatures and implementation patterns for server-side Luau scripts.

When should roblox-datastores be activated?

roblox-datastores activates when implementing player data persistence, saving or loading stats and inventory, building ordered leaderboards, handling data migration between versions, diagnosing data loss, or adding auto-save and shutdown-safe data handling with DataStoreService o

Does roblox-datastores handle data migration?

roblox-datastores includes guidance for migrating player data between game versions so schema changes do not wipe existing saves. Patterns cover versioned keys, backward-compatible reads, and safe write paths when deploying updates to live Roblox experiences.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.