Datastore sent too frequently on datastore2

Hello , i got a warning from console , i dont know why and please help me because i supposed to public the game today . pls help me :disappointed_relieved:

local DataStoreService = game:GetService("DataStoreService")
local oldDataStore = DataStoreService:GetDataStore("DataSaver001") -- money DATA
local playerData = DataStoreService:GetDataStore("PlayerData") -- Vehicle DATA
local helmetData = DataStoreService:GetDataStore("Helmet") -- Helmet DATA
local newDataStore = require(script.DataStore2)
newDataStore.Combine("DataSaver001", "PlayerData") -- combining it


--- MONEY FUNCTION OK 
local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end


-- MOTOR FUNCTION #1
local function CreateCarValue(player, name, value)
	local carValue = player.OwnedCars:FindFirstChild(name)
	if not carValue then
		carValue = Instance.new("BoolValue")
		carValue.Name = name
		carValue.Parent = player.OwnedCars
	end
	carValue.Value = value
	return carValue
end

--MOTOR FUNCTION #2 -- MOTOR TABLE
local function CreateTable(player)
	local playerStats = {}
	for _, stat in pairs(player.OwnedCars:GetChildren()) do
		if stat.Value == true then
			playerStats[stat.Name] = true
		end
	end
	return playerStats
end


-- MOTOR FUNCTION #3
local cars = {
	-- list cars put here ok
	"HondeEX5",
	"HondeWave100",
	"Kasaki 150sp",
	"Lagenda115zr",
	"Lajak",
	"Rzx Milinium",
	"Wave125i Drag",
	"Light Lz",
	"Yamha Soleriz",
	"Yamha 125rz",
	"Sniper150Drag",
	"Yamha Sniper135 v1",
	"Honde Deo",
	"Honde Nsr500",
	"Icikiwir",
	"Yamha Yzr500",
	"Honde Wave 125r",
	"Kasaki Pdk R1",
	"Dukatti SuperSport S",
	"Kasaki Serpico",
	"Yamha X1r",
	"Vesp 150ss",
	"Dukatti 1299",
	"Yamha Sniper v2",
	"Suzuka Raider 150",
	"Kasaki Ninja H2",
	"Yamha R6 v2",
	"Suzuka Hayabusa Drag",
	"Yamha X1r White",
	"Mz Agusza F4",
	"Honde NR750",
	"Dukatti 1199 Martini"
}




local function onPlayerJoin(player)
	-- Money Section
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Parent = leaderstats
	
	--- Motor Section
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "OwnedCars"
	leaderstats.Parent = player
	
	--- Money Section
	local MoneyStats = newDataStore("MoneyData1", player)
	local data = MoneyStats:Get()
	
	
	if not data then 

		local oldData = oldDataStore:GetAsync(player.UserId.."-Money")
		print("oldData for player " .. player.Name .. ": " .. tostring(oldData))
		if oldData then
			data = oldData
			MoneyStats:Set(data)
		else
			data = {Money=3000} 
			print(player.Name .." MONEY'S DATA not found from both data , creating a new data")
		end
	end
	
	if data then
		print("money loaded for " .. player.Name)
	end

	if type(data) == "number" then
		money.Value = data
	else
		money.Value = data['Money']
	end
	money.Changed:Connect(function(value)
		MoneyStats:Set(create_table(player))
	end)
	
	
	-- Vehicle section ( not done yet )
	
	
	local MotorStats = newDataStore("VehicleData", player)
	local data1 = MotorStats:Get()

	if data1 then
		print("Motorsikal loaded forc" .. player.Name)
		for car, value in pairs(data1) do
			if value == true and table.find(cars, car) then
				CreateCarValue(player, car, true)
			end
		end
	else
		-- load old data
		local oldmotor = playerData:GetAsync("Player_" .. player.UserId)
		if oldmotor then
			print("Load for player " .. player.Name)

			for car, value in pairs(oldmotor) do
				if value == true and table.find(cars, car) then
					CreateCarValue(player, car, true)
				end
			end

			print("Saving for player " .. player.Name)
			MotorStats:Set(oldmotor)
		else
			print("NO DATA MOTORCYCLE FOUND FOR " .. player.Name)
		end
	end
end




local function onPlayerExit(player)
	local player_stats = create_table(player)
	local motor_stats = CreateTable(player)
	local MotorStats = newDataStore("VehicleData", player)
	local MoneyStats = newDataStore("MoneyData1", player)
	MotorStats:Set(motor_stats)
	MoneyStats:Set(player_stats)
	player.leaderstats.Money.Value = player_stats.Money
	print("money and motor saved for " .. player.Name)
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
1 Like

got warning when player try to load old data which is normal datastore . It works fine but when tons of player join at the same time , warning occur

you can only call asyncs once a 6 secconds, soo make loading, first load data store 1, and then data store 2 after 6 secconds, put some loading screen in your game, with text: “playing boblox” and then player will think something is loading, but remember to make a security lock, soo if player leaves data don’t save

