§ How to · with Forge AI
How to make a Roblox leaderboard (with AI)
A Roblox top-scores leaderboard needs three wired-up parts: an OrderedDataStore for cross-server ranking, a 60-second refresh loop, and a SurfaceGui that displays the top N. Forge AI generates all three in 31 seconds.
4 files · 110 lines · 31 seconds · 1 credit. Cross-server, throttle-safe.
OrderedDataStore
Sorted by numeric score across all servers. Top 10 read in a single :GetSortedAsync call.
60-second refresh
Server polls top 10 every 60 seconds and pushes to clients via RemoteEvent. Roblox throttles OrderedDataStore reads — polling is bounded by design.
SurfaceGui display
Top 10 names + scores displayed on a SurfaceGui Part. Configurable for ScreenGui too.
Score push
On qualifying event (level up, death, win), server writes a new score to the OrderedDataStore atomically.
Cross-server ranking
Players see the same top 10 regardless of which server they joined. OrderedDataStore handles the sort.
Username resolution
Stored player UserIds are resolved to display names via Players:GetNameFromUserIdAsync, cached for 5 minutes.
Files Forge AI ships for this prompt
4 files · 110 lines · 31 seconds · 1 credit
ServerScriptService/LeaderboardServer.lua
OrderedDataStore reader + 60s loop + push to clients
64 lines
ServerScriptService/ScoreWriter.lua
Public API: ScoreWriter:Submit(player, score)
24 lines
ReplicatedStorage/Remotes/LeaderboardUpdate
Server → client top 10 push
instance
StarterGui/LeaderboardUI.lua
SurfaceGui rows + name resolution
22 lines
Sample output: ServerScriptService/LeaderboardServer.lua
--!strict
-- ServerScriptService/LeaderboardServer.lua (Forge AI · excerpt)
local DataStoreService = game:GetService("DataStoreService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LeaderboardUpdate = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("LeaderboardUpdate")
local store = DataStoreService:GetOrderedDataStore("TopScores_v1")
local function fetchTop10(): { { userId: number, score: number } }
local ok, pages = pcall(function()
return store:GetSortedAsync(false, 10)
end)
if not ok then return {} end
local entries: { { userId: number, score: number } } = {}
for _, e in ipairs(pages:GetCurrentPage()) do
table.insert(entries, { userId = tonumber(e.key) or 0, score = e.value })
end
return entries
end
task.spawn(function()
while true do
local top = fetchTop10()
for _, player in ipairs(game.Players:GetPlayers()) do
LeaderboardUpdate:FireClient(player, top)
end
task.wait(60)
end
end)Building a Roblox leaderboard
Cross-server leaderboards require OrderedDataStore — regular DataStore is not sorted, so retrieving top N is O(all keys). The Forge AI leaderboard uses OrderedDataStore with GetSortedAsync to read top 10 in one network call.
The 60-second refresh interval is set by Roblox throttling. OrderedDataStore reads are rate-limited per server — too-frequent polling drops requests. 60 seconds is the well-known sweet spot: low enough to feel live, slow enough to never throttle. Forge AI's default polling loop respects this; tune up to faster only if you have a small player base.
Score submission is atomic. ScoreWriter:Submit(player, score) writes the new score to the OrderedDataStore — Roblox handles the sort. The submit is fire-and-forget; the server poll picks up new entries on the next 60-second tick.
Username resolution is the often-missed part. Stored entries are UserIds (numeric, the only stable identifier). Display names need Players:GetNameFromUserIdAsync — but that has a per-call cost. Forge AI caches resolved names for 5 minutes per UserId, so a stable top 10 only resolves names once and reuses them across refreshes.
The display layer is decoupled. Same data flows into a SurfaceGui leaderboard board, a ScreenGui side panel, or a podium with 3D models for top 3. Default is a SurfaceGui Part — the highest-impact placement for most game lobbies.
See more on the Luau generator, the game builder, or browse the full blog.
Frequently asked
Why OrderedDataStore and not regular DataStore?+
OrderedDataStore is sorted by numeric value and supports GetSortedAsync — top N retrieved in one call. Regular DataStore would require iterating every key, which is impossible at scale.
How often does the leaderboard refresh?+
Default 60 seconds. Roblox throttles OrderedDataStore reads aggressively, so 60 seconds is the sweet spot for cross-server display.
Can I show top 100 instead of top 10?+
Yes. GetSortedAsync supports up to 100 per page. For 1000+, paginate via :AdvanceToNextPageAsync. Network cost grows with size — top 10 is the standard.
What about per-game-mode or per-week leaderboards?+
Use a separate OrderedDataStore per scope (TopScores_FFA, TopScores_Capture). For weekly resets, key by ISO week (TopScores_2026W14) and the new week starts empty.
Is the SurfaceGui the only display option?+
No — same data flows into a ScreenGui list, a podium with 3D models for top 3, or a full screen on death. The Forge AI default is a SurfaceGui Part because that is the most common; swap UI in StarterGui/LeaderboardUI.lua.
Related Forge AI prompts
How to use Roblox DataStore the right way
3 files · 140 lines · 36 seconds · 1 credit. Drop-in save service for any game.
Roblox tycoon
9 files · 260 lines · 1m 04s · 1 credit. Per-player tycoon plots cloned from ReplicatedStorage.
Roblox simulator
8 files · 240 lines · 58 seconds · 1 credit. Tap, earn, rebirth, repeat.