Renderify

Performance Tuning Guide

This guide focuses on concrete runtime knobs and operational practices to reduce latency and prevent regressions.

1. Establish a Baseline

Run the benchmark suite first:

pnpm bench

For CI artifact output:

pnpm bench:ci
# writes .artifacts/benchmarks/runtime-bench.json

Useful environment variables for benchmark sensitivity:

RENDERIFY_BENCH_TIME_MS=400
RENDERIFY_BENCH_WARMUP_MS=200

2. Measure the Real Pipeline

If you use @renderify/core, provide your own DefaultPerformanceOptimizer and read metrics from it:

import {
  createRenderifyApp,
  DefaultPerformanceOptimizer,
} from "@renderify/core";

const perf = new DefaultPerformanceOptimizer();
const app = createRenderifyApp({
  // ...other dependencies
  performance: perf,
});

app.on("rendered", (payload) => {
  console.log("render duration(ms):", payload?.metric?.durationMs);
});

console.table(perf.getMetrics());

If you use renderer-only integration, inspect these outputs on every render:

  • security.issues
  • execution.diagnostics
  • preflight result (runtime.probePlan(plan))

3. Tune the Highest-Impact Knobs

KnobDefaultImpactTradeoff
enableDependencyPreflighttrueBetter safety and earlier failure signalsAdds startup latency
failOnDependencyPreflightErrorfalseFast fail for strict CI/prod lanesLower tolerance for flaky CDNs
remoteFetchTimeoutMs12000Prevents long hangsToo low can create false timeouts
remoteFetchRetries2Better resilienceMore retries increase tail latency
remoteModuleMaxBytes8388608Bounds memory per remote moduleToo low rejects large bundles
remoteFallbackCdnBases['https://esm.sh']Better availabilityMust align with security host policy
browserSourceSandboxModebrowser:worker, server:noneContainment for reviewed sourceWorker/iframe adds overhead
browserSourceSandboxTimeoutMs4000Bounds worst-case source executionToo low may cut valid workloads
runtimeSourceJsxHelperModeautoPredictable transpilation behavioralways can add minor output overhead
autoPinLatestModuleManifesttrueGreat DX for bare importsLatest-based resolution can drift

4. Scenario Presets

Low-Latency Interactive Preview

Use in chat preview paths where responsiveness matters more than strict fail-fast.

const runtime = new DefaultRuntimeManager({
  enableDependencyPreflight: false,
  remoteFetchTimeoutMs: 6000,
  remoteFetchRetries: 1,
  browserSourceSandboxMode: "worker",
  browserSourceSandboxTimeoutMs: 2500,
});

Deterministic Production Rendering

Use when reproducibility and policy guarantees are required.

const runtime = new DefaultRuntimeManager({
  enforceModuleManifest: true,
  enableDependencyPreflight: true,
  failOnDependencyPreflightError: true,
  allowIsolationFallback: false,
  browserSourceSandboxMode: "worker",
  browserSourceSandboxFailClosed: true,
  remoteFallbackCdnBases: [],
});

High-Volume Concurrency

  • Reuse initialized runtime instances instead of creating a new runtime per request.
  • Keep serializeTargetRenders enabled for same-target UI safety.
  • Bound render cancellations with AbortController to shed load quickly.

5. Memory and Lifecycle Hygiene

The runtime keeps in-memory module URL caches for browser source execution. For long-lived pages:

  • Reuse a runtime instance for steady traffic.
  • Periodically recycle runtime instances in very long sessions.
  • Always call runtime.terminate() on shutdown/unmount to clear caches and revoke blob URLs.

Example:

await runtime.initialize();

try {
  await runtime.execute({ plan });
} finally {
  await runtime.terminate();
}

6. Protect Against Regressions

Use these checks in CI:

  1. pnpm typecheck
  2. pnpm unit
  3. pnpm compat
  4. pnpm bench:ci and compare key metrics (meanMs, rme, samples)

Suggested policy:

  • Block merge if meanMs regresses more than an agreed threshold (for example 10%).
  • Track trend over multiple runs instead of a single datapoint to reduce noise.

7. Quick Debug Checklist for Slow Renders

  1. Run probe-plan to isolate dependency failures from execution logic.
  2. Inspect execution.diagnostics for timeout and import budget messages.
  3. Check module count and transitive dependency size in plan.source imports.
  4. Reduce fallback retries if tail latency dominates.
  5. Switch sandbox mode only after confirming it is the dominant overhead.
Edit this page on GitHub

On this page