') + ')', '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('^' + ".*" + ', '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" + ', '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('^' + ".*" + ', '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); } })(); })(); fix(core): resolve forwarded stream keys across deployments by pranaygp · Pull Request #2191 · vercel/workflow · GitHub
Skip to content

fix(core): resolve forwarded stream keys across deployments - #2191

Merged
pranaygp merged 1 commit into
mainfrom
pranaygp/codex/fix-cross-deployment-stream-encryption
Jun 1, 2026
Merged

fix(core): resolve forwarded stream keys across deployments#2191
pranaygp merged 1 commit into
mainfrom
pranaygp/codex/fix-cross-deployment-stream-encryption

Conversation

@pranaygp

Copy link
Copy Markdown
Contributor

Summary

  • carry the owning deployment ID on forwarded writable stream descriptors so a child on a newer deployment encrypts parent-stream chunks with the parent key
  • fall back to loading the owning run for descriptors already serialized by older SDK versions
  • add focused regression tests and document the expanded World key-resolution usage

Root Cause

Cross-run writable revivers only carried the parent runId and called getEncryptionKeyForRun(targetRunId). In @workflow/world-vercel, a string lookup without deployment context resolves against the executing deployment, so a child started on a newer deployment encrypted new chunks using its key while the parent stream is read using the older run key.

Context

This upstreams the behavior temporarily patched downstream in https://github.com/vercel/ash/pull/852, while avoiding its extra owner-run lookup for newly serialized descriptors. Legacy or in-flight descriptors retain a correctness fallback.

Validation

  • pnpm turbo build --filter=@workflow/core...
  • pnpm --filter @workflow/core typecheck
  • pnpm --filter @workflow/core exec vitest run src/serialization.test.ts src/step/writable-stream.test.ts
  • pnpm --filter @workflow/core test
  • pnpm biome format <changed files>
  • pnpm changeset status --since=main

@vercel

vercelBot commented May 31, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c12a58f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
NameType
@workflow/corePatch
@workflow/worldPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

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

@github-actions

github-actionsBot commented May 31, 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🥇 Express0.038s (-13.5% 🟢)1.005s (~)0.967s101.00x
💻 LocalNitro0.042s (-2.6%)1.006s (~)0.964s101.10x
🐘 PostgresExpress0.060s (+4.3%)1.012s (~)0.951s101.58x
🐘 PostgresNext.js (Turbopack)0.068s1.013s0.945s101.76x
🐘 PostgresNitro0.068s (-28.2% 🟢)1.012s (-2.9%)0.944s101.79x
💻 LocalNext.js (Turbopack)0.555s1.508s0.952s1014.50x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.299s (+27.1% 🔺)2.417s (+13.2% 🔺)2.118s101.00x
▲ VercelNext.js (Turbopack)0.337s (+33.8% 🔺)2.172s (-6.9% 🟢)1.835s101.12x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.095s (-2.7%)2.006s (~)0.912s101.00x
💻 LocalNitro1.097s (-3.0%)2.006s (~)0.910s101.00x
💻 LocalNext.js (Turbopack)1.104s2.006s0.902s101.01x
🐘 PostgresNitro1.109s (-2.7%)2.010s (~)0.901s101.01x
🐘 PostgresExpress1.111s (-3.1%)2.012s (~)0.901s101.01x
🐘 PostgresNext.js (Turbopack)1.140s2.011s0.870s101.04x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.715s (-15.7% 🟢)3.338s (-12.9% 🟢)1.622s101.00x
▲ VercelExpress1.729s (-7.8% 🟢)3.887s (+2.1%)2.157s101.01x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.500s (-3.9%)11.022s (~)0.522s31.00x
💻 LocalNitro10.545s (-3.7%)11.023s (~)0.478s31.00x
🐘 PostgresNitro10.548s (-3.0%)11.017s (~)0.469s31.00x
🐘 PostgresExpress10.573s (-3.6%)11.020s (~)0.447s31.01x
💻 LocalNext.js (Turbopack)10.617s11.020s0.403s31.01x
🐘 PostgresNext.js (Turbopack)10.801s11.020s0.218s31.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.754s (-19.0% 🟢)16.102s (-19.6% 🟢)2.348s21.00x
▲ VercelNext.js (Turbopack)13.931s (-19.6% 🟢)15.555s (-19.8% 🟢)1.624s21.01x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.642s (-8.9% 🟢)14.026s (-6.7% 🟢)0.384s51.00x
🐘 PostgresExpress13.784s (-5.5% 🟢)14.017s (-6.7% 🟢)0.233s51.01x
💻 LocalNitro13.788s (-8.5% 🟢)14.026s (-12.5% 🟢)0.239s51.01x
🐘 PostgresNitro13.815s (-5.3% 🟢)14.018s (-6.7% 🟢)0.203s51.01x
💻 LocalNext.js (Turbopack)13.937s14.026s0.089s51.02x
🐘 PostgresNext.js (Turbopack)14.512s15.018s0.506s41.06x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express22.997s (-54.3% 🟢)25.068s (-52.3% 🟢)2.071s31.00x
▲ VercelNext.js (Turbopack)23.211s (-55.8% 🟢)24.883s (-54.4% 🟢)1.672s31.01x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express12.315s (-25.8% 🟢)13.024s (-23.5% 🟢)0.709s71.00x
🐘 PostgresExpress12.574s (-10.2% 🟢)13.023s (-10.8% 🟢)0.449s71.02x
💻 LocalNitro12.623s (-24.8% 🟢)13.025s (-23.5% 🟢)0.402s71.03x
🐘 PostgresNitro12.869s (-7.9% 🟢)13.304s (-7.0% 🟢)0.436s71.04x
💻 LocalNext.js (Turbopack)12.874s13.166s0.293s71.05x
🐘 PostgresNext.js (Turbopack)13.759s14.018s0.259s71.12x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express31.902s (-73.7% 🟢)34.053s (-72.5% 🟢)2.152s31.00x
▲ VercelNext.js (Turbopack)34.880s (-91.1% 🟢)36.165s (-90.9% 🟢)1.285s31.09x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.178s (-6.5% 🟢)2.007s (~)0.829s151.00x
🐘 PostgresNitro1.184s (-7.1% 🟢)2.007s (~)0.823s151.00x
💻 LocalExpress1.235s (-17.0% 🟢)2.006s (~)0.771s151.05x
🐘 PostgresNext.js (Turbopack)1.237s2.009s0.772s151.05x
💻 LocalNitro1.267s (-22.4% 🟢)2.006s (-3.3%)0.739s151.07x
💻 LocalNext.js (Turbopack)1.299s2.006s0.707s151.10x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.527s (-25.6% 🟢)3.955s (-19.8% 🟢)1.428s81.00x
▲ VercelExpress2.610s (-8.7% 🟢)4.087s (-11.6% 🟢)1.477s81.03x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.251s (-46.8% 🟢)2.007s (-33.3% 🟢)0.757s151.00x
🐘 PostgresExpress1.271s (-46.2% 🟢)2.008s (-33.3% 🟢)0.737s151.02x
🐘 PostgresNext.js (Turbopack)1.369s2.008s0.639s151.09x
💻 LocalNext.js (Turbopack)1.696s2.005s0.309s151.36x
💻 LocalExpress1.720s (-41.7% 🟢)2.006s (-41.9% 🟢)0.285s151.38x
💻 LocalNitro1.999s (-36.4% 🟢)2.392s (-38.4% 🟢)0.393s131.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.597s (-0.6%)5.445s (+6.5% 🔺)1.848s61.00x
▲ VercelNext.js (Turbopack)3.940s (-44.5% 🟢)5.435s (-39.0% 🟢)1.495s61.10x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.387s (-60.2% 🟢)2.007s (-50.0% 🟢)0.620s151.00x
🐘 PostgresNitro1.412s (-59.4% 🟢)2.009s (-49.9% 🟢)0.597s151.02x
🐘 PostgresNext.js (Turbopack)1.714s2.225s0.511s141.24x
💻 LocalExpress4.279s (-48.7% 🟢)5.013s (-44.5% 🟢)0.734s63.09x
💻 LocalNext.js (Turbopack)4.404s5.011s0.607s63.18x
💻 LocalNitro5.590s (-33.0% 🟢)6.213s (-31.1% 🟢)0.623s54.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.133s (+21.0% 🔺)7.674s (+25.2% 🔺)2.542s41.00x
▲ VercelNext.js (Turbopack)6.980s (-21.7% 🟢)8.913s (-18.7% 🟢)1.933s41.36x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.189s (-5.4% 🟢)2.009s (~)0.820s151.00x
🐘 PostgresExpress1.227s (-2.4%)2.008s (~)0.781s151.03x
🐘 PostgresNext.js (Turbopack)1.262s2.009s0.747s151.06x
💻 LocalNext.js (Turbopack)1.285s2.006s0.720s151.08x
💻 LocalExpress1.533s (-19.1% 🟢)2.006s (-15.1% 🟢)0.473s151.29x
💻 LocalNitro1.579s (-15.3% 🟢)2.007s (-14.2% 🟢)0.428s151.33x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.835s (-3.3%)4.591s (-1.1%)1.756s71.00x
▲ VercelExpress2.955s (+14.5% 🔺)4.521s (+3.9%)1.566s71.04x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.265s (-45.9% 🟢)2.075s (-31.1% 🟢)0.809s151.00x
🐘 PostgresExpress1.279s (-45.4% 🟢)2.009s (-33.3% 🟢)0.730s151.01x
🐘 PostgresNext.js (Turbopack)1.390s2.008s0.618s151.10x
💻 LocalNext.js (Turbopack)1.894s2.220s0.326s141.50x
💻 LocalExpress1.908s (-39.1% 🟢)2.317s (-38.4% 🟢)0.409s131.51x
💻 LocalNitro2.223s (-27.5% 🟢)2.736s (-29.6% 🟢)0.513s111.76x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.674s (+15.1% 🔺)5.322s (+11.1% 🔺)1.648s61.00x
▲ VercelNext.js (Turbopack)3.868s (+23.1% 🔺)5.206s (+15.1% 🔺)1.338s61.05x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.406s (-59.8% 🟢)2.008s (-49.9% 🟢)0.602s151.00x
🐘 PostgresNitro1.407s (-59.6% 🟢)2.008s (-49.9% 🟢)0.601s151.00x
🐘 PostgresNext.js (Turbopack)1.644s2.222s0.577s141.17x
💻 LocalNext.js (Turbopack)4.454s5.180s0.725s63.17x
💻 LocalExpress5.494s (-37.6% 🟢)6.013s (-35.1% 🟢)0.520s63.91x
💻 LocalNitro7.016s (-23.3% 🟢)7.518s (-25.0% 🟢)0.502s44.99x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.973s (-11.6% 🟢)7.791s (-8.8% 🟢)1.818s41.00x
▲ VercelExpress6.080s (-5.3% 🟢)8.025s (-1.9%)1.945s41.02x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.582s (-40.8% 🟢)1.004s (-6.6% 🟢)0.422s601.00x
🐘 PostgresExpress0.592s (-29.4% 🟢)1.023s (~)0.431s591.02x
🐘 PostgresNitro0.601s (-26.8% 🟢)1.023s (+1.7%)0.423s591.03x
💻 LocalNext.js (Turbopack)0.676s1.004s0.328s601.16x
💻 LocalNitro0.731s (-25.5% 🟢)1.089s (~)0.358s601.25x
🐘 PostgresNext.js (Turbopack)0.834s1.042s0.208s581.43x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.615s (-61.3% 🟢)7.015s (-56.4% 🟢)1.400s91.00x
▲ VercelExpress5.937s (-68.8% 🟢)7.762s (-63.6% 🟢)1.825s81.06x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.356s (-31.4% 🟢)2.007s (-11.1% 🟢)0.652s451.00x
🐘 PostgresNitro1.403s (-27.2% 🟢)2.008s (-4.4%)0.605s451.03x
💻 LocalExpress1.523s (-49.5% 🟢)2.028s (-43.4% 🟢)0.505s451.12x
💻 LocalNitro1.608s (-47.0% 🟢)2.029s (-46.0% 🟢)0.421s451.19x
💻 LocalNext.js (Turbopack)1.674s2.006s0.332s451.23x
🐘 PostgresNext.js (Turbopack)1.923s2.100s0.177s431.42x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.345s (-61.3% 🟢)15.636s (-57.5% 🟢)2.291s61.00x
▲ VercelNext.js (Turbopack)13.612s (-72.7% 🟢)15.872s (-69.3% 🟢)2.260s61.02x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.705s (-34.1% 🟢)3.060s (-33.5% 🟢)0.354s401.00x
🐘 PostgresExpress2.754s (-31.0% 🟢)3.111s (-28.8% 🟢)0.357s391.02x
💻 LocalExpress3.210s (-65.1% 🟢)3.944s (-60.6% 🟢)0.734s311.19x
💻 LocalNitro3.286s (-64.7% 🟢)4.010s (-60.0% 🟢)0.723s301.21x
💻 LocalNext.js (Turbopack)3.550s4.008s0.458s301.31x
🐘 PostgresNext.js (Turbopack)3.800s4.076s0.276s301.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express28.591s (-78.0% 🟢)31.446s (-76.2% 🟢)2.855s41.00x
▲ VercelNext.js (Turbopack)31.602s (-70.5% 🟢)34.095s (-68.7% 🟢)2.493s41.11x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.223s (-21.2% 🟢)1.006s (~)0.783s601.00x
🐘 PostgresNitro0.225s (-20.4% 🟢)1.007s (~)0.781s601.01x
🐘 PostgresNext.js (Turbopack)0.257s1.006s0.749s601.15x
💻 LocalExpress0.420s (-25.1% 🟢)1.004s (~)0.584s601.88x
💻 LocalNitro0.453s (-25.1% 🟢)1.005s (-1.6%)0.552s602.03x
💻 LocalNext.js (Turbopack)0.538s1.039s0.501s582.41x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.445s (+25.1% 🔺)4.322s (+18.8% 🔺)1.877s151.00x
▲ VercelNext.js (Turbopack)3.185s (+57.5% 🔺)4.444s (+17.1% 🔺)1.259s151.30x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.342s (-32.8% 🟢)1.006s (~)0.664s901.00x
🐘 PostgresNitro0.353s (-28.9% 🟢)1.006s (~)0.654s901.03x
🐘 PostgresNext.js (Turbopack)0.466s1.006s0.540s901.36x
💻 LocalExpress2.148s (-14.5% 🟢)2.655s (-11.8% 🟢)0.508s346.27x
💻 LocalNitro2.193s (-13.6% 🟢)2.797s (-7.0% 🟢)0.605s336.40x
💻 LocalNext.js (Turbopack)2.227s3.043s0.816s306.50x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.028s (+70.5% 🔺)7.446s (+43.4% 🔺)1.418s131.00x
▲ VercelExpress6.098s (+100.1% 🔺)7.792s (+62.1% 🔺)1.694s121.01x
▲ VercelNitro⚠️missing----

🔍 Observability: Next.js (Turbopack) | Express

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.699s (-14.7% 🟢)1.007s (-1.1%)0.308s1201.00x
🐘 PostgresNitro0.709s (-10.3% 🟢)1.008s (~)0.299s1201.01x
🐘 PostgresNext.js (Turbopack)0.933s1.357s0.424s891.34x
💻 LocalExpress9.490s (-15.2% 🟢)10.028s (-16.0% 🟢)0.538s1213.58x
💻 LocalNext.js (Turbopack)9.750s10.527s0.777s1213.95x
💻 LocalNitro9.804s (-12.4% 🟢)10.444s (-10.5% 🟢)0.640s1214.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express16.197s (+118.3% 🔺)18.287s (+97.8% 🔺)2.090s71.00x
▲ VercelNext.js (Turbopack)16.476s (+59.5% 🔺)18.218s (+48.3% 🔺)1.742s71.02x
▲ VercelNitro⚠️missing----

🔍 Observability: Express | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.158s (+481.8% 🔺)2.005s (+99.6% 🔺)0.010s (-14.0% 🟢)2.017s (+98.1% 🔺)0.859s101.00x
🐘 PostgresNitro1.173s (+472.4% 🔺)1.998s (+99.8% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.836s101.01x
🐘 PostgresExpress1.174s (+472.6% 🔺)1.999s (+100.2% 🔺)0.001s (-18.8% 🟢)2.011s (+98.8% 🔺)0.836s101.01x
💻 LocalNitro1.176s (+450.4% 🔺)2.005s (+99.6% 🔺)0.014s (+10.4% 🔺)2.021s (+98.4% 🔺)0.845s101.02x
💻 LocalNext.js (Turbopack)1.176s2.003s0.009s2.016s0.839s101.02x
🐘 PostgresNext.js (Turbopack)1.222s2.002s0.001s2.011s0.788s101.06x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.237s (-10.7% 🟢)3.360s (-17.9% 🟢)1.747s (+81.8% 🔺)5.615s (~)3.378s101.00x
▲ VercelNext.js (Turbopack)2.308s (-66.3% 🟢)3.188s (-63.1% 🟢)2.062s (+226.3% 🔺)5.657s (-42.2% 🟢)3.350s101.03x
▲ VercelNitro⚠️missing-----

🔍 Observability: Express | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.569s (+107.3% 🔺)2.009s (+95.3% 🔺)0.010s (+5.2% 🔺)2.021s (+94.4% 🔺)0.452s301.00x
🐘 PostgresExpress1.590s (+152.4% 🔺)2.009s (+99.6% 🔺)0.004s (-0.8%)2.025s (+98.0% 🔺)0.435s301.01x
💻 LocalNitro1.620s (+93.2% 🔺)2.011s (+98.7% 🔺)0.010s (+7.4% 🔺)2.023s (+81.2% 🔺)0.402s301.03x
💻 LocalNext.js (Turbopack)1.621s2.007s0.010s2.020s0.399s301.03x
🐘 PostgresNitro1.656s (+165.3% 🔺)2.037s (+102.4% 🔺)0.004s (-8.1% 🟢)2.059s (+101.4% 🔺)0.403s301.06x
🐘 PostgresNext.js (Turbopack)1.738s2.010s0.004s2.026s0.287s301.11x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.860s (-9.9% 🟢)7.352s (-8.2% 🟢)0.306s (-25.0% 🟢)8.208s (-7.1% 🟢)2.348s81.00x
▲ VercelNext.js (Turbopack)6.340s (-62.5% 🟢)7.483s (-59.0% 🟢)0.505s (+139.1% 🔺)8.483s (-55.2% 🟢)2.143s81.08x
▲ VercelNitro⚠️missing-----

🔍 Observability: Express | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.694s (-27.7% 🟢)1.012s (-20.8% 🟢)0.000s (-61.0% 🟢)1.024s (-21.6% 🟢)0.329s591.00x
🐘 PostgresNitro0.733s (-24.4% 🟢)1.051s (-15.8% 🟢)0.000s (+26.3% 🔺)1.060s (-15.7% 🟢)0.327s571.05x
🐘 PostgresNext.js (Turbopack)0.790s1.052s0.000s1.059s0.269s571.14x
💻 LocalNitro1.397s (+14.2% 🔺)2.015s (~)0.001s (+533.3% 🔺)2.017s (~)0.621s302.01x
💻 LocalNext.js (Turbopack)1.411s2.012s0.000s2.015s0.604s302.03x
💻 LocalExpress1.427s (+16.5% 🔺)2.014s (~)0.000s (-50.0% 🟢)2.016s (~)0.589s302.06x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.770s (+0.8%)5.106s (~)0.000s (-100.0% 🟢)5.635s (+1.9%)1.866s111.00x
▲ VercelNext.js (Turbopack)4.126s (-59.5% 🟢)5.368s (-53.4% 🟢)0.000s (+Infinity% 🔺)5.823s (-51.7% 🟢)1.696s111.09x
▲ VercelNitro⚠️missing-----

🔍 Observability: Express | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.492s (-16.7% 🟢)2.136s (~)0.000s (-3.4%)2.151s (-1.1%)0.658s291.00x
🐘 PostgresExpress1.542s (-13.0% 🟢)2.176s (~)0.000s (NaN%)2.189s (~)0.647s281.03x
🐘 PostgresNext.js (Turbopack)1.655s2.069s0.000s2.099s0.444s291.11x
💻 LocalNext.js (Turbopack)2.802s3.552s0.000s3.556s0.753s171.88x
💻 LocalNitro3.134s (-7.5% 🟢)3.837s (-4.9%)0.001s (-6.2% 🟢)3.843s (-4.8%)0.710s162.10x
💻 LocalExpress3.141s (-9.4% 🟢)3.830s (-5.1% 🟢)0.001s (-29.7% 🟢)3.843s (-4.8%)0.702s162.10x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)6.210s (+10.6% 🔺)7.419s (+6.3% 🔺)0.000s (~)7.796s (+3.4%)1.586s81.00x
▲ VercelExpress6.612s (+44.1% 🔺)8.262s (+37.2% 🔺)0.005s (+Infinity% 🔺)8.737s (+35.3% 🔺)2.125s81.06x
▲ VercelNitro⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress15/21
🐘 PostgresExpress13/21
▲ VercelExpress14/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres13/21
Next.js (Turbopack)🐘 Postgres12/21
Nitro🐘 Postgres15/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)
  • 🌐 Redis: Community world (local development)
  • 🌐 Redis + BullMQ: Community world (local development)
  • 🌐 Cloudflare: Community world (local development)
  • 🌐 MySQL: Community world (local development)
  • 🌐 Azure: Community world (local development)
  • 🌐 NATS JetStream: Community world (local development)
  • 🌐 Upstash: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

