How to Fix 'DataStore request was added to queue' Warnings
Last updated:
Quick answer: 'DataStore request was added to queue' means your server is sending DataStore calls faster than its request budget allows, so Roblox is holding them back. Fix it by sending fewer requests: save once per player on leave instead of constantly, store a player's data in one key, and check DataStoreService:GetRequestBudgetForRequestType before calling.
The warning "DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests." means your server is calling DataStore faster than Roblox allows. The request is not lost yet. It is waiting in line. But if the line fills up, later requests are dropped, and a dropped save is a player losing progress.
Treat this warning as an early alarm. Fix it before it becomes missing data.
How DataStore Limits Work
Each server gets a request budget for every type of DataStore call (get, set, update, and so on). The budget refills over time and grows with the number of players in the server. When you use it up, new requests queue. When the queue is full, they are dropped with an error.
You can read the remaining budget directly:
local DataStoreService = game:GetService("DataStoreService")
local budget = DataStoreService:GetRequestBudgetForRequestType(
Enum.DataStoreRequestType.UpdateAsync
)
print("UpdateAsync budget left:", budget)
Common request types are GetAsync, SetIncrementAsync (covers SetAsync and IncrementAsync), UpdateAsync and GetSortedAsync. If the budget is near zero, you are about to be throttled.
The Usual Causes
Saving on every change. A common pattern is to save a coin value every time it changes. If a player collects 10 coins a second, that is 10 requests a second per player.
-- BAD: one request per coin
coins.Changed:Connect(function()
store:SetAsync("Player_" .. player.UserId, coins.Value)
end)
One key per stat. Saving coins, level and inventory under three separate keys triples your requests. Put everything for a player in one table under one key.
Autosave loops that fire for everyone at once. A loop that saves every player each second, or all players on the same tick, creates spikes.
Saving on both PlayerRemoving and BindToClose without a guard. When the server shuts down, both fire for every player, doubling requests at exactly the wrong moment.
Repeated reads. Calling GetAsync every time you need a value instead of keeping it in memory.
The Fix: Load Once, Keep in Memory, Save Rarely
Read the data once when the player joins, keep it in a table, and write it back on a timer and when they leave:
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("PlayerData")
local cache: { [number]: { coins: number, level: number } } = {}
local saving: { [number]: boolean } = {}
local DEFAULT = { coins = 0, level = 1 }
local function load(player: Player)
local key = "Player_" .. player.UserId
local ok, result = pcall(function()
return store:GetAsync(key)
end)
if ok then
cache[player.UserId] = result or table.clone(DEFAULT)
else
warn("Load failed:", result)
player:Kick("Could not load your data. Please rejoin.")
end
end
local function save(player: Player)
local userId = player.UserId
local data = cache[userId]
if not data or saving[userId] then
return
end
saving[userId] = true
local ok, err = pcall(function()
store:UpdateAsync("Player_" .. userId, function()
return data
end)
end)
saving[userId] = nil
if not ok then
warn("Save failed:", err)
end
end
Players.PlayerAdded:Connect(load)
Players.PlayerRemoving:Connect(function(player)
save(player)
cache[player.UserId] = nil
end)
Now the rest of your game changes cache[player.UserId].coins as often as it wants, and no request is made. For the full setup, see our DataStore guide.
Add a Staggered Autosave
An autosave protects against crashes. Space it out so players do not all save in the same second:
local AUTOSAVE_INTERVAL = 120
task.spawn(function()
while true do
task.wait(AUTOSAVE_INTERVAL)
for _, player in Players:GetPlayers() do
local budget = DataStoreService:GetRequestBudgetForRequestType(
Enum.DataStoreRequestType.UpdateAsync
)
if budget > 5 then
save(player)
end
task.wait(1)
end
end
end)
The task.wait(1) between players spreads the load, and the budget check skips a save if the budget is low. That player will be saved on the next cycle or when they leave. Use task.wait, not the old wait; the difference is explained in task.wait vs wait.
Handle Server Shutdown Safely
BindToClose gives you a short window to save everyone:
game:BindToClose(function()
for _, player in Players:GetPlayers() do
task.spawn(save, player)
end
task.wait(3)
end)
The saving guard in save stops the same player from being written twice when both PlayerRemoving and BindToClose fire.
Common Mistakes
- Retrying in a tight loop. If a call fails, do not immediately call it again. Wait a few seconds between retries, and cap the number of attempts.
- Using SetAsync for data other servers might change. Prefer
UpdateAsyncfor player data so you do not overwrite a newer value. - Saving values nobody needs. Do not store things you can recompute. Fewer fields means smaller payloads, which also helps with the 4 MB value limit.
- Ignoring the warning in Studio. Studio shares the live budget model. If it shows up in testing, it will be worse with real players.
If Data Is Still Not Saving
A queue warning is about volume. If your saves fail for other reasons (permissions, API access, silent errors), read why DataStore is not saving and the guide to the DataStore 403 error.
Practice
Keeping state in memory and syncing on events is a pattern you will reuse in every game. The Luablox lessons walk through tables and persistence step by step, and the problems page lets you practice the table handling in the browser.
Frequently asked questions
What does 'DataStore request was added to queue' mean?
Your server hit its DataStore request budget, so Roblox is holding the request in a queue instead of sending it right away. If the queue fills up, further requests are dropped, which can cause lost saves.
Is this warning harmful or can I ignore it?
A single occasional warning is usually harmless, since the request will run once budget refills. Repeated warnings mean you are sending too many requests and risk dropped saves, so reduce your request volume.
How often should I save player data?
Save when the player leaves, when the server shuts down, and optionally on a slow autosave timer such as every two to five minutes, staggered across players. Do not save on every stat change.
How can I check how many DataStore requests I have left?
Call DataStoreService:GetRequestBudgetForRequestType with an Enum.DataStoreRequestType value such as UpdateAsync or GetAsync. It returns how many requests of that type you can still make right now.
Understand Roblox DataStoreService patterns to save player data, implement safety checks, and handle load failures.