Would my code be able to prevent Data losses?

So, I was making a Datastore for one of my games, and I ran into a bit of a problem when I remembered the 28th of October. Yes, Data losses. I fear that when Roblox Server goes down, all data is gone, and my game’s economy would be ruined.

I’ve thought of using ProfileService, but after reviewing some DevForum threads, I figure that my best option would be regular Roblox Datastores. I also thought about sending a request to API Services, and if it errors, it indicates that the Server is possibly down. Though, I don’t know if that’s the best way to approach this matter.

If you have any suggestions about how can I prevent that from happening, I’d appreciate it!

Anyway, here’s my code:

local Players = game:GetService("Players")
local DatastoreServices = game:GetService("DataStoreService")

local EconomyData = DatastoreServices:GetDataStore("Economy", "General")

Players.PlayerAdded:Connect(function(plr)
	local key = plr.UserId .. "-Economy"
	
	local Folder = Instance.new("Folder")
	Folder.Name = "leaderstats"
	Folder.Parent = plr
	
	local Cash = Instance.new("IntValue")
	Cash.Name = "Cash"
	Cash.Value = 50000
	Cash.Parent = Folder
	
	local Bank = Instance.new("IntValue")
	Bank.Name = "Bank"
	Bank.Parent = Folder
	
	task.wait()
	
	local Success, Result = pcall(function()
		return EconomyData:GetAsync(key)
	end)
	
	if Success then
		if Result then
			Cash.Value = Result[1]
			Bank.Value = Result[2]
		end
		
	else
		local Retry = 3
		
		print("Unable to load " .. plr.Name .. " Economy Data")
		
		if Result then
			warn("An unknown error occured")
		else
			warn(Result)
		end
		
		repeat
			local success, result = pcall(function()
				return EconomyData:GetAsync(key)
			end)
			
			task.wait(1)
			
			Retry -= 1
			warn(result)
		until success or Retry <= 0
		
		if Retry <= 0 then
			plr:Kick("An error occured while loading your data")
		end
	end
end)

Players.PlayerRemoving:Connect(function(plr)
	local key = plr.UserId .. "-Economy"
	local leaderstats = plr.leaderstats
	
	local Success, Result = pcall(function()
		EconomyData:SetAsync(key, {leaderstats.Cash.Value, leaderstats.Bank.Value})
	end)
	
	if not Success then
		warn(Result)
	end
end)

game:BindToClose(function()
	local Player = Players:GetPlayers()
	for _, plr in ipairs(Player) do
		local key = plr.UserId .. "-Economy"
		local leaderstats = plr.leaderstats
		
		local Success, Result = pcall(function()
			EconomyData:SetAsync(key, {leaderstats.Cash.Value, leaderstats.Bank.Value})
		end)
		
		if not Success then
			warn(Result)
		end
	end
end)

Your code won’t prevent all the data loses.

Main issue: you don’t check if the data is loaded properly while saving:

local dataLoaded = {}

Players.PlayerAdded:Connect(function(plr)
  -- load the data here
  
  dataLoaded[plr] = true
end)

Players.PlayerRemoving:Connect(function(plr)
  if (dataLoaded[plr]) then
    -- save
  else
    warn('Data didn\'t save due to a problem with loading')
  end

  dataLoaded[plr] = nil
end)

If you want to be sure your data is safe, you could be interested in reading this announcement:

1 Like

As the user above stated, I would recommend that you use a Datastore2 as it pretty much saves your data immediately after every single update and it helps with exploiters because it gets the data directly from the datastore instead of uploading the data from a text label to the datastore. I don’t know just an overall improvement and prevents you from wasting your time.