I get it so i need to add gap between two data money and cars? But how bout if player joining the game but got kicked due game update ? So got no time to load the data . And what is security lock ?

wait how much request can i do maximum from getting warning ? 10 request every 6 sec? , i added function for money and vehicle , it should prevent from getting warning right ?

local function onPlayerJoin(player)
	-- Money Section
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Parent = leaderstats
	
	--- Motor Section
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "OwnedCars"
	leaderstats.Parent = player
	
	
	-- Load function
	MoneyFunction(player)
	VehicleFunction(player)

end

Ouh god please help me pleaseeee , i spent too much time on it players getting mad since game private . i would like to pay if someone could help me . IM STRESS

oh god

Old datastore is the same as new datastore so there is no need in “loading old data”.

Edit : yes you are right my bad im really bad with database

ITS REALLY WEIRD OK HOW DOES WARNING OCCUR IT SHOULD NEVER HAPPEN . THE WAY IT LOADS OLD DATA IS SAME AS MY OLD SCRIPT WHICH IS LITERALLY SAME . I JUST TRYNA PREVENT FROM DATALOSS , AND YES I DID BUT NOW I GOT PROBLEM WITH LOAD OLD DATA .yes

First, you should basically never change your DataStore, as it is a difficult to switch everything from the first to the second one (especially when your Game has 11 M. visits).

Then you are basically saying in your code, that first you want to check if there is any Data in the second DS and then immediately check after if there is any Data in the first DS. This is most likely causing the error. Putting a wait in between would solve this problem.

Just so you get what I mean:


else
     -- load old data
        wait(6)
	local oldmotor = playerData:GetAsync("Player_" .. player.UserId)

(Also make an proper loading screen minimal 7 sec.)

I get it , now the problem is how bout shutdown occur while load data? Edit : sorry i gotta change the data since dataloss always occur , let say if 100 of ppl , 2 or 3 ppl will experience the dataloss which i dont want it to happen

have you tried using something other than datastore2?

yes normal datastore , and yes dataloss
its my old script btw

– Money Data –

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataSaver001")
local Players = game:GetService("Players")

local playerData = {}

function savePlayerData(player)
	local success, error = pcall(function()
		playerData[player.UserId] = player.leaderstats.Money.Value
		DataStore:SetAsync(player.UserId.."-Money", player.leaderstats.Money.Value)
		print(player.Name .. "'s money data saved. Current money: " .. player.leaderstats.Money.Value)
	end)

	if not success then
		warn("Error while saving Money data: " .. error)
	end
end

function loadPlayerData(player)
	local success, data = pcall(function()
		return DataStore:GetAsync(player.UserId.."-Money")
	end)

	if success then
		player.leaderstats.Money.Value = data or 3000
		playerData[player.UserId] = player.leaderstats.Money.Value
		print(player.Name .. " has " .. player.leaderstats.Money.Value .. " money.")
	else
		warn("Error while loading Money data: " .. data)
	end
end



Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = leaderstats

	loadPlayerData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	savePlayerData(player)
end)

game:BindToClose(function()
	task.wait(10)
end)

– Vehicle Data –

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")

local cars = {
	-- list cars put here ok
	"HondeEX5",
	"HondeWave100",
	"Kasaki 150sp",
	"Yamha X1r White"
}

local function CreateCarValue(player, name, value)
	local carValue = Instance.new("BoolValue")
	carValue.Name = name
	carValue.Value = value
	carValue.Parent = player.OwnedCars
	return carValue
end

local function CreateTable(player)
	local playerStats = {}
	for _, stat in pairs(player.OwnedCars:GetChildren()) do
		if stat.Value == true then
			playerStats[stat.Name] = true
		end
	end
	return playerStats
end

Players.PlayerAdded:Connect(function(player)
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "OwnedCars"
	leaderstats.Parent = player
	

	local data = playerData:GetAsync("Player_" .. player.UserId)
	if data then
		for car, value in pairs(data) do
			if value == true and table.find(cars, car) then
				CreateCarValue(player, car, true)
			end
		end
	end
	
end)

Players.PlayerRemoving:Connect(function(player)
	local key = "Player_" .. player.UserId
	local playerStats = CreateTable(player)
	
	local success, err = pcall(function()
		playerData:UpdateAsync(key, function(prev)
			return playerStats
		end)
	end)
	
	if not success then
		warn("DataStore error".. err)
	end
	
end)

im not quite sure , is this ok ?

this part here needs to be set when data is loaded or changed not right before saving

you should then use this value to save the data since it should be already up to date

thats what the playerdata table in this script is used for

Also you need a while loop that goes through and saves/updates the data that has changed on the player ever minute or so incase of server crash that way your not trying to save all the data when server is shutting down and you also won’t timeout the datastores

the loop , i understand but the local playerData = {} , uhhh i dont understand . sorry im not pure english so its kinda hard to understand

Here is your top datastore script with a setup like i was explaining
all you have to do now is just change the money.value with server scripts and it will autosave and update
this has the loop at bottom to autosave and also catches and updates the data with Money.Value changes

