Skip to Content

Performance

@neststack/config is optimized for read-heavy workloads. Configuration is read thousands of times during an application’s lifetime but written only once at startup.

O(1) Lookups

When a config namespace is registered, the store builds a flat lookup map:

// Input (nested) { database: { host: "localhost", port: 5432 }, app: { name: "myapp" } } // Flat lookup map (Map<string, unknown>) "database" → { host: "localhost", port: 5432 } "database.host""localhost" "database.port"5432 "app" → { name: "myapp" } "app.name""myapp"

Every config.get('database.host') is a single Map.get() call — no string splitting, no object traversal, no recursion.

Why a Flat Map?

ApproachTime per readAllocation per read
Flat Map.get()O(1)None
String split + traverseO(n) where n = depthArray from .split('.')
Recursive searchO(n)Stack frames

The flat map trades a few microseconds of startup time (to build the map) for zero-cost reads at runtime.

Memory Efficiency

The flat map adds memory overhead proportional to the number of unique paths. For a typical config with 20-50 keys, this is negligible (a few KB). The benefit — instant access without parsing — vastly outweighs the cost.

Deep Freeze Performance

Object.freeze() is called once per namespace at registration time. It’s a native V8 operation that:

  • Adds zero overhead to subsequent property reads
  • Makes objects slightly more optimizable by V8 (frozen objects have a stable shape)
  • Throws TypeError on mutation attempts (caught by strict mode)

Rebuild Strategy

The lookup map is rebuilt whenever a new namespace is registered (via forRoot() or forFeature()). Since registration only happens at startup, this has no impact on runtime performance.

Startup: forRoot() → register 3 namespaces → rebuild map (once) forFeature() → register 1 namespace → rebuild map (once) Runtime: config.get('database.host') → Map.get() → O(1) config.get('app.port') → Map.get() → O(1)

Benchmarks

For a configuration with 5 namespaces and 30 total keys:

OperationTime
Full registration + validation + freeze~2ms
Single get() call~0.001ms (1μs)
getAll()~0.01ms
getSafeAll() (with masking)~0.05ms

These are approximate values. Actual performance depends on hardware and config size.

Last updated on