@github-actions

github-actionsBot commented May 31, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production126602191485
✅ 💻 Local Development167102191890
✅ 📦 Local Production167102191890
✅ 🐘 Local Postgres167102191890
✅ 🪟 Windows13500135
✅ 📋 Other7690176945
Total7183010528235

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro109026
✅ example109026
✅ express109026
✅ fastify109026
✅ hono109026
✅ nextjs-turbopack13302
✅ nextjs-webpack13302
✅ nitro109026
✅ nuxt109026
✅ sveltekit12807
✅ vite109026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable110025
✅ express-stable110025
✅ fastify-stable110025
✅ hono-stable110025
✅ nextjs-turbopack-canary116019
✅ nextjs-turbopack-stable-lazy-discovery-disabled13500
✅ nextjs-turbopack-stable-lazy-discovery-enabled13500
✅ nextjs-webpack-canary116019
✅ nextjs-webpack-stable-lazy-discovery-disabled13500
✅ nextjs-webpack-stable-lazy-discovery-enabled13500
✅ nitro-stable110025
✅ nuxt-stable110025
✅ sveltekit-stable12906
✅ vite-stable110025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable110025
✅ express-stable110025
✅ fastify-stable110025
✅ hono-stable110025
✅ nextjs-turbopack-canary116019
✅ nextjs-turbopack-stable-lazy-discovery-disabled13500
✅ nextjs-turbopack-stable-lazy-discovery-enabled13500
✅ nextjs-webpack-canary116019
✅ nextjs-webpack-stable-lazy-discovery-disabled13500
✅ nextjs-webpack-stable-lazy-discovery-enabled13500
✅ nitro-stable110025
✅ nuxt-stable110025
✅ sveltekit-stable12906
✅ vite-stable110025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable110025
✅ express-stable110025
✅ fastify-stable110025
✅ hono-stable110025
✅ nextjs-turbopack-canary116019
✅ nextjs-turbopack-stable-lazy-discovery-disabled13500
✅ nextjs-turbopack-stable-lazy-discovery-enabled13500
✅ nextjs-webpack-canary116019
✅ nextjs-webpack-stable-lazy-discovery-disabled13500
✅ nextjs-webpack-stable-lazy-discovery-enabled13500
✅ nitro-stable110025
✅ nuxt-stable110025
✅ sveltekit-stable12906
✅ vite-stable110025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack13500
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable110025
✅ e2e-local-dev-tanstack-start-110025
✅ e2e-local-postgres-nest-stable110025
✅ e2e-local-postgres-tanstack-start-110025
✅ e2e-local-prod-nest-stable110025
✅ e2e-local-prod-tanstack-start-110025
✅ e2e-vercel-prod-tanstack-start109026

