Skip to content

perf(kb): lazy-load KB schemas per namespace/endpoint to cut startup heap #251

@MattDevy

Description

@MattDevy

Problem

elastic stack kb has the same eager-load problem that elastic stack es had before #171, at roughly 7x the scale.

src/kb/apis.ts statically imports all 40+ namespace files, which are then spread into allKbApis (2,083 endpoint definitions). On every elastic stack kb ... invocation (including --help), cli.ts calls registerKbCommands() with no arguments, which defaults to allKbApis and calls buildCommandSchema() for all 2,083 entries. That means 2,083 z.object constructions, plus transitive z.string / z.boolean / z.array / z.record calls, happen before the user's command even runs.

The ES fix (#171, commit d496a74) measured a 373 MB eager heap floor and 599 MB RSS for elastic stack es --help before the fix. KB has 7x the endpoint count, so the overhead will be proportionally higher.

Key differences from the ES path

The ES fix split per-namespace files into per-endpoint files (each containing one large generated Zod schema), built a manifest of lightweight metadata, and used registerEsCommandsLazy() to sniff process.argv and dynamic-import only the one endpoint's schema file.

KB is structured differently: the namespace files (src/kb/apis/*.ts) are plain KbApiDefinition[] arrays with no Zod imports. Zod schemas are built dynamically in register.ts via buildCommandSchema(). So the per-endpoint file split is not required — the namespace files are already the right granularity. What's needed is:

  1. A KB manifest — a flat array of lightweight entries (name, namespace, method, path, no param details) that lets the CLI build the command tree structure without loading any namespace file or constructing any Zod schema.
  2. A registerKbCommandsLazy() counterpart — sniffs process.argv to identify the invoked namespace + endpoint, dynamic-imports only that namespace file, builds only that one endpoint's buildCommandSchema(), and registers everything else as stubs (lazy on access).
  3. Stubs for the remaining 2,082 endpoints — same pattern as ES: register a named stub command for each manifest entry, which dynamic-imports its namespace file and calls buildCommandSchema() only if the user actually invokes it.

Acceptance criteria

  • elastic stack kb --help RSS is comparable to the ES --help RSS after perf: loading 292 ES API Zod schemas allocates 373 MB of heap #171 (roughly 100 MB range vs current).
  • elastic stack kb <namespace> <endpoint> --help RSS is bounded by loading one namespace file + one Zod object construction.
  • registerKbCommands(definitions) (explicit definitions, used in tests) continues to work synchronously as-is.
  • No regression to existing KB integration tests.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions