Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Push backport branches via GraphQL createCommitOnBranch (signed commits) by TooTallNate · Pull Request #1937 · vercel/workflow · GitHub
Skip to content

Push backport branches via GraphQL createCommitOnBranch (signed commits) - #1937

Merged
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql
May 5, 2026
Merged

Push backport branches via GraphQL createCommitOnBranch (signed commits)#1937
TooTallNate merged 1 commit into
mainfrom
backport-signed-commits-via-graphql

Conversation

@TooTallNate

Copy link
Copy Markdown
Member

Summary

Backport of PR #1902 (label-triggered) failed with:

remote: error: GH013: Repository rule violations found for refs/heads/backport/pr-1902-to-stable.
remote: - Commits must have verified signatures.

The repo has an enterprise-level branch ruleset matching ~ALL that requires verified signatures on every ref, so a normal git push of a locally cherry-picked commit is rejected because CI doesn't have a signing key.

This replaces the git push step with a GraphQL createCommitOnBranch mutation, which signs commits automatically with GitHub's internal key (the same way commits made via the web UI or by changesets/action with commitMode: github-api are signed).

Implementation

After the local cherry-pick (with optional AI conflict resolution) succeeds, a new Push backport branch via GitHub API step:

  1. Walks git diff --name-status -z between the parent (stable HEAD) and the cherry-pick HEAD.
  2. For each addition/modification, reads the blob raw bytes via git cat-file blob and base64-encodes them into a FileAddition. For each deletion, emits a FileDeletion. Renames are handled as add(new) + delete(old).
  3. Ensures the backport/<...> branch exists on the remote and points at the stable HEAD (the mutation requires the branch to already exist with the expected expectedHeadOid).
  4. Runs the createCommitOnBranch mutation. GitHub creates a verified-signed commit and updates the branch ref atomically.

The subsequent Create backport PR step is unchanged.

Caveats

  • Authorship is lost.createCommitOnBranch always attributes commits to the token owner (github-actions[bot]), so we lose original-author attribution in the git log. The original commit SHA is still referenced in the PR body.
  • Non-regular files (executable bit, symlinks, submodules) are not supported by the GraphQL mutation. The step warns and proceeds with mode 100644 for affected paths. This matches the documented limitations of @changesets/ghcommit, which the release.yml workflow uses for its own commitMode: github-api. Backports involving these file types will need manual signed pushes (the failure-comment instructions now mention git cherry-pick -S for that).

Manual fallback

The Comment on conflict failure step's manual instructions are also updated to mention that local cherry-picks must be signed (git cherry-pick -S) because of the same ruleset, and to push to a backport/<...> branch and open a PR rather than pushing directly to stable.

The repo has an enterprise-level branch ruleset requiring verified
signatures on every ref (`~ALL`), so a normal `git push` of a locally
cherry-picked commit is rejected ("Commits must have verified
signatures"). Replace the `git push` step with a GraphQL
`createCommitOnBranch` mutation, which signs commits automatically
with GitHub's internal key (the same way commits made via the web UI
are signed).
Walks the cherry-pick's diff against the parent (`stable` HEAD),
collects file additions (with binary-safe base64 contents read via
`git cat-file blob`) and deletions, ensures the backport branch
exists on the remote, then runs the mutation. Also updates the manual
conflict-resolution instructions in the failure comment to mention
that local cherry-picks must be signed (`git cherry-pick -S`)
because of the same ruleset.
Caveats:
- Authorship is lost — `createCommitOnBranch` always attributes
commits to the token owner (`github-actions[bot]`). The original
commit SHA is still referenced in the PR body.
- Non-regular files (executable bit, symlinks, submodules) are not
supported by the mutation; the step warns and proceeds with mode
100644 for affected paths.
CopilotAI review requested due to automatic review settings May 5, 2026 08:10
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bf2f2a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercelBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production92502191144
✅ 💻 Local Development123702191456
✅ 📦 Local Production123702191456
✅ 🐘 Local Postgres123702191456
✅ 🪟 Windows10400104
✅ 📋 Other5520176728
Total5292010526344

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro78026
✅ example78026
✅ express78026
✅ fastify78026
✅ hono78026
✅ nextjs-turbopack10202
✅ nextjs-webpack10202
✅ nitro78026
✅ nuxt78026
✅ sveltekit9707
✅ vite78026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable79025
✅ express-stable79025
✅ fastify-stable79025
✅ hono-stable79025
✅ nextjs-turbopack-canary85019
✅ nextjs-turbopack-stable-lazy-discovery-disabled10400
✅ nextjs-turbopack-stable-lazy-discovery-enabled10400
✅ nextjs-webpack-canary85019
✅ nextjs-webpack-stable-lazy-discovery-disabled10400
✅ nextjs-webpack-stable-lazy-discovery-enabled10400
✅ nitro-stable79025
✅ nuxt-stable79025
✅ sveltekit-stable9806
✅ vite-stable79025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack10400
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable79025
✅ e2e-local-dev-tanstack-start-79025
✅ e2e-local-postgres-nest-stable79025
✅ e2e-local-postgres-tanstack-start-79025
✅ e2e-local-prod-nest-stable79025
✅ e2e-local-prod-tanstack-start-79025
✅ e2e-vercel-prod-tanstack-start78026

