Other ways for secure and reliable projectiles?

Right now I am using CFrames and raycasting for my projectiles but I am afraid that as I add more projectile based attacks to the game it’s going to start being not the best way to go about this:

-- Creating knives
local distance = 150
local lifetime = knife_generation_info["distance"] / knife_generation_info["speed"]
local knives_end_pos = root.CFrame * CFrame.new(0, 0, -distance)
local knives_start_pos = CFrame.new(root.CFrame.Position, knives_end_pos.Position)

-- Knife movement and hitbox
local start_t = tick()
local finished = false
local last_position = {}
for index, knife in ipairs(knives:GetChildren()) do
	last_position[knife] = knife.Position
end

while wait() do
	-- Moving the knife
	local current_time = tick() - start_t
	local percent_finished = math.min(current_time / lifetime, 1)
	if percent_finished >= 1 or #knives:GetChildren() <= 1 then
		break
	end

	-- Setting knife new position
	knives:SetPrimaryPartCFrame(knives_start_pos:Lerp(knives_end_pos, percent_finished))

        -- ... (Checking hithox using raycast between current position and last_position for each knife

Hopefully this example demonstrates how I deal with my projectiles well. What I’m looking for are different solutions to this issue, but it is important to me that the projectiles must be owned by the server, this is how I deal with all my hitboxes/everything that deals damage

I couldn’t come up with a different solution, I thought about jsut using the Roblox physics but I don’t know how taxing they are on the server (if it’s even worth it) and if they won’t be more laggy than my current solution.