Should I use :UpdateAsync() or :SetAsync() when player leaves

im not sure what use because one of my players kept rejoining and they lost most of there data because they kept sending requests

UpdateAsync is more expensive than SetAsync as it both reads and writes data. Generally, using SetAsync is sufficient for most situations.

There are many things which may be responsible for this so I tend to just use ProfileService which handles all the edge cases

im not sure how to use profileservice

and also my little data template looks like this:

local data = {
	["regular data"] = {
		levels = 1,
		gold = 0,
	},
	["inventory"] = {
		["wood sword"] = true
	},
	["equipped"] = {
		[1] = "wood sword"
	},
	SpawnPoint = "forest",
	["levelinfo"] = {
		levelprogress = 0,
		levelmax = 100,
		hp = 50,
	}
}

return data

Do you have a :BindToClose hook set up?

game:BindToClose(function()
	--[[
	if game:GetService("RunService"):IsStudio() then
		wait(3)
	end
	]]--
	
	local DataModule = require(game:GetService("ServerScriptService"):WaitForChild("Modules"):WaitForChild("DataModule"))
	
	local mainThread = coroutine.running()
	local threadrunning = 0 
	
	for _,player in ipairs(game.Players:GetPlayers()) do
		local startSavingThread = coroutine.wrap(function()
			DataModule.SaveGame(player)
			threadrunning -= 1
			if threadrunning == 0 then
				coroutine.resume(mainThread)
			end
		end)
		
		threadrunning += 1
		
		startSavingThread(player)
	end
end)

but this was more used for when i shutdown all servers

This just seems unnecessary can be simplified down to:

for _,player in ipairs(game.Players:GetPlayers()) do
	task.spawn(DataModule.SaveGame, player)
end