📋 View full workflow run

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approve — solid fix, with one small consistency concern worth thinking about

The cross-deployment encryption bug is real and the fix is well-targeted: add deploymentId to the writable stream descriptor wire format, stamp it via STREAM_SERVER_DEPLOYMENT_ID_SYMBOL on writables that have it, and use it in getEncryptionKeyForRun(runId, { deploymentId }) instead of the assumed-current-deployment fallback. Legacy descriptors without a deploymentId fall back to loading the owning run via world.runs.get(runId) — that's correctness-preserving for in-flight serialized payloads.

Verified

  • After rebasing onto current main: 12 files, +278/-22 (the scary "removals" of experimentalSetAttributes from interfaces.ts and the encryption error handling in serialization.ts are stale-branch artifacts from being forked before #2134, #2157, and #2145 landed)
  • pnpm install --frozen-lockfile
  • pnpm turbo run build --filter @workflow/core
  • pnpm --filter @workflow/core test ✓ (1083/1083)
  • The two new serialization tests both pass:
    • Happy path — forwarded writable with deploymentId → uses getEncryptionKeyForRun(runId, { deploymentId }) and does NOT call runs.get
    • Legacy fallback — descriptor without deploymentId → calls runs.get(runId) first, then getEncryptionKeyForRun(run)

CI noise

14 failures on the latest run, but they're all cascading from swc-plugin-workflow WASM build failing with undefined symbol: __emit_diagnostics. That's the bug fixed by #2174 (5dabbeeca fix(swc-plugin): allow wasm host imports during link) which landed on main after this branch was forked. A rebase would resolve them all.

One thing worth thinking about — step-handler.ts uses process.env.VERCEL_DEPLOYMENT_ID

The two workflowDeploymentId sites are:

SiteSource
runtime.ts (inline step execution)workflowRun.deploymentId / bgRun.deploymentId — the workflow's ACTUAL deployment ✓
step-handler.ts (background step execution)process.env.VERCEL_DEPLOYMENT_ID — the CURRENT runtime deployment

For background steps, these are only the same if the queue routes steps to the workflow's original deployment. If queues route steps to a NEWER deployment, process.env.VERCEL_DEPLOYMENT_ID is the newer one, not the workflow's.

Reading the world-vercel getEncryptionKeyForRun, the existing background-step encryption key resolution ALREADY assumes current-deployment (it calls memoizeEncryptionKey(world, workflowRunId) with no context, which then uses local HKDF when running inside Vercel). So this PR's choice in step-handler.ts is at least consistent with how step encryption already works — if the existing background-step encryption is correct (i.e., queue routes to original deployment, or some other invariant), then the new workflowDeploymentId source is also correct.

If the existing encryption has a latent bug for background steps running on newer deployments, this PR carries that forward — but doesn't make it worse, and the parent/child cross-deployment case (which is what the PR is actually trying to fix) IS handled correctly via the inline runtime.ts paths using workflowRun.deploymentId.

Worth confirming the invariant: do background step queues always route to the workflow's original deployment, or can they route to newer deployments? If the latter, there's a follow-up to also resolve the workflow's actual deployment in step-handler.ts (probably load the run first, similar to the legacy fallback in this PR's getForwardedWritableEncryptionKey).

