What a change may do to the speed, weight and stability of the dispatch shells and remotes, and what happens when it goes over.
What this page is for
Every change to a shell or a remote is checked against a performance standard before it merges: some checks run on its own pull request, and the merge queue judges a stack of pull requests as a whole. This page says what the standard protects, how it is measured and what to do when a change goes over it. The generic pages in this section teach techniques; this one describes the checks those techniques have to pass.The limits are not written here. They live in metrics.json at the repository root, and the table below is generated from that file, so it shows what the checks enforce.
What a change may not do
A blocking check fails its job on the pull request when a change:
makes a built shell or remote larger than its growth limit allows;
makes a shell download more to mount a remote module than the growth limit allows;
leaves more DOM nodes or event listeners behind after a module unmounts or a route is left, or raises more uncaught errors during those flows;
stops a shell from staying usable when one of its remotes fails to load;
removes the runtime plugins or the telemetry wiring a shell must have.
A speed measure can fail a pull request only once metrics.json marks it as blocking, and it then appears in the table below. Data from real sessions never can. Whether a failing check also stops the merge is set in branch protection; the metrics guide explains the enforcement field.
Budgets that block
Metric
Kind
Applies to
Limit
Basis
Bundle size, brotli
growth
shell, remote
5%
carried-over
Remote bytes loaded inside a shell
growth
remote
3% and +3072 bytes
measured
DOM nodes left after unmount
increase
remote, shell
0 count
deterministic
Event listeners left after unmount
increase
remote, shell
0 count
deterministic
Uncaught errors during lab flows
increase
remote, shell
0 count
deterministic
These blocking checks pass or fail, so they have no budget:
Shell survives a remote failing
Default runtime plugins kept
Deployable reports telemetry
Each row is one budget. A growth budget limits how far a value may rise above the commit the change is based on; a limit that also shows bytes is breached only when both are exceeded. An increase budget limits the rise in an exact count. The "Applies to" column says which tiers are gated; a tier with no row is reported but not gated. The metrics guide defines the kinds and the bases. The Basis column says where each limit came from; where budget numbers come from explains each basis, and what a carried-over limit was copied from.
Where it is measured
Remote alone: the remote on its own in the switchboard harness.
Shell alone: a shell with no remotes loaded.
Remote in shell: a remote's module as a shell loads it.
A change to a shared package can move a shell's numbers without touching any remote, so read which level a result is reported at before deciding where the cause is.
When a change goes over
A budget breach is reported on the pull request with its value at the base and at the head. A pass/fail check fails its job and names the shell or remote. The memory lab comment also gives a command that reproduces each failure.
Fix the cause. Each metric's entry in the metrics reference lists the levers that move it.
If the cost is deliberate, a person accepts it as a reviewed change to metrics.json or to an exception file. The review pipeline requires the owning team's approval for those files. A limit is never raised to make a change pass, and limits are read from trunk rather than from the change, so a change cannot loosen the gate it is judged by.
Where to go next
The performance overview in the repository covers the commands and the measurement levels. The metrics guide defines every field. The pages that follow in this section cover the code patterns that keep a change inside its budgets.