From 9b54edd2db401ddfa6aa08ff9a66c3387a2dbd7b Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Tue, 11 Aug 2026 10:22:31 +0200 Subject: [PATCH] docs(perf): correct the "16 MiB tRPC subtree" lever - it was already removed This branch has repeatedly named a 16.10 MiB subtree of 460 files, reached by every API route, as the one remaining server-side lever with real headroom, attributing it to the tRPC router importing every integration eagerly. Both halves are wrong. The integration creator was already fully lazy: every kind in creator.ts is `() => import(...)`, so no integration class loads until one is constructed. The earlier barrel diet had done this properly - the claim was never checked against the code. The subtree was an artefact of route preloading, measured before preloadEntriesOnStart: false shipped, when Next loaded all 74 routes' module graphs at startup. Re-measured on the current build, boot is 706 files and 10.56 MiB: 3.73 MiB 28 files .next/server/chunks (the app's own boot graph) 2.16 MiB 14 files better-sqlite3 (2.1 MiB of it the native binary) 1.75 MiB 359 files next/dist 1.58 MiB 25 files next/dist/compiled 0.45 MiB 77 files mysql2 <- known, structurally blocked 0.07 MiB 13 files pg <- same There is no single large server lever left. What remains is diffuse: a full multi-tab session loads 15.44 MiB of app chunks across 241 files, and both the ~41 MiB of retained source and the ~38 MiB of compiler zones scale with that. Reducing it means shipping less application JavaScript per route, which is a broad refactor with no single target. --- docs/perf/SERVER-MEMORY.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/perf/SERVER-MEMORY.md b/docs/perf/SERVER-MEMORY.md index d2a5c6974..08b771d84 100644 --- a/docs/perf/SERVER-MEMORY.md +++ b/docs/perf/SERVER-MEMORY.md @@ -709,3 +709,33 @@ probe under `--max-opt=2`: memory; only not compiling at all does, and that breaks the page. So this 38 MiB is not reachable through V8 configuration — it is proportional to how much JavaScript V8 has to compile, which puts it back under the one remaining server-side lever: ship less server code. Reverted. + +## Correction: the "16 MiB tRPC subtree" lever was already removed + +Earlier rounds identified a **16.10 MiB subtree of 460 files reached by every API route** and named it +the one remaining lever with real headroom, attributing it to the tRPC router importing every +integration eagerly. Both halves of that are now known to be wrong. + +**The integration creator was already fully lazy.** Every kind in +`packages/integrations/src/base/creator.ts` is `() => import(...)`, so no integration class is loaded +until one is constructed. The earlier "integrations barrel diet" had already done this properly; the +claim that the router imports them eagerly was never checked against the code. + +**The subtree itself was an artefact of route preloading.** That measurement was taken before +`preloadEntriesOnStart: false` shipped, when Next loaded the module graph of all 74 routes at startup. +Re-measured on the current build, boot is **706 files and 10.56 MiB of source**, and it breaks down as: + +| owner | size | files | can it be reduced? | +| --- | --- | --- | --- | +| `.next/server/chunks` (app code) | 3.73 MiB | 28 | this is the app's own boot graph, already lean at 28 chunks | +| better-sqlite3 | 2.16 MiB | 14 | no — 2.1 MiB of it is the native `.node` binary, and it is the default driver | +| next/dist (framework) | 1.75 MiB | 359 | no — framework, and flat regardless of load | +| next/dist/compiled (vendored) | 1.58 MiB | 25 | no | +| **mysql2 + pg** | **0.52 MiB** | 90 | yes in principle, but structurally blocked — see REJECTED.md | +| everything else | < 0.5 MiB | — | noise | + +So there is no single large server-side lever left. What remains is diffuse: under a full multi-tab +session the app loads **15.44 MiB of its own chunks** across 241 files, and that is what the ~41 MiB of +retained source and the ~38 MiB of compiler zones both scale with. Reducing it means shipping less +application JavaScript per route — a broad refactor with no single target, not a 16 MiB subtree waiting +to be cut.