3bc88c453e
## Summary Under high request load the webapp spends most of its CPU inside react-router's `matchRoutes`, not in application code. `@remix-run/router@1.23.2` (the React Router v6 / Remix 2 core) re-flattens, re-ranks, and recompiles the entire route table on every request, and with the webapp's ~436 routes that cost dominates once request rates climb. There is no `NODE_ENV` gate, so production pays it too. This adds a pnpm patch that memoizes the parts that depend only on the static route manifest: it caches the flattened/ranked branches per route tree, hoists the loop-invariant `decodePath` out of the match loop, and caches compiled path regexes. ## Benchmark CPU profile over the same load (100 concurrent tag feeds, ~425 req/s), `NODE_ENV=production`, before vs after the patch: | Metric | Before | After | | --- | --- | --- | | Active CPU (self-time over the window) | 28.3s | 18.5s (-34%) | | Route-matching self-time | 19.2s | 7.5s (-61%) | | Event-loop lag p99 | 322ms | 113ms (-65%) | | Idle headroom | 26% | 52% | Application/realtime code was ~0% of CPU in both profiles; the bottleneck was entirely generic per-request route matching. ## Why a patch instead of an upgrade The inefficiency is acknowledged upstream ([remix-run/react-router#8653](https://github.com/remix-run/react-router/issues/8653)). A contributor PR doing exactly this ([remix-run/react-router#14866](https://github.com/remix-run/react-router/pull/14866)) was closed in favor of a narrower fix ([remix-run/react-router#14967](https://github.com/remix-run/react-router/pull/14967), branch caching only, shipped in React Router v7), with the maintainer suggesting patch-package as the interim until the Remix 3 route-pattern rewrite (see [remix-run/remix#4786](https://github.com/remix-run/remix/discussions/4786)). We are on the v6-era core and cannot pick up even the partial fix without a framework migration, so this patch is the sanctioned stopgap, and it also includes the compiled-regex cache the merged PR left out. [`patches/README.md`](https://github.com/triggerdotdev/trigger.dev/blob/perf/react-router-route-matching/patches/README.md) documents the full rationale, the safety argument (deterministic, internal-only, bounded caches), and when to remove the patch.
147 lines
5.9 KiB
JSON
147 lines
5.9 KiB
JSON
{
|
|
"name": "triggerdotdev",
|
|
"private": true,
|
|
"workspaces": [
|
|
"apps/*",
|
|
"packages/*",
|
|
"integrations/*"
|
|
],
|
|
"version": "0.0.1",
|
|
"scripts": {
|
|
"build": "turbo run build",
|
|
"build:force": "turbo run build --force",
|
|
"build:db:seed": "turbo run build:db:seed",
|
|
"db:migrate": "turbo run db:migrate:deploy generate",
|
|
"db:seed": "turbo run db:seed",
|
|
"db:studio": "turbo run db:studio",
|
|
"db:populate": "turbo run db:populate",
|
|
"dev": "turbo run dev",
|
|
"i:dev": "infisical run -- turbo run dev",
|
|
"generate": "turbo run generate",
|
|
"lint": "turbo run lint",
|
|
"docker": "node scripts/docker.mjs -f docker/docker-compose.yml up -d --build --remove-orphans",
|
|
"docker:stop": "node scripts/docker.mjs -f docker/docker-compose.yml stop",
|
|
"docker:full": "node scripts/docker.mjs -f docker/docker-compose.yml -f docker/docker-compose.extras.yml up -d --build --remove-orphans",
|
|
"docker:full:stop": "node scripts/docker.mjs -f docker/docker-compose.yml -f docker/docker-compose.extras.yml stop",
|
|
"dev:docker": "docker compose -p triggerdotdev-dev-docker -f docker/dev-compose.yml up -d --build --remove-orphans",
|
|
"dev:docker:build": "docker compose -p triggerdotdev-dev-docker -f docker/dev-compose.yml up -d --build",
|
|
"dev:docker:stop": "docker compose -p triggerdotdev-dev-docker -f docker/dev-compose.yml stop",
|
|
"test": "turbo run test --concurrency=1 -- --run",
|
|
"test:webapp": "turbo run test --filter webapp -- --run",
|
|
"test:packages": "turbo run test --concurrency=1 --filter \"@trigger.dev/*\" -- --run",
|
|
"test:internal": "turbo run test --concurrency=1 --filter \"@internal/*\" -- --run",
|
|
"test:dev": "turbo run test:dev",
|
|
"start": "turbo run start",
|
|
"check-exports": "turbo run check-exports",
|
|
"clean": "turbo run clean",
|
|
"clean:node_modules": "find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +",
|
|
"typecheck": "turbo run typecheck",
|
|
"test:e2e": "playwright test",
|
|
"test:e2e:ui": "playwright test --ui",
|
|
"test:e2e:dev": "turbo run test:e2e:dev",
|
|
"test:e2e:ci": "turbo run test:e2e:ci",
|
|
"setup": "turbo run generate db:migrate:force db:seed",
|
|
"env:pull": "turbo run env:pull",
|
|
"changeset:add": "changeset",
|
|
"changeset:version": "changeset version && pnpm install --lockfile-only && node scripts/bump-helm-chart.mjs && node scripts/cleanup-server-changes.mjs",
|
|
"changeset:release": "pnpm run build --filter \"@trigger.dev/*\" --filter \"trigger.dev\" && changeset publish",
|
|
"changeset:v4": "changeset pre enter v4",
|
|
"changeset:normal": "changeset pre exit",
|
|
"clean:sourcemaps": "turbo run clean:sourcemaps",
|
|
"storybook": "turbo run storybook"
|
|
},
|
|
"devDependencies": {
|
|
"@manypkg/cli": "^0.19.2",
|
|
"@playwright/test": "^1.36.2",
|
|
"@trigger.dev/database": "workspace:*",
|
|
"@types/node": "20.14.14",
|
|
"@vitest/coverage-v8": "4.1.7",
|
|
"autoprefixer": "^10.4.12",
|
|
"eslint-plugin-turbo": "^2.0.4",
|
|
"lefthook": "^1.11.3",
|
|
"pkg-pr-new": "0.0.75",
|
|
"pkg-types": "1.1.3",
|
|
"prettier": "^3.0.0",
|
|
"tsx": "^3.7.1",
|
|
"turbo": "^1.10.3",
|
|
"typescript": "5.5.4",
|
|
"vite-tsconfig-paths": "^4.0.5",
|
|
"vitest": "4.1.7"
|
|
},
|
|
"packageManager": "pnpm@10.33.2",
|
|
"dependencies": {
|
|
"@changesets/cli": "2.26.2",
|
|
"@remix-run/changelog-github": "^0.0.5",
|
|
"agentcrumbs": "^0.5.0",
|
|
"node-fetch": "2.6.x"
|
|
},
|
|
"pnpm": {
|
|
"patchedDependencies": {
|
|
"@changesets/assemble-release-plan@5.2.4": "patches/@changesets__assemble-release-plan@5.2.4.patch",
|
|
"engine.io-parser@5.2.2": "patches/engine.io-parser@5.2.2.patch",
|
|
"graphile-worker@0.16.6": "patches/graphile-worker@0.16.6.patch",
|
|
"redlock@5.0.0-beta.2": "patches/redlock@5.0.0-beta.2.patch",
|
|
"@kubernetes/client-node@1.0.0": "patches/@kubernetes__client-node@1.0.0.patch",
|
|
"@sentry/remix@9.46.0": "patches/@sentry__remix@9.46.0.patch",
|
|
"@upstash/ratelimit@1.1.3": "patches/@upstash__ratelimit.patch",
|
|
"antlr4ts@0.5.0-alpha.4": "patches/antlr4ts@0.5.0-alpha.4.patch",
|
|
"@window-splitter/state@1.1.3": "patches/@window-splitter__state@1.1.3.patch",
|
|
"streamdown@2.5.0": "patches/streamdown@2.5.0.patch",
|
|
"@remix-run/router@1.23.2": "patches/@remix-run__router@1.23.2.patch"
|
|
},
|
|
"overrides": {
|
|
"typescript": "5.5.4",
|
|
"@types/node": "20.14.14",
|
|
"express@^4>body-parser": "1.20.3",
|
|
"@remix-run/dev@2.17.4>tar-fs": "2.1.4",
|
|
"tar@>=7 <7.5.11": "^7.5.11",
|
|
"form-data@^2": "2.5.4",
|
|
"form-data@^3": "3.0.4",
|
|
"form-data@^4": "4.0.4",
|
|
"js-yaml@>=3.0.0 <3.14.2": "3.14.2",
|
|
"js-yaml@>=4.0.0 <4.1.1": "4.1.1",
|
|
"jws@<3.2.3": "3.2.3",
|
|
"qs@>=6.0.0 <6.15.2": "^6.15.2",
|
|
"systeminformation@>=5.0.0 <5.31.0": "^5.31.0",
|
|
"lodash@>=4.17 <4.18.0": "^4.18.0",
|
|
"lodash-es@>=4.17 <4.18.0": "^4.18.0",
|
|
"dompurify@>=3 <3.4.0": "^3.4.1",
|
|
"vite@>=5.0.0 <6.4.2": "^6.4.2",
|
|
"rollup@>=4 <4.59.0": "^4.59.0",
|
|
"flatted@>=3 <3.4.2": "^3.4.2",
|
|
"picomatch@>=2 <2.3.2": "^2.3.2",
|
|
"picomatch@>=4 <4.0.4": "^4.0.4",
|
|
"minimatch@>=3 <3.1.3": "^3.1.3",
|
|
"protobufjs@>=7 <7.5.6": "^7.5.6",
|
|
"fast-xml-parser@>=4 <4.5.5": "^4.5.5",
|
|
"fast-xml-parser@>=5 <5.7.0": "^5.7.0",
|
|
"path-to-regexp@>=0.1 <0.1.13": "^0.1.13",
|
|
"ajv@>=8 <8.18.0": "^8.18.0",
|
|
"socket.io-parser@>=4 <4.2.6": "^4.2.6",
|
|
"postcss@>=8 <8.5.10": "^8.5.10",
|
|
"yaml@>=2 <2.8.3": "^2.8.3",
|
|
"semver@>=5 <5.7.2": "^5.7.2",
|
|
"defu@>=6 <6.1.5": "^6.1.5",
|
|
"fast-uri@<3.1.2": "^3.1.2",
|
|
"fast-xml-builder@<1.1.7": "^1.1.7"
|
|
},
|
|
"onlyBuiltDependencies": [
|
|
"@depot/cli",
|
|
"@fingerprintjs/fingerprintjs-pro-react",
|
|
"@prisma/client",
|
|
"@prisma/engines",
|
|
"@sentry/cli",
|
|
"@swc/core",
|
|
"better-sqlite3",
|
|
"cpu-features",
|
|
"esbuild",
|
|
"lefthook",
|
|
"prisma",
|
|
"protobufjs",
|
|
"sharp",
|
|
"ssh2",
|
|
"turbo"
|
|
]
|
|
}
|
|
}
|