📋 View full workflow run

@github-actions

github-actionsBot commented May 5, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.032s (-26.9% 🟢)1.006s (~)0.974s101.00x
💻 LocalExpress0.033s (-24.6% 🟢)1.006s (~)0.973s101.06x
🐘 PostgresExpress0.049s (-16.4% 🟢)1.013s (~)0.964s101.54x
🐘 PostgresNitro0.054s (-43.5% 🟢)1.013s (-2.9%)0.959s101.71x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.226s (-3.9%)2.309s (+8.1% 🔺)2.083s101.00x
▲ VercelNitro0.228s (-44.3% 🟢)2.010s (-19.9% 🟢)1.782s101.01x
▲ VercelNext.js (Turbopack)0.822s (+226.9% 🔺)2.891s (+23.9% 🔺)2.069s103.63x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.067s (-5.2% 🟢)2.007s (~)0.940s101.00x
💻 LocalNitro1.073s (-5.1% 🟢)2.007s (~)0.934s101.01x
🐘 PostgresExpress1.081s (-5.7% 🟢)2.009s (~)0.928s101.01x
🐘 PostgresNitro1.084s (-4.9%)2.008s (~)0.924s101.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express1.530s (-18.4% 🟢)4.053s (+6.4% 🔺)2.523s101.00x
▲ VercelNitro1.604s (-58.8% 🟢)3.816s (-35.4% 🟢)2.212s101.05x
▲ VercelNext.js (Turbopack)2.444s (+20.1% 🔺)5.515s (+44.0% 🔺)3.071s101.60x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.390s (-4.9%)11.022s (~)0.632s31.00x
🐘 PostgresNitro10.416s (-4.2%)11.019s (~)0.603s31.00x
🐘 PostgresExpress10.426s (-4.9%)11.018s (~)0.592s31.00x
💻 LocalNitro10.432s (-4.7%)11.022s (~)0.590s31.00x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro13.328s (-43.8% 🟢)15.244s (-39.3% 🟢)1.916s21.00x
▲ VercelNext.js (Turbopack)13.499s (-22.1% 🟢)15.421s (-20.5% 🟢)1.921s21.01x
▲ VercelExpress13.634s (-19.7% 🟢)15.581s (-22.2% 🟢)1.947s21.02x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.405s (-10.5% 🟢)14.026s (-6.7% 🟢)0.622s51.00x
🐘 PostgresExpress13.477s (-7.6% 🟢)14.019s (-6.7% 🟢)0.542s51.01x
🐘 PostgresNitro13.487s (-7.6% 🟢)14.019s (-6.7% 🟢)0.532s51.01x
💻 LocalNitro13.501s (-10.4% 🟢)14.027s (-12.5% 🟢)0.526s51.01x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.186s (-67.1% 🟢)23.236s (-65.1% 🟢)2.049s31.00x
▲ VercelExpress21.669s (-56.9% 🟢)23.908s (-54.5% 🟢)2.239s31.02x
▲ VercelNext.js (Turbopack)22.502s (-57.2% 🟢)25.855s (-52.7% 🟢)3.353s31.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express11.805s (-28.9% 🟢)12.023s (-29.4% 🟢)0.218s81.00x
🐘 PostgresNitro11.950s (-14.4% 🟢)12.265s (-14.3% 🟢)0.315s81.01x
💻 LocalNitro11.961s (-28.7% 🟢)12.272s (-27.9% 🟢)0.312s81.01x
🐘 PostgresExpress11.999s (-14.3% 🟢)12.395s (-15.1% 🟢)0.396s81.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro29.482s (-93.0% 🟢)32.053s (-92.4% 🟢)2.571s31.00x
▲ VercelExpress31.774s (-73.8% 🟢)33.949s (-72.5% 🟢)2.175s31.08x
▲ VercelNext.js (Turbopack)32.588s (-91.7% 🟢)34.963s (-91.2% 🟢)2.375s31.11x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.149s (-9.9% 🟢)2.008s (~)0.860s151.00x
🐘 PostgresExpress1.149s (-8.9% 🟢)2.007s (~)0.858s151.00x
💻 LocalExpress1.182s (-20.6% 🟢)2.006s (~)0.824s151.03x
💻 LocalNitro1.187s (-27.2% 🟢)2.006s (-3.3%)0.819s151.03x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.393s (-16.3% 🟢)4.076s (-11.8% 🟢)1.683s81.00x
▲ VercelNitro3.586s (+27.2% 🔺)6.167s (+42.7% 🔺)2.582s51.50x
▲ VercelNext.js (Turbopack)4.111s (+21.0% 🔺)6.005s (+21.7% 🔺)1.893s51.72x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.219s (-48.4% 🟢)2.007s (-33.3% 🟢)0.787s151.00x
🐘 PostgresNitro1.226s (-47.8% 🟢)2.007s (-33.3% 🟢)0.781s151.01x
💻 LocalExpress1.696s (-42.6% 🟢)2.005s (-41.9% 🟢)0.309s151.39x
💻 LocalNitro1.813s (-42.3% 🟢)2.150s (-44.7% 🟢)0.337s141.49x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.409s (-5.8% 🟢)5.002s (-2.1%)1.593s61.00x
▲ VercelNitro3.694s (-8.8% 🟢)5.496s (-7.2% 🟢)1.802s61.08x
▲ VercelNext.js (Turbopack)5.534s (-22.1% 🟢)8.109s (-8.9% 🟢)2.575s41.62x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.380s (-60.4% 🟢)2.010s (-49.9% 🟢)0.629s151.00x
🐘 PostgresNitro1.402s (-59.7% 🟢)2.008s (-49.9% 🟢)0.606s151.02x
💻 LocalExpress4.670s (-44.0% 🟢)5.347s (-40.8% 🟢)0.678s63.38x
💻 LocalNitro5.542s (-33.6% 🟢)6.014s (-33.3% 🟢)0.472s54.02x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.291s (+50.1% 🔺)6.876s (+24.2% 🔺)1.585s51.00x
▲ VercelExpress6.062s (+43.0% 🔺)7.819s (+27.6% 🔺)1.757s41.15x
▲ VercelNext.js (Turbopack)7.963s (-10.7% 🟢)10.220s (-6.8% 🟢)2.257s31.51x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.160s (-7.7% 🟢)2.009s (~)0.849s151.00x
🐘 PostgresNitro1.166s (-7.2% 🟢)2.008s (~)0.842s151.01x
💻 LocalExpress1.373s (-27.5% 🟢)2.006s (-15.1% 🟢)0.633s151.18x
💻 LocalNitro1.416s (-24.1% 🟢)2.006s (-14.3% 🟢)0.590s151.22x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.761s (+12.3% 🔺)4.858s (+16.5% 🔺)2.097s71.00x
▲ VercelExpress3.000s (+16.2% 🔺)4.648s (+6.9% 🔺)1.648s71.09x
▲ VercelNext.js (Turbopack)4.394s (+49.9% 🔺)6.773s (+45.9% 🔺)2.379s51.59x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.236s (-47.2% 🟢)2.009s (-33.3% 🟢)0.773s151.00x
🐘 PostgresNitro1.246s (-46.7% 🟢)2.007s (-33.3% 🟢)0.762s151.01x
💻 LocalExpress1.895s (-39.5% 🟢)2.315s (-38.5% 🟢)0.420s131.53x
💻 LocalNitro2.077s (-32.2% 🟢)2.591s (-33.3% 🟢)0.515s121.68x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.692s (+14.2% 🔺)5.687s (+12.0% 🔺)1.994s61.00x
▲ VercelExpress3.848s (+20.5% 🔺)5.646s (+17.8% 🔺)1.798s61.04x
▲ VercelNext.js (Turbopack)4.815s (+53.2% 🔺)7.048s (+55.9% 🔺)2.233s51.30x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.381s (-60.5% 🟢)2.008s (-49.9% 🟢)0.627s151.00x
🐘 PostgresNitro1.391s (-60.0% 🟢)2.008s (-49.9% 🟢)0.617s151.01x
💻 LocalExpress5.537s (-37.1% 🟢)6.017s (-35.1% 🟢)0.480s54.01x
💻 LocalNitro5.929s (-35.2% 🟢)6.413s (-36.0% 🟢)0.484s54.29x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.012s (-21.9% 🟢)6.881s (-15.9% 🟢)1.869s51.00x
▲ VercelNitro5.472s (+7.4% 🔺)7.689s (+12.8% 🔺)2.218s41.09x
▲ VercelNext.js (Turbopack)5.785s (-14.4% 🟢)7.606s (-11.0% 🟢)1.822s41.15x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.007s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.456s (-44.4% 🟢)1.006s (~)0.550s601.09x
💻 LocalExpress0.475s (-51.7% 🟢)1.004s (-6.7% 🟢)0.529s601.14x
💻 LocalNitro0.561s (-42.8% 🟢)1.095s (~)0.535s551.34x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.832s (-74.6% 🟢)6.959s (-67.4% 🟢)2.127s91.00x
▲ VercelNitro4.927s (-77.7% 🟢)6.794s (-71.7% 🟢)1.867s91.02x
▲ VercelNext.js (Turbopack)7.374s (-49.2% 🟢)9.277s (-42.3% 🟢)1.902s71.53x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.072s (-44.4% 🟢)1.705s (-18.8% 🟢)0.633s531.00x
🐘 PostgresExpress1.109s (-43.9% 🟢)1.923s (-14.8% 🟢)0.813s471.04x
💻 LocalExpress1.163s (-61.4% 🟢)2.005s (-44.1% 🟢)0.843s451.09x
💻 LocalNitro1.192s (-60.7% 🟢)2.006s (-46.6% 🟢)0.814s451.11x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.140s (-61.9% 🟢)15.341s (-58.3% 🟢)2.200s61.00x
▲ VercelNitro13.355s (-66.2% 🟢)16.002s (-61.3% 🟢)2.647s61.02x
▲ VercelNext.js (Turbopack)16.463s (-66.9% 🟢)18.716s (-63.8% 🟢)2.253s51.25x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.143s (-46.3% 🟢)2.781s (-36.3% 🟢)0.638s441.00x
🐘 PostgresNitro2.158s (-47.4% 🟢)2.781s (-39.6% 🟢)0.623s441.01x
💻 LocalExpress2.649s (-71.2% 🟢)3.008s (-70.0% 🟢)0.358s401.24x
💻 LocalNitro2.729s (-70.6% 🟢)3.008s (-70.0% 🟢)0.278s401.27x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express41.153s (-68.4% 🟢)43.595s (-67.0% 🟢)2.442s31.00x
▲ VercelNitro43.379s (-55.2% 🟢)45.800s (-53.5% 🟢)2.421s31.05x
▲ VercelNext.js (Turbopack)49.075s (-54.2% 🟢)51.250s (-52.9% 🟢)2.175s31.19x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.192s (-31.9% 🟢)1.006s (~)0.814s601.00x
🐘 PostgresNitro0.203s (-28.5% 🟢)1.006s (~)0.803s601.05x
💻 LocalExpress0.439s (-21.6% 🟢)1.004s (~)0.565s602.28x
💻 LocalNitro0.452s (-25.2% 🟢)1.005s (-1.7%)0.552s602.35x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.128s (+28.1% 🔺)4.004s (+19.5% 🔺)1.876s151.00x
▲ VercelExpress2.485s (+27.2% 🔺)4.316s (+18.7% 🔺)1.830s141.17x
▲ VercelNext.js (Turbopack)4.322s (+113.7% 🔺)6.196s (+63.3% 🔺)1.873s102.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.318s (-35.9% 🟢)1.006s (~)0.688s901.00x
🐘 PostgresExpress0.322s (-36.8% 🟢)1.007s (~)0.684s901.01x
💻 LocalNitro2.170s (-14.5% 🟢)2.976s (-1.1%)0.806s316.82x
💻 LocalExpress2.288s (-9.0% 🟢)2.945s (-2.1%)0.657s317.19x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.901s (+95.2% 🔺)8.807s (+69.6% 🔺)1.906s111.00x
▲ VercelExpress7.484s (+145.6% 🔺)9.450s (+96.6% 🔺)1.966s101.08x
▲ VercelNitro8.029s (+148.9% 🔺)10.079s (+109.0% 🔺)2.050s91.16x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.648s (-20.8% 🟢)1.006s (-1.1%)0.358s1201.00x
🐘 PostgresNitro0.662s (-16.2% 🟢)1.006s (~)0.344s1201.02x
💻 LocalExpress10.154s (-9.3% 🟢)10.779s (-9.7% 🟢)0.625s1215.67x
💻 LocalNitro10.261s (-8.3% 🟢)10.861s (-6.9% 🟢)0.600s1215.83x
💻 LocalNext.js (Turbopack)⚠️missing----
🐘 PostgresNext.js (Turbopack)⚠️missing----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro21.143s (+173.8% 🔺)23.663s (+151.7% 🔺)2.520s61.00x
▲ VercelNext.js (Turbopack)21.735s (+110.5% 🔺)24.215s (+97.1% 🔺)2.480s51.03x
▲ VercelExpress23.578s (+217.7% 🔺)25.565s (+176.5% 🔺)1.987s61.12x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.133s (+452.3% 🔺)1.998s (+100.1% 🔺)0.001s (-18.8% 🟢)2.010s (+98.7% 🔺)0.877s101.00x
🐘 PostgresNitro1.139s (+455.7% 🔺)1.996s (+99.7% 🔺)0.002s (+6.7% 🔺)2.010s (+98.8% 🔺)0.871s101.01x
💻 LocalNitro1.141s (+434.0% 🔺)2.005s (+99.6% 🔺)0.013s (+0.8%)2.020s (+98.3% 🔺)0.879s101.01x
💻 LocalExpress1.142s (+473.7% 🔺)2.005s (+99.6% 🔺)0.010s (-15.7% 🟢)2.017s (+98.1% 🔺)0.875s101.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.084s (-16.8% 🟢)3.621s (-11.5% 🟢)1.392s (+44.9% 🔺)5.488s (-1.8%)3.404s101.00x
▲ VercelNitro2.351s (-38.7% 🟢)3.757s (-28.8% 🟢)1.714s (+130.9% 🔺)6.059s (-6.5% 🟢)3.708s101.13x
▲ VercelNext.js (Turbopack)4.987s (-27.2% 🟢)5.551s (-35.8% 🟢)0.780s (+23.4% 🔺)8.218s (-16.0% 🟢)3.230s102.39x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.516s (+142.9% 🔺)1.999s (+98.6% 🔺)0.004s (-8.9% 🟢)2.023s (+97.9% 🔺)0.508s301.00x
💻 LocalExpress1.528s (+101.9% 🔺)2.011s (+95.5% 🔺)0.010s (+8.0% 🔺)2.023s (+94.6% 🔺)0.495s301.01x
🐘 PostgresExpress1.530s (+142.9% 🔺)2.001s (+98.8% 🔺)0.004s (-3.4%)2.025s (+98.0% 🔺)0.495s301.01x
💻 LocalNitro1.532s (+82.7% 🔺)2.012s (+98.8% 🔺)0.010s (+7.4% 🔺)2.024s (+81.4% 🔺)0.491s301.01x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.651s (-13.1% 🟢)7.576s (-5.4% 🟢)0.276s (-32.5% 🟢)8.321s (-5.8% 🟢)2.670s81.00x
▲ VercelNitro5.768s (-80.4% 🟢)7.321s (-76.2% 🟢)0.226s (+101.7% 🔺)8.075s (-74.6% 🟢)2.306s81.02x
▲ VercelNext.js (Turbopack)13.542s (-20.0% 🟢)14.863s (-18.5% 🟢)0.258s (+22.0% 🔺)16.071s (-15.1% 🟢)2.529s42.40x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.655s (-31.8% 🟢)1.014s (-20.6% 🟢)0.000s (-20.7% 🟢)1.039s (-20.5% 🟢)0.384s581.00x
🐘 PostgresNitro0.686s (-29.2% 🟢)1.050s (-15.9% 🟢)0.000s (+26.3% 🔺)1.061s (-15.7% 🟢)0.375s571.05x
💻 LocalNitro1.358s (+11.0% 🔺)2.015s (~)0.000s (+233.3% 🔺)2.017s (~)0.660s302.07x
💻 LocalExpress1.399s (+14.2% 🔺)2.015s (~)0.000s (~)2.017s (~)0.619s302.13x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.448s (-7.8% 🟢)5.468s (+7.2% 🔺)0.000s (-100.0% 🟢)5.938s (+7.4% 🔺)2.490s111.00x
▲ VercelNitro3.536s (+15.9% 🔺)5.018s (+14.2% 🔺)0.000s (+18.2% 🔺)5.582s (+16.1% 🔺)2.046s111.03x
▲ VercelNext.js (Turbopack)6.247s (-38.6% 🟢)7.226s (-37.3% 🟢)0.000s (+Infinity% 🔺)8.682s (-27.9% 🟢)2.435s81.81x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-25.3% 🟢)2.032s (-5.1% 🟢)0.000s (-100.0% 🟢)2.043s (-6.0% 🟢)0.706s301.00x
🐘 PostgresExpress1.607s (-9.3% 🟢)2.257s (+3.6%)0.000s (NaN%)2.269s (+3.2%)0.662s271.20x
💻 LocalNitro3.176s (-6.2% 🟢)3.902s (-3.2%)0.000s (-18.0% 🟢)3.908s (-3.2%)0.732s162.37x
💻 LocalExpress3.234s (-6.7% 🟢)3.969s (-1.6%)0.001s (-21.9% 🟢)3.972s (-1.6%)0.738s162.42x
💻 LocalNext.js (Turbopack)⚠️missing-----
🐘 PostgresNext.js (Turbopack)⚠️missing-----

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.843s (+27.4% 🔺)7.349s (+22.0% 🔺)0.000s (NaN%)7.881s (+22.1% 🔺)2.039s81.00x
▲ VercelNitro6.140s (+50.0% 🔺)7.289s (+35.6% 🔺)0.000s (-54.2% 🟢)8.368s (+44.4% 🔺)2.228s81.05x
▲ VercelNext.js (Turbopack)9.992s (+77.9% 🔺)10.778s (+54.4% 🔺)0.000s (-100.0% 🟢)12.503s (+65.8% 🔺)2.511s51.71x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress16/21
🐘 PostgresExpress14/21
▲ VercelExpress12/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres15/21
Next.js (Turbopack)▲ Vercel21/21
Nitro🐘 Postgres19/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@TooTallNate
TooTallNate merged commit 254482e into mainMay 5, 2026
111 of 114 checks passed
@TooTallNate
TooTallNate deleted the backport-signed-commits-via-graphql branch May 5, 2026 08:12
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 254482e (AI decision).