Not a blocker — the PR's scope is the parent/child writable case, and that's handled correctly.

Bonus: the test design caught a subtle correctness point

The legacy-fallback test asserts the right behavior when descriptors are mid-flight from older SDK versions:

expect(runsGet).toHaveBeenCalledWith('wrun_parent');expect(getEncryptionKeyForRun).toHaveBeenCalledWith(parentRun);

That confirms the fallback uses the full WorkflowRun overload (which extracts deploymentId from run.deploymentId), not the broken (runId, undefined-context) overload. Good test instinct.

PR status

Currently draft. Approving in spirit pending:

  1. Rebase onto current main (resolves the stale-branch CI cascades + the deletions-in-diff confusion)
  2. Optional: thread an explicit workflowDeploymentId through the background step path if cross-deployment step routing is actually possible

Approving.

@pranaygp
pranaygp marked this pull request as ready for review June 1, 2026 17:48
@pranaygp
pranaygp requested a review from a team as a code ownerJune 1, 2026 17:48
CopilotAI review requested due to automatic review settings June 1, 2026 17:48
@pranaygp
pranaygp enabled auto-merge (squash) June 1, 2026 17:49
@pranaygp
pranaygpforce-pushed the pranaygp/codex/fix-cross-deployment-stream-encryption branch from bf73d05 to c12a58fCompareJune 1, 2026 17:51
@pranaygp

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current main to pick up the SWC linker fix from #2174 (5dabbeeca). Focused validation on the new head passed locally:

  • pnpm --filter @workflow/swc-plugin build
  • pnpm turbo build --filter=@workflow/core...
  • pnpm --filter @workflow/core typecheck
  • pnpm --filter @workflow/core test (44 files / 1083 tests)
  • pnpm changeset status --since=origin-https/main

