How to delay SetAsync calls to avoid sending too many requests?

I made a data store script recently that uses a “Caching” system, both for current data and data that failed to save when a player leaves(If it does happen).

--> Services
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--> Remotes
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DataEvent = Remotes:WaitForChild("Data")
local DataFunc = Remotes:WaitForChild("Data_F")
local DataBind = Remotes:WaitForChild("Data_B")
local DataBindFunc = Remotes:WaitForChild("Data_B_F")

--> Data Stores
local DataStore = DataStoreService:GetDataStore("PlayerData", "UserData")

--> Data Template
local Template = {
	Time = 0,
	Gears = {},
	Gradients = {},
	Equipped = {
		Gradient = "",
		Title = "",
	},
	Titles = {},
	Kills = 0,
	ProductsBought = {},
}

--> Profiles
local Profiles = {}
local Cache = {}

--> Functions
local function GetData(player: Player)
	return Profiles[player]
end

local function LoadData(player: Player)
	local UserId = tostring(player.UserId)

	local Data = nil

	pcall(function()
		Data = DataStore:GetAsync(UserId)
	end)

	if Data == nil then
		Data = Template
	end

	return Data
end

local function SaveData(player: Player, Data: {})
	local UserId = tostring(player.UserId)

	local succ, err = pcall(function()
		DataStore:SetAsync(UserId, Data)
	end)

	if succ == false then
		Cache[UserId] = Data
	end
end

local function PlayerAdded(player: Player)
	local Data = LoadData(player)

	Profiles[player] = Data

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local Time = Instance.new("NumberValue")
	Time.Name = "Time"

	Time.Value = Data.Time

	Time.Parent = leaderstats
	leaderstats.Parent = player

	task.spawn(function()
		while task.wait(60) do
			Profiles[player].Time += 1
			Time.Value = Profiles[player].Time
		end
	end)
end

local function PlayerRemoving(player: Player)
	local Data = Profiles[player]

	SaveData(player, Data)

	Profiles[player] = nil
end

local function onEvent(player: Player, Key: string, ...)

end

local function onBind(key: string, ...)

end

local function onBindFunc(key: string, ...)
	if key:lower() == "get" then
		return GetData(...)
	end

	return nil
end

local function onFunc(player: Player, Key: string, ...)
	if Key:lower() == "get" then
		return GetData(player)
	end

	return nil
end

--> Race Conditions (If a player loads in before this script runs.)
for _, v in pairs(Players:GetPlayers()) do
	PlayerAdded(v)
end

--> Connections
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

--> Remotes
DataEvent.OnServerEvent:Connect(onEvent)
DataFunc.OnServerInvoke = onFunc
DataBind.Event:Connect(onBind)
DataBindFunc.OnInvoke = onBindFunc

--> Game Shutdown
game:BindToClose(function()
	for _, v in pairs(Players:GetPlayers()) do
		PlayerRemoving(v)
	end
	
	--> Also save the data of players that failed to save.
	for UserId, Data in pairs(Cache) do
		DataStore:SetAsync(UserId, Data)

		Cache[UserId] = nil
	end
end)

You would use remotes to retrieve the players data from other scripts, and from the client.

An example of getting a players data with all the listed remotes in the variables:

DataFunc: (Client)

--> Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--> remotes
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DataFunc = Remotes:WaitForChild("Data_F")

--> Added Wait
task.wait(1)

--> Get Player Data
local PlayerData = DataFunc:InvokeServer("get")

--> Print Player Data
print(PlayerData)

DataBindFunc: (Server)

--> Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--> Remotes
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DataBindFunc = Remotes:WaitForChild("Data_B_F")

--> Functions

Players.PlayerAdded:Connect(function(player: Player)
	--> wait so that data can load
	task.wait(3)
	
	--> Get Player Data
	local PlayerData = DataBindFunc:Invoke("get", player)
	
	--> Print Data
	print(PlayerData)
end)

But like someone previously mentioned, ProfileService is a much better data store that uses a cache.
Profile Service: