Files
vercel__workflow/.changeset/perf-cached-workflow-script.md
Pranay Prakash 939890d4c2 perf(core): cache compiled workflow-bundle vm.Script across replays (#2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays

The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.

Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).

Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* perf(core): bound script cache with LRU; soften determinism claim; add tests

Addresses review on #2471:

- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
  serves one bundle per process so the bound is never reached; it exists for
  dev/watch mode, where each edit produces a new bundle string that would
  otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
  the latest bundle hot; evicting a `code` entry drops its per-filename scripts
  together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
  stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
  the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
  same-workflow-function + same-`filename`-attribution, noting the one caveat:
  a lookup-expression error's line number shifts to line 1 of the separate
  lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
  (hot bundle survives churn), and a realistic multi-workflow collision test
  (distinct code/filename never returns the wrong Script, results carry their
  own bundle marker).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 06:37:45 +00:00

174 B

@workflow/core
@workflow/core
patch

Cache the compiled workflow-bundle vm.Script per process so replays reuse the compiled bundle instead of re-parsing it on every iteration.