I left the existing V1 step-handler deployment behavior unchanged; this patch only carries the writable stream owner deployment through serialization so forwarded stream writes resolve their original key.

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 fixes encryption-key resolution for forwarded WritableStream handles when parent/child workflow runs execute on different Vercel deployments, by carrying the owning deployment ID through serialization and using it to resolve the correct per-run encryption key.

Changes:

  • Stamp forwarded WritableStream descriptors with an owning deploymentId and thread deployment context through step hydration/execution.
  • Update serialization reducers/revivers to persist and revive the owning deployment ID, and resolve the forwarded-stream encryption key with deployment context (with legacy fallback).
  • Add regression tests and a changeset; clarify World.getEncryptionKeyForRun documentation to cover forwarded-stream usage.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
packages/world/src/interfaces.tsExpands getEncryptionKeyForRun docs to include forwarded-stream key resolution context.
packages/core/src/symbols.tsAdds a new symbol to tag forwarded streams with owning deployment ID.
packages/core/src/step/context-storage.tsExtends StepContext to carry workflowDeploymentId for forwarded streams.
packages/core/src/step/writable-stream.tsTags created writables with owning deployment ID when available.
packages/core/src/step/writable-stream.test.tsAdds a test asserting the deployment tag is applied to step-level writables.
packages/core/src/serialization/types.tsExtends serializable WritableStream descriptor shape with deploymentId.
packages/core/src/serialization.tsPropagates deploymentId in reducers/revivers and resolves forwarded-stream encryption keys with deployment context + legacy fallback.
packages/core/src/serialization.test.tsAdds regression tests covering deployment-aware key resolution and legacy fallback behavior.
packages/core/src/runtime/step-handler.tsPasses deployment ID into step hydration and step context for stream forwarding.
packages/core/src/runtime/step-executor.tsThreads workflowDeploymentId through step execution to hydration/context.
packages/core/src/runtime.tsPopulates workflowDeploymentId from the loaded run when executing steps.
.changeset/cross-deployment-stream-keys.mdPublishes patch changes for @workflow/core and @workflow/world.
Comments suppressed due to low confidence (1)

