Help with Tower Defense Enemies

I recently redid my enemy system. But their are one or two issues.

1s: Sometimes, the enemies freeze and stop Working
2nd: The enemies are really clunky, And I have no idea how to implement lerping.

Also, the memory usage is still really high, and still not as optimized as I had hoped for. Is their any way that I can still improve this?

EnemyClass

--!native
--!strict
local class = {}
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BezierPath = require(ReplicatedStorage.Packages:WaitForChild("BezierPath"))
local enemystats = require(ServerStorage:WaitForChild("EnemyStats"))
local bosshealthbar = ReplicatedStorage.AddHealthBar
local AbilityManager = require(ServerStorage.AbilityManager)
local Enemies = ReplicatedStorage.Enemies
local HashCreator = require(ServerStorage.HashCreator)
local refresh_rate = 0.1
class.__index = class

export type enemy = {
	speed: number,
	health: number,
	hash: string,
	position: CFrame,
	updateConnection: RBXScriptConnection,
}

function class.create(enemyName, path: BezierPath.Path)
	ReplicatedStorage.DebugValues.EnemyCount.Value += 1
	local self = setmetatable({}, class)
	self.path = path
	self.position = nil
	self.class = enemyName
	self.StartTime = os.clock()
	local enemyData = enemystats.get(enemyName)
	self.speed = enemyData.speed
	self.health = enemyData.health
	self.hash = HashCreator.retriveHash()
	local _, boundingBox = Enemies[enemyName]:GetBoundingBox()
	local sizeAddition = boundingBox.Y / 2
	local rotationalOffset
	local offset = math.random(-1, 1)
	if enemyData.modifiers["boss"] then
		bosshealthbar:FireAllClients(enemyData.name, self, self.health)
	end
	if enemyData.rotationOffset ~= nil then
		rotationalOffset = enemyData.rotationOffset
	else
		rotationalOffset = Vector3.zero
	end
	if enemyData["abilities"] then
		task.spawn(function()
			for ability, _ in pairs(enemyData["abilities"]) do
				AbilityManager.register("enemies", ability, self)
			end
		end)
	end
	self.updateConnection = task.spawn(function()
		local PreviousTime = os.clock()
		self.translated = 0
		task.desynchronize()
		while self.translated < 1 do
			self.translated += (os.clock() - PreviousTime) * self.speed / path["path"]:GetPathLength()
			PreviousTime = os.clock()
			local transformedcframe: CFrame = path["path"]:CalculateUniformCFrame(self.translated)
				* CFrame.new(offset, sizeAddition, 0)
				* CFrame.Angles(rotationalOffset.X, rotationalOffset.Y, rotationalOffset.Z)
			task.synchronize()
			self.position = transformedcframe
			task.wait(refresh_rate)
		end
		task.synchronize()
		ReplicatedStorage.DebugValues.EnemyCount.Value -= 1
		if self.health > 0 then
			ReplicatedStorage.BaseHealth.Value -= self.health
			self.health = 0
		end
	end)
	return self
end

function class:damage(damage)
	local clampedDamage = math.clamp(self.health - damage, 0, 9999999999)
	self.health -= clampedDamage
	if self.health <= 0 then
		class.health = 0
	end
end


return class

EnemyReplicator:

--!native
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local replicator = {}
replicator.enemies = {}
replicator.pathTable = {}
local BezierPath = require(ReplicatedStorage.Packages:WaitForChild("BezierPath"))
local BridgeNet = require(ReplicatedStorage.Packages:WaitForChild("bridgenet2"))
local enemyclass = require(ServerStorage:WaitForChild("EnemyClass"))
local packetBridge = BridgeNet.ServerBridge("enemyReplication")
local createBridge = BridgeNet.ServerBridge("enemyCreation")
local janitor = require(ReplicatedStorage.Packages:WaitForChild("janitor")).new()
local hashCreator = require(ServerStorage.HashCreator)

replicator.createnavpath = function(nodefolder: Folder, index)
	local nodePositions = { nodefolder.enemyspawn.Position }

	for i = 1, #nodefolder:GetChildren() - 2 do
		table.insert(nodePositions, nodefolder[i].Position)
	end

	table.insert(nodePositions, nodefolder.exit.Position)
	local pathtable = {
		["path"] = BezierPath.new(nodePositions, 3),
		["nodefolder"] = nodefolder,
	}
	replicator.pathTable[index] = pathtable
end

replicator.getEnemyData = function()
	task.desynchronize()
	local enemyData = {}
	for hash, enemy: enemyclass.enemy in pairs(replicator.enemies) do
		enemyData[hash] = { enemy.position, (enemy.health <= 0) }
		if enemy.health <= 0 or enemy.translated == 1 then
			hashCreator.putBack(hash)
			replicator.enemies[hash] = nil
		end
	end
	task.synchronize()
	return enemyData
end

replicator.getSingleEnemy = function(enemyHash)
	local enemy = replicator.enemies[enemyHash]
	return enemy
end

replicator.update = function()
	packetBridge:Fire(BridgeNet.AllPlayers(), replicator.getEnemyData())
end

replicator.addEnemy = function(enemyName, pathNum)
	local eClass = enemyclass.create(enemyName, replicator.pathTable[pathNum])
	createBridge:Fire(BridgeNet.AllPlayers(), { eClass["hash"], eClass["class"] })
	local hash = eClass["hash"]
	replicator.enemies[hash] = eClass
end

return replicator

Client:

local Map = ReplicatedStorage:WaitForChild("Map")
local Enemies = ReplicatedStorage:WaitForChild("Enemies")
local loadedEnemies = {}
local MapObject = Workspace:WaitForChild(Map.Value)

function createEnemy(content)
	local hash, name = content[1], content[2]
	local enemyModel: Model = Enemies:FindFirstChild(name):Clone()
	enemyModel.Name = hash
	enemyModel.Parent = MapObject.enemies
	loadedEnemies[hash] = enemyModel.PrimaryPart
end

function updatePosition(content)
	local cframes = {}
	local parts = {}
	local index = 1
	for hash, data in pairs(content) do
		if data[2] == true then
			loadedEnemies[hash]:Destroy()
			loadedEnemies[hash] = nil
			continue
		end
		parts[index] = loadedEnemies[hash]
		cframes[index] = data[1]
		index += 1
	end
	Workspace:BulkMoveTo(parts, cframes, Enum.BulkMoveMode.FireCFrameChanged)
end

enemyCreationBridge:Connect(createEnemy)
enemyPacketBridge:Connect(updatePosition)

Server Code:

local function spawnenemies(name, amount, nodes, spawninterval)
	for _ = 1, amount, 1 do
		local enemyWrap = coroutine.wrap(enemyReplicator.addEnemy)
		enemyWrap(name, tonumber(nodes.Name))
		task.wait(spawninterval)
	end
end

Also, here is the error when the enemies freeze:


The enemies do not freeze at an specific point

You cant just throw entire pieces of code and expect us to optimize for you.

Client-sided rendering is extremely helpful for eliminating visual lag.

This is client rendering. Im just asking for tips for optimizing this