npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hexium-softworks/instancepool

v0.1.0

Published

Game-agnostic Nevermore instance pool for Roblox objects with leases, lifecycle tracking, registries, and diagnostics.

Readme

InstancePool

A game-agnostic Nevermore package for reusing Roblox Instance objects safely.

InstancePool owns creation, reuse, lifecycle tracking, statistics, and optional registry lookup. Your game owns object-specific initialization and reset behavior through callbacks.

Installation

pnpm add @hexium-softworks/instancepool

Standalone Usage

Use the core class directly when a system owns its own pool.

local require = require(script.Parent.loader).load(script)

local InstancePool = require("InstancePool")
local PoolOverflowPolicy = require("PoolOverflowPolicy")

local projectilePool = InstancePool.new({
	Name = "Projectiles",
	Template = projectileTemplate,

	InitialCapacity = 32,
	MaxCapacity = 128,
	ExpandBy = 16,
	Container = pooledInstancesFolder,
	OverflowPolicy = PoolOverflowPolicy.Grow,

	OnAcquire = function(projectile, context)
		projectile.CFrame = context.CFrame
		projectile.Parent = context.Parent
	end,

	OnRelease = function(projectile)
		projectile.AssemblyLinearVelocity = Vector3.zero
		projectile.AssemblyAngularVelocity = Vector3.zero
	end,
})

local lease = projectilePool:Acquire({
	CFrame = spawnCFrame,
	Parent = workspace.Projectiles,
})

local projectile = lease:GetInstance()

lease:Release()

Creation

A pool must define exactly one creation mechanism.

Template cloning:

local pool = InstancePool.new({
	Template = workspace.ProjectileTemplate,
})

Custom factory:

local pool = InstancePool.new({
	Factory = function()
		local part = Instance.new("Part")
		part.Anchored = true
		part.CanCollide = false
		return part
	end,
})

Factories must return a fresh Instance each time.

Leases

Acquire() returns an InstancePoolLease.

local lease = pool:Acquire()
local instance = lease:GetInstance()

lease:GetMaid():GiveTask(instance.Touched:Connect(function(hit)
	print(hit)
end))

lease:Release()

Release cleans the lease Maid before the pool runs OnRelease. Double release, stale release, and wrong-pool release fail safely and return false.

lease:Destroy() aliases lease:Release() for Maid compatibility.

Raw Convenience API

Systems that prefer raw instances can use:

local instance = pool:Take()
pool:Return(instance)

This is checked against the same ownership records, but leases are the preferred API because they carry generation and per-use cleanup explicitly.

Overflow Policies

PoolOverflowPolicy.Grow expands by ExpandBy when empty until MaxCapacity.

PoolOverflowPolicy.Reject returns nil, "PoolExhausted" from TryAcquire().

PoolOverflowPolicy.Temporary creates overflow instances that are destroyed on release and never enter the reusable queue.

local lease, reason = pool:TryAcquire()
if not lease then
	warn(reason)
end

Prewarming

pool:Prewarm(50)

For batched prewarming:

pool:PromisePrewarm(100, {
	BatchSize = 10,
	YieldBetweenBatches = true,
})

PromisePrewarm uses Nevermore Promise; the rest of the package does not require Promise at module load time.

Reset Behavior

The core pool does not attempt to reset arbitrary Roblox properties. There is no universally safe reset for things like CFrame, Transparency, attributes, tags, physics velocity, playback state, child instances, or event connections.

Use OnRelease for game-specific reset:

OnRelease = function(part)
	part.CFrame = CFrame.identity
	part.AssemblyLinearVelocity = Vector3.zero
	part.AssemblyAngularVelocity = Vector3.zero
	part:SetAttribute("Owner", nil)
end

Lifecycle

Available instances are parented to Container or nil. Checked-out instances are controlled by OnAcquire and consumer code.

Methods:

pool:Trim(targetAvailable)
pool:Clear()
pool:Destroy()

Trim() destroys available instances only.

Clear() destroys all available instances and prevents already checked-out instances from re-entering the pool when released.

Destroy() rejects future acquisition, destroys available instances, disconnects observers, and marks checked-out instances for destruction when released.

The pool listens to Instance.Destroying. If an available or checked-out instance is destroyed externally, the pool removes it from tracking and invalidates any active lease.

Stats

local stats = pool:GetStats()
local connection = pool:ObserveStats(function(nextStats)
	print(nextStats.InUse)
end)

Stats include available, in-use, reusable, temporary, created, acquired, released, reused, destroyed, peak usage, expansion count, and acquire failures.

Registry Services

Registries are optional. Use them when multiple systems intentionally share a pool or when centralized diagnostics are useful.

Server:

local InstancePoolService = require("InstancePoolService")

function MyService:Init(serviceBag)
	self._poolService = serviceBag:GetService(InstancePoolService)
end

function MyService:Start()
	self._poolService:CreatePool("VFX.Explosions", {
		Factory = function()
			return Instance.new("Part")
		end,
		InitialCapacity = 16,
	})
end

Client:

local InstancePoolServiceClient = require("InstancePoolServiceClient")

Server and client registries are independent. They do not replicate pooled instances or pool state.

Registry methods:

service:CreatePool(name, config)
service:GetPool(name)
service:FindPool(name)
service:DestroyPool(name)
service:ObservePool(name, callback)

Duplicate names are rejected.

API Reference

Core:

| Method | Description | | --- | --- | | InstancePool.new(config) | Creates a standalone pool. | | Acquire(context?) | Acquires a lease or errors if unavailable. | | TryAcquire(context?) | Acquires a lease or returns nil, reason. | | Release(instanceOrLease) | Releases a checked-out instance or lease. | | Take(context?) | Raw instance convenience acquire. | | Return(instance) | Raw instance convenience release. | | Prewarm(count) | Creates reusable available instances. | | PromisePrewarm(count, options?) | Batched async prewarming. | | Trim(targetAvailable) | Destroys available instances above the target. | | Clear() | Destroys available instances and invalidates pool generation. | | Destroy() | Destroys the pool. | | GetStats() | Returns a read-only stats snapshot. | | ObserveStats(callback) | Observes stats changes. |

Config:

| Field | Description | | --- | --- | | Name | Human-readable pool name. | | Template | Instance to clone. Mutually exclusive with Factory. | | Factory | Function returning a fresh Instance. | | InitialCapacity | Number of instances to prewarm at construction. | | MaxCapacity | Maximum reusable capacity. Defaults to unbounded. | | ExpandBy | Grow batch size. Defaults to 1. | | Container | Parent for available instances, or nil. | | OverflowPolicy | Grow, Reject, or Temporary. | | OnAcquire | Synchronous callback run after checkout. | | OnRelease | Synchronous callback run before reusable return. | | LeakWarningSeconds | Optional retained-lease warning threshold. | | CaptureAcquireTracebacks | Optional traceback capture for leak diagnostics. |