packages/core/src/serialization.ts:1363

  • The legacy (no deploymentId) path loads the full run via world.runs.get(runId) to resolve the encryption key. runs.get() defaults to resolveData: 'all', which can fetch large input/output/error blobs unnecessarily just to read deploymentId, increasing latency and memory usage when hydrating forwarded streams.

Consider fetching the owner run with resolveData: 'none' for this fallback lookup.

 tagAbortPair(controller, value);
controller.abort(value.reason);
} else if (value.streamName) {

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

@pranaygp
pranaygp merged commit 8f68d35 into mainJun 1, 2026
178 of 191 checks passed
@pranaygp
pranaygp deleted the pranaygp/codex/fix-cross-deployment-stream-encryption branch June 1, 2026 18:38
@github-actionsgithub-actionsBot mentioned this pull request Jun 1, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Backport to stable failed — the cherry-pick had conflicts that could not be resolved automatically (backport job run).

To resolve manually, push a backport branch and open a PR against stable (the workflow never pushes directly to stable). Note: this repository requires verified signatures on every branch, so your local commits must be signed (git config commit.gpgsign true with a configured GPG/SSH signing key, or git cherry-pick -S).

git fetch origin stable
git checkout -b backport/pr-2191-to-stable origin/stable
git cherry-pick -S 8f68d3525ce3e420f4d16b9976c97a5598f91afd # -S signs the commit# Fix conflicts, then:
git add -A
git cherry-pick --continue
git push -u origin backport/pr-2191-to-stable
gh pr create --base stable --head backport/pr-2191-to-stable \
--title "Backport #2191: <original PR title>" \
--body "Manual backport of #2191 (cherry-pick 8f68d3525ce3) to \`stable\`."

pranaygp added a commit that referenced this pull request Jun 1, 2026
TooTallNate pushed a commit that referenced this pull request Jun 1, 2026
pranaygp added a commit that referenced this pull request Jun 2, 2026
* origin/main:
[world-vercel] Retry transient response-body parse failures in the HTTP client (#2204)
Add virtualization to the trace viewer (#2205)
Trace viewer: scroll-load events past an auto-load cap (#2200)
fix(core): resolve forwarded stream keys across deployments (#2191)
[e2e] Improve error labeling in event-log-race-repro CI job (#2190)
[core] Harden event pagination response parsing (#2180) (#2179)
Add loading skeleton to the new trace viewer (#2164)
Add tooltip components + apply on up/down detail pane (#2163)
fix(swc-plugin): allow wasm host imports during link (#2174)
[test] Forward-port reused-sleep replay divergence test (#2172)
[e2e] Add `event-log-race-repro` label for triggering CI stress-test (#2159)
Version Packages (beta) (#2162)
fix(world-local): skip Nov 2025 ghost versions on npm (#2168)
fix(core,errors): classify SDK encryption failures as RUNTIME_ERROR (#2145)
[web-shared][web] Fix events tab search (#2107)
Version Packages (beta) (#2147)
Allow setting workflow attributes from steps (#2157)
Better search handling on the trace viewer (#2144)
[docs] Document experimental attributes feature (#2141)
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.

3 participants

@pranaygp@TooTallNate