How would I make this datastore better to prevent data loss

So I’m making a datastore and I’m trying to make it good but I’m a starter scripter and I don’t know too much about those fancy models. what do you think I can do to prevent data loss?

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


Players.PlayerAdded:Connect(function(Player)
	if Player then
		local Folder = Instance.new("Folder")
		Folder.Name = "leaderstats"
		Folder.Parent = Player
		
		local Bank =  Instance.new("IntValue")
		Bank.Name = "Bank"
		Bank.Parent = Folder
		Bank.Value = 100
		
		local Cash =  Instance.new("IntValue")
		Cash.Name = "Cash"
		Cash.Parent = Folder
		Cash.Value = 50
		
		local Data = DataStore:GetAsync(Player.UserId)
		if Data then
			Bank.Value = Data.Bank
			Cash.Value = Data.Cash
		end
		
		while wait(300) do
			game.ReplicatedStorage.Remotes.Message.MessageEdit:FireAllClients("notification","DATA SAVED SUCCESSFULLY",Color3.new(0.0352941, 0.580392, 0))
			DataStore:SetAsync(Player.UserId, {
				["Bank"] = Bank.Value;
				["Cash"] = Cash.Value;
			})
		end
	end
end)

Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync(Player.UserId, {
		["Bank"] = Player.leaderstats.Bank.Value;
		["Cash"] = Player.leaderstats.Cash.Value;
	})
end)
1 Like
  1. Use BindToClose.
  2. Wrap your datastore requests in pcalls, they are network calls, so they can fail.
  3. Make the datastore retry if it fails a couple of times before giving up.
  4. UpdateAsync > SetAsync
  5. Don’t save data if all the datastore get requests fail.
1 Like

Another cool thing to add, only save player data if the data is deemed loaded.
Here’s some pseudo code to demonstrate that.

local ACTIVE_PLAYERS = {}

local function OnDataLoaded()
    --\\ AFTER the data is deemed loaded

    ACTIVE_PLAYERS[player] = true
end

Players.PlayerRemoving:Connect(function(player)
    if not ACTIVE_PLAYERS[player] then
        return
    end

    --\\ only THEN save data

    --\\ AFTER the data is deemed saved,
    ACTIVE_PLAYERS[player] = nil
end)

game:BindToClose(function()
    local players = Players:GetPlayers()
    for _, player in ipairs(players) do
        task.spawn(function()
             if not ACTIVE_PLAYERS[player] then
                 return
             end

            --\\ Save data

            ACTIVE_PLAYERS[player] = nil
        end
    end

    while next(ACTIVE_PLAYERS) ~= nil do --\\ next returns the first thing in a table, if there's nothing it returns nil.
        RunService.Heartbeat:Wait()
    end
end)

Also, @DogGuyTheThird it’s good that you have a good syntax, even if your code is not the best, it helps a lot.

2 Likes

How would i do most of those things?