you should be able to code your car script to work the same but I would suggest only having one main save script control most of your player data

Also did this quick and haven’t tested but I think I have most everything right
I commented in it so you can tell and learn what its there for

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataSaver001")
local Players = game:GetService("Players")

local playerData = {}  -- holds the players current data on server
local playerDataChanged = {}  -- holds players that need saved
local timeBetweenSaves = 60  -- 1 minute between save you can adjust this how you like


function savePlayerData(player)
	if not playerDataChanged[Player.UserId] then return end  -- no need to save the data it hasnt changed
	local success, error = pcall(function()
		DataStore:SetAsync(player.UserId.."-Money", playerData[player.UserId])  -- this saves the current data saved in the playerdata table
		print(player.Name .. "'s money data saved. Current money: " .. playerData[player.UserId])
	end)
	
	if success then  -- since it was success and their data is up to date in the datastore you wnat to remove them from changed table
		playerDataChanged[player.UserId] = nil 
	end
	
	if not success then
		warn("Error while saving Money data: " .. error)
	end
end

function loadPlayerData(player)
	local success, data = pcall(function()
		return DataStore:GetAsync(player.UserId.."-Money")
	end)

	if success then
		data = data or 3000
		player.leaderstats.Money.Value = data
		playerData[player.UserId] = data -- this is where it is set
		
		-- this will update the playerdata table when the value is changed on the server 
		-- this allows any server scripts to add or remove money and it will instantly update to the playerdata table
		player.leaderstats.Money.Changed:Connect(function()   
			playerData[player.UserId] = player.leaderstats.Money.Value
			playerDataChanged[player.UserId] = player    -- this will set that the players data has been change and needs saved on the next loop
		end)
		
		print(player.Name .. " has " .. data .. " money.")
	else
		warn("Error while loading Money data: " .. data)
	end
end



Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = leaderstats

	loadPlayerData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	savePlayerData(player)
	playerData[player.UserId] = nil   -- this nils out both the data and the changed when player leaves
	playerDataChanged[player.UserId] = nil
end)

game:BindToClose(function()
	task.wait(10)
end)


while task.wait(timeBetweenSaves) do  -- waits 1 minute and saves any players data that has changed
	for userid, player in pairs(playerDataChanged) do  -- this goes through and saves any data that has changed since last loop
		savePlayerData(player)
	end
end

why dont u try using profileservice? its an alternative to datastore2

can it load old data ? never heard of em

Hello, I see your problem, I will try to explain as clearly as I possibly can :slight_smile:.

The error message you’re receiving from Roblox’s datastore is informing you that you’re hitting the datastore limit for the rate at which you can send requests. This limit is in place to ensure that the data store remains available and responsive for all developers.

There are different types of limits placed on data store requests. They include:

  • Per-minute limits: Every game server is allowed to make a certain number of datastore requests per minute.
  • Per-server limits: Each individual server instance is allowed to make a certain number of requests per minute.
  • Queue limit: If your game is making too many requests too fast and the system can’t process them in time, they get added to a queue. If this queue fills up, any additional requests will be dropped, which is what the error message is warning about.

To avoid these limits, you should reduce the number of requests you’re making to the datastore. There are a few strategies you can use:

  1. Batching: Instead of making many small requests, try to group them together into larger requests. For example, in your case, you can save multiple pieces of player data in one request instead of making individual requests for each piece of data.
  2. Rate limiting: Make sure you’re not making too many requests in a short amount of time. If necessary, add delays between your requests to avoid hitting the limit.
  3. Caching: Keep a local copy of data and only write to the datastore when necessary. For example, you can save a player’s data when they leave the game, instead of saving it every time a small change is made.

Looking at your code, it appears that you’re correctly saving player data when they leave the game (PlayerRemoving event), but you should be careful with the frequency of datastore requests in the money.Changed event.

The money.Changed event is triggered every time the player’s money value changes, which can potentially be very often. Instead of directly setting the datastore in this event, consider implementing a caching system where you keep track of changes and save them after a certain time interval or when the player leaves the game.

Here’s an example of how you can implement this:

local moneyCache = {}

money.Changed:Connect(function(value)
    moneyCache[player.UserId] = create_table(player)
end)

game.Players.PlayerRemoving:Connect(function(player)
    local player_stats = moneyCache[player.UserId] or create_table(player)
    local motor_stats = CreateTable(player)
    local MotorStats = newDataStore("VehicleData", player)
    local MoneyStats = newDataStore("MoneyData1", player)
    MotorStats:Set(motor_stats)
    MoneyStats:Set(player_stats)
    player.leaderstats.Money.Value = player_stats.Money
    print("money and motor saved for " .. player.Name)
    moneyCache[player.UserId] = nil
end)

In this modification, money.Changed event just updates the cached data instead of directly saving it to the datastore. When the player leaves the game, the cached data is used to save their stats to the datastore. This should significantly reduce the number of requests your game makes to the datastore and prevent you from hitting the limit.