How would I save my players data when they leave

Hey everyone, So my data request keep getting to the max then I cant save data anymore how would I make it save the players data when the leave the game or the servers shut down

local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("LeaderStatSave")
local killsDataStore = DataStore:GetDataStore("KillsDataStore")
local gloveDataStore = DataStore:GetDataStore("GloveDataStore")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Set up the RemoteEvent for purchases
local purchaseEvent = ReplicatedStorage:FindFirstChild("PurchaseEvent")
if not purchaseEvent then
	purchaseEvent = Instance.new("RemoteEvent")
	purchaseEvent.Name = "PurchaseEvent"
	purchaseEvent.Parent = ReplicatedStorage
end


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

	local Pushes = Instance.new("NumberValue", leaderstats)
	Pushes.Name = "Pushes"
	Pushes.Value = ds:GetAsync(player.UserId .. "-Pushes") or 0


	local Glove = Instance.new("StringValue", leaderstats)
	Glove.Name = "Arm"
	Glove.Value = gloveDataStore:GetAsync(player.UserId .. "-Glove") or script.StarterGlove.Value

	local function saveStats()
		ds:SetAsync(player.UserId .. "-Pushes", Pushes.Value)
		gloveDataStore:SetAsync(player.UserId .. "-Glove", Glove.Value)
	end

	Pushes.Changed:Connect(saveStats)
	Glove.Changed:Connect(saveStats)
end)


-- Save data when player is leaving the game
game.Players.PlayerRemoving:Connect(function(player)
	local leaderstats = player:FindFirstChild("leaderstats")
	if leaderstats then
		ds:SetAsync(player.UserId .. "-Pushes", leaderstats.Pushes.Value)
		gloveDataStore:SetAsync(player.UserId .. "-Glove", leaderstats.Arm.Value)
	end
end)

-- Handle purchase requests
purchaseEvent.OnServerEvent:Connect(function(player, itemName, price)
	local leaderstats = player:FindFirstChild("leaderstats")
	if not leaderstats then return end

	local coins = leaderstats:FindFirstChild("Pushes")
	local arm = leaderstats:FindFirstChild("Arm")
	if coins and arm and coins.Value >= price then
		coins.Value = coins.Value - price
		arm.Value = itemName
		gloveDataStore:SetAsync(player.UserId .. "-Glove", arm.Value)
		ds:SetAsync(player.UserId .. "-Pushes", coins.Value)
	else
		warn("Purchase failed for " .. player.Name .. ": not enough Pushes or missing leaderstats.")
	end
end)

You can just use profileservice to make your life easier. There are several tutorials on youtube for it.

Instead of saving the data every time the value changes, you should only do it every 30 seconds or so. This data saving is for cases when a server crashes, or something unexpected happens (datastore errors, etc, you also don’t have error handling for your datastore calls which is not great. If you save your data in a while loop, you NEED pcalls, or a single error will stop the auto save entirely. Well, you need pcalls either way)

Usually though, the data will be saved when the player leaves. You’ve got that setup right, but one thing is missing. You need to use game:BindToClose(), which can be used to prevent the server from shutting down before it is able to save your player’s data
Currently, what is probably happening is that you leave, it runs the code for setting the data, but the server shuts down right after, and the data is never saved

You’ve got other issues, such as missing pcalls, and using SetAsync. It is recommended to use UpdateAsync() to update the data instead of overwriting it (ie. player earned 5$ so take the old data returned by UpdateAsync and increase the value by 5), or implement a session locking system, which is what ProfileService mentioned by @jin123123412345 is using
This is to prevent data loss from the data being loaded in a new server faster than the old server was able to save it

I personally don’t use Datastore modules, as I like doing things myself, knowing how my systems work, and my datastores are pretty non-standard. Depending on your personal preferences and the needs of your game, ProfileService might or might not be a good fit for you