Data stores
How the game loads and saves with DataStoreService: what happens when a load or save fails, whether two servers can hold the same player's data at once, whether servers can overwrite each other's writes, whether keys are tied to the player's UserId and chosen by the server, whether UpdateAsync callbacks stay pure, whether saving stays within Roblox's request budgets and size limits, whether each player gets fresh default data and saved tables come back with the keys they were saved with, and whether join and load code copes with players who arrive before it's ready or leave before it finishes.
Building a data store key from a user id or slot the client sent lets one player read or overwrite another's data. How to build keys on the server.
How to stop a failed data store load wiping player datacriticalTreating a failed load as a new player hands out default data, which is then saved over the real data. How to keep failed loads apart from new players.
How to stop cross-server markets duplicating itemscriticalReading a memory store listing and then removing it lets two servers sell it twice. How to claim entries safely with UpdateAsync.
How to session-lock player data in RobloxcriticalWithout a session lock, two servers can hold the same player's data and the later save wins. How session locking with UpdateAsync works.
Why Roblox player data should be saved by UserIdcriticalData store keys built from a player's name or display name break when they change it, and display names aren't unique. How to key saves by UserId instead.
Why numeric keys in saved Roblox data stop matchingcriticalData stores save number keys in tables without a list part as strings, so lookups by UserId or id miss after a rejoin. How to key saved tables with strings.
How to stop MemoryStore queue items paying out twicecriticalA queue item that isn't removed in time becomes visible again and gets processed twice. How to record each item's id so gifts and prizes are only granted once.
Why every player needs their own copy of default datacriticalOne default table handed to every new player, or copied with table.clone, shares its inventory between them. How to build fresh defaults for each player.
How to use UpdateAsync for values many servers changecriticalGetAsync followed by SetAsync lets two servers overwrite each other's changes to a bank, counter or limited stock. How to use UpdateAsync and IncrementAsync instead.
How to stop client strings breaking your data store savescriticalData stores only accept valid UTF-8, so one bad string can stop a whole profile saving. How to check with utf8.len and rebuild client tables on the server.
How to write a safe UpdateAsync callbackcriticalGranting coins or items inside an UpdateAsync callback can pay twice when the write fails. How to keep the callback pure and grant after it succeeds.
How to check whether a failed data store write was savedwarningGetAsync can return a cached value for four seconds, so a check after a failed write can be wrong. How to read past the cache before refunding.
How to run join code for players already in the serverwarningA script that waits before connecting PlayerAdded misses players who join during the wait. How to connect first and handle existing players too.
What to do when a player leaves before their data loadswarningA load that finishes after the player left can hold their session lock for the life of the server. How to check the player is still there before keeping the data.
Why purchases and bans don't belong in memory storeswarningMemory store entries expire and writes fail at the quota. What to keep in data stores instead, and when memory stores are the right tool.
How to send gifts between servers without losing themwarningMessagingService doesn't promise delivery, so gifts and staff changes sent only as messages can vanish. How to save them first and use messages to speed things up.
How to stay within data store request limitswarningSaving on every coin, kill or second played uses up the server's data store budget and gets saves dropped. How to keep values in memory and save on a timer.
How to stop player data outgrowing the data store size limitwarningBuilds, drawings and lists with no cap can grow past the 4 MB limit and stop a profile saving. How to cap and bound what players add to saved data.
How to save player data so deletion requests can find itwarningRoblox's deletion templates match a UserId in the key, not inside a value. How to lay out data stores so a player's data can be erased.
How to save player data when a Roblox server shuts downwarningSaving only in PlayerRemoving can lose data when a server closes. How to use BindToClose to wait for every save to finish.
Each guide covers one problem. Fixing every one of them makes a game harder to exploit, but it doesn't make it secure on its own: review your own game logic too.