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, and whether saving stays within Roblox's request budgets and size limits.

Back to categories
Why the client should never choose a data store keycritical

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 datacritical

Treating 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 itemscritical

Reading 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 Robloxcritical

Without 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 UserIdcritical

Data 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.

How to stop MemoryStore queue items paying out twicecritical

A 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.

How to use UpdateAsync for values many servers changecritical

GetAsync 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 savescritical

Data 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 callbackcritical

Granting 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 savedwarning

GetAsync 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.

Why purchases and bans don't belong in memory storeswarning

Memory 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 themwarning

MessagingService 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 limitswarning

Saving 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 limitwarning

Builds, 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 itwarning

Roblox'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 downwarning

Saving 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.