Messiest script ever

First, don’t use the .Parent argument of Instance.new() as it is slower than setting it through the .Parent property. [Source]

Second, you could get rid of all those if statements in the data loading function by doing

local savedLevel = leaderstatsDataStore:GetAsync(Player.UserId.."-Level") or 1

Level.Value = savedLevel

as if the data was nil it would instead choose 1 as the default level. And you can repeat this for the other stats.

Anyway it would be better to save all the data inside a table instead of having tons of keys for each player and making tons of API requests for each player.

Third, why are you using different pcalls for saving operations? If one is going to fail due to API issues it’s very likely that all the others will as well.

Do this instead:

game.Players.PlayerRemoving:Connect(function(plr)
	local sucess, err = pcall(function()
		leaderstatsDataStore:SetAsync(plr.UserId.."-Level", plr.leaderstats.Level.Value)
        data:SetAsync(plr.UserId.."-RequiredEXP", plr.RequiredEXP.Value)
        leaderboardDataStore:SetAsync(plr.UserId.."-Exp", plr.leaderboard.Exp.Value)
		leaderboardDataStore:SetAsync(plr.UserId.."-Exp", plr.leaderboard.Exp.Value)
	end)
end)

Although you should check if there’s already data saved and if yes then use UpdateAsync() to prevent possible data loss. You were declaring success and result for every pcall but were never using them so it’s useless and can be removed, those variables are not mandatory and you should not just do things by memory.

game.Players.PlayerRemoving:Connect(function(plr)
	pcall(function()
		leaderstatsDataStore:SetAsync(plr.UserId.."-Level", plr.leaderstats.Level.Value)
        data:SetAsync(plr.UserId.."-RequiredEXP", plr.RequiredEXP.Value)
        leaderboardDataStore:SetAsync(plr.UserId.."-Exp", plr.leaderboard.Exp.Value)
		leaderboardDataStore:SetAsync(plr.UserId.."-Exp", plr.leaderboard.Exp.Value)
	end)
end)

Finally this topic should be in #help-and-feedback:code-review