This commit only modifies .github/workflows/backport.yml, which is the backport workflow itself. The backport workflow runs on main and pushes to stable, so it doesn't need to exist on stable at all. Backporting changes to the backport workflow would have no effect.

To override, add the backport-stable label to this PR.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the backport.yml workflow to avoid branch ruleset rejections that require verified-signed commits on all refs. Instead of pushing a locally cherry-picked commit (unsigned in CI), it replays the cherry-pick via GitHub’s GraphQL createCommitOnBranch mutation so GitHub produces a verified-signed commit on the backport branch.

Changes:

  • Replace git push with a GitHub API–based branch update using GraphQL createCommitOnBranch (auto-signed commits).
  • Improve robustness of PR creation by reusing an existing open backport PR for the same branch instead of failing.
  • Update manual conflict-resolution instructions to require signed local cherry-picks (git cherry-pick -S) due to repo rulesets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +555
const [, mode, type, blobSha] = match;
if (type !== 'blob') {
throw new Error(
`Unsupported tree entry for ${path}: type=${type} mode=${mode}. ` +
`GraphQL createCommitOnBranch only supports regular files.`,
);
}
Comment on lines +522 to +526
const diffOutput = git(
'diff',
'--name-status',
'-z',
parentSha,
pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
feat: serializable AbortController/AbortSignal (#1301)
Auto-remove workflow packages from serverExternalPackages (#1481)
Add missing changeset for Zod 4.4.x compatibility fix in @workflow/world (#1939)
Push backport branch via GraphQL createCommitOnBranch for signed commits (#1937)
Fix backport workflow opencode permission and surface AI failures (#1936)
Restructure backport workflow with AI-driven decisions (#1934)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TooTallNate