Codectionary / Developer documentation / Luau

Retries, autosave and shutdown limits

A save can fail after gameplay succeeded. Keep the ready session available for another attempt, retry only a bounded number of times and report unresolved failures. PlayerRemoving and BindToClose are opportunities to save, not guarantees of durability.

Syntax

-- Save during normal operation; do not rely only on shutdown.
-- Track failures and keep pending data until acknowledged.

Examples

Bound retries outside the update callback

ModuleScript named LessonRetry in ServerScriptService, alongside LessonSave. This retries that idempotent highest-progress merge at most three times. Failed attempts remain failures; the helper never changes ready=false into ready=true.

local LessonSave = require(script.Parent:WaitForChild("LessonSave"))
local LessonRetry = {}
function LessonRetry.save(userId, session)
    for attempt = 1, 3 do
        local ok, reason = LessonSave.save(userId, session)
        if ok then return true end
        warn("Progress save failed", attempt, reason)
        if attempt < 3 then task.wait(2 ^ (attempt - 1)) end
    end
    return false
end
return LessonRetry

Understand a shutdown hook in isolation

Server Script wiring fragment, not a complete persistence system. sessionsByUserId must be the same table populated by your successful load flow, not a second empty table. This demonstrates bounded parallel dispatch; platform shutdown can still interrupt outstanding requests.

-- Integration fragment: sessionsByUserId is owned by your session manager.
local LessonRetry = require(script.Parent:WaitForChild("LessonRetry"))
game:BindToClose(function()
    local pending = 0
    for userId, session in pairs(sessionsByUserId) do
        if session.ready then
            pending += 1
            task.spawn(function()
                local ok, saved = pcall(LessonRetry.save, userId, session)
                if not ok or not saved then warn("Shutdown save unresolved", userId) end
                pending -= 1
            end)
        end
    end
    local deadline = os.clock() + 20
    while pending > 0 and os.clock() < deadline do task.wait(0.1) end
    if pending > 0 then warn("Shutdown deadline reached with pending saves") end
end)

Best practices

  • Add staggered autosaves during normal play, bounded concurrency and request-budget awareness; never save every frame.
  • Coordinate PlayerRemoving, autosave and shutdown so a session does not start overlapping writes. Snapshot or version pending changes and clear dirty state only for the version acknowledged.
  • Retries can repeat a write after an uncertain response. Use idempotent merges or an operation-ID protocol, and monitor failures rather than promising guaranteed saves.

At a glance

Purpose
Typed scripting and Roblox development
File extension
.luau
Runs in
Luau host; Roblox engine examples require Roblox Studio
Usually used with
Roblox APIs and Studio

Specifications & further reading

Related Luau documentation