Data
How to Make a Roblox Global Leaderboard GUI
A global leaderboard ranks every player by a stat like total coins, and the ranking persists across servers. The hard part isn't the GUI — it's storing sorted data with OrderedDataStore and reading the top players back. This guide covers the full loop: save a score, fetch the top 10, and render them as rows. Start from the leaderboard template for the row layout.
Open the Leaderboard template →1. Store ranked data with OrderedDataStore
An OrderedDataStore keeps values sortable. Use the player's UserId as the key and their score as the value, so each player appears once.
local DataStoreService = game:GetService("DataStoreService")
local scores = DataStoreService:GetOrderedDataStore("CoinsLeaderboard")
local function saveScore(player, coins)
scores:UpdateAsync(tostring(player.UserId), function(old)
return math.max(old or 0, coins)
end)
end2. Read the top players
GetSortedAsync returns the entries in order. Pass false for descending (highest first) and a page size. GetCurrentPage gives the ranked list of { key, value }.
local function getTop(n)
local page = scores:GetSortedAsync(false, n)
local entries = {}
for _, entry in ipairs(page:GetCurrentPage()) do
local userId = tonumber(entry.key)
local player = game:GetService("Players"):GetNameFromUserIdAsync(userId)
table.insert(entries, { name = player, score = entry.value })
end
return entries
end3. Send the list to clients and build rows
Fire a RemoteEvent with the top list; each client builds a row per entry. Because the panel has a UIListLayout, parenting each row stacks it automatically.
-- Server
local remote = game.ReplicatedStorage:WaitForChild("LeaderboardUpdate")
task.spawn(function()
while true do
remote:FireAllClients(getTop(10))
task.wait(60) -- refresh once a minute
end
end)
-- Client: make one row per entry, parented to the panel
local function makeRow(rank, name, score)
local row = Instance.new("Frame")
row.Size = UDim2.fromScale(1, 0.14)
row.Parent = panel
-- ...rank label, name label, score label...
return row
endFAQ
How often should I refresh a global leaderboard?
OrderedDataStore has tight rate limits. Cache the top list and refresh every 30–60 seconds via a server loop, never on every score change.
Why does a player appear twice?
You're using something other than UserId as the key. Always key by tostring(player.UserId) so each player maps to exactly one entry.