vercel — Engineering Performance
46 engineers all time · Jan 2025 – Aug 2026 · built 2026-08-23 · GitHub
Performance snapshot
Today's rolling 90-day reading for vercel, compared with the start of the series. Pick a window to move that comparison point.
Eff. capacity added
+1.4engineers
24 devs deliver like 25 (1.1x pre-AI)
Avg. perf / dev / mo (ETV)
+391.1%
0.19 → 0.91
Active engineers
+60.0%
15.0 → 24.0
Features
+15.4pp
28.3% → 43.7%
vercel vs. Vercel
Per-engineer ETV for vercel against Vercel as a whole. Both lines are 90-day rolling averages scaled to a 30-day month, so they share one axis and can be read against each other at any point. Pick a window to zoom the chart to it.
Performance over time
ETV stacked by Features / Maintenance / Tests / Docs / Fixes — 90-day moving average, normalized to ETV / month.
Engineering capacity
Effective engineers behind vercel, in pre-AI terms. Per-engineer ETV divided by the Q1 2025 baseline of 0.86 ETV / dev / mo gives a capacity multiple, and that multiple applied to the engineers active in the trailing 90 days turns it into engineer-equivalents. The line is the real headcount, so the gap between line and area is what the leverage is worth.
Knowledge concentration
How dependent is this repo on a small number of engineers? Higher top-1 share = higher key-person risk.
Jeff See owns 15.2 % of commits.
Reports
Written summary of the work completed each month.
No monthly reports available yet.
Top engineers
Most impactful commits
Top 10 by ETV in the all-time window.
- 2.9ETVAdd experimental container runtime (#16648) ## Summary Adds an experimental **container service runtime** to the Vercel CLI monorepo. Services configured with `runtime: "container"` can either: - **Build from a Dockerfile** — build the image, push it to the Vercel Container Registry (VCR), wait for readiness, and emit a digest-pinned image reference as build output, or - **Use a prebuilt image** — pass through an existing registry reference via `image` / entrypoint without building locally. This wires the new `@vercel/container` builder into service detection, `vercel build` output collection, and the Build Output API. ## TLDR This is a small tweak to add a new runtime for the existing services api, the container package is isolated and only enabled when the runtime is `container`, so should be safe to merge with minimal impact to production codepaths. ## How it works 1. **Detection** (`@vercel/fs-detectors`) — resolves container services from `vercel.json` / service config; Dockerfile entrypoints (`Dockerfile`, `Containerfile`, `*.dockerfile`) trigger a build, otherwise the entrypoint is treated as a prebuilt image ref. 2. **Build** (`@vercel/container`) — authenticates to VCR with `VERCEL_OIDC_TOKEN`, ensures the target repository exists, then build → login → push. 3. **Output** — writes a container function to `.vercel/output` with `runtime: "container"` and a digest-pinned VCR image reference as the handler. 4. **Readiness** — polls until the pushed digest is usable (remote manifest inspection locally via docker; skopeo with buildah on Vercel). ## Toolchain | Environment | Engine | Notes | |---|---|---| | Local `vercel build` | **docker** | Uses the local Docker daemon (OrbStack, Docker Desktop, etc.) | | Vercel build container | **buildah** | Daemonless; includes storage-driver selection for nested build cells and a permissive `registries.conf` for unqualified `FROM` lines | Override with `VERCEL_CONTAINER_ENGINE=docker|buildah`. ## Packages touched - **`@vercel/container`** (new) — builder implementation, VCR push/readiness, pluggable `ContainerEngine` interface - **`@vercel/build-utils`** — `ContainerImage` output type for BOA collection - **`@vercel/fs-detectors`** — container service runtime resolution - **`vercel` CLI** — container output wiring in `write-build-result`, config validation, builder dependency ## Test plan - [x] `@vercel/container` unit tests (`pnpm test-unit` in `packages/container`) - [x] `@vercel/fs-detectors` container service detection tests - [ ] Local `vercel build --cwd <project-with-container-service>` with linked project + fresh OIDC token - [ ] Deploy to Vercel with a container service Dockerfile and confirm image lands in VCR - [ ] Verify buildah path in the Vercel build container (not just local docker) --------- Co-authored-by: Cursor <cursoragent@cursor.com>Jeff See · 186014d1 · 2026-06-24
- 2.3ETV[CLI] Updating the Vercel CLI Evals (#16136) This PR adds and tightens Vercel CLI agent eval coverage, including env, list, logs, inspect, project, pull, and curl scenarios. Also persists agent-eval model metadata during result upload so the dashboard can distinguish configured models from resolved runtime models. _deploy build curl/explicit curl/implicit env/add env/ls env/pull env/remove env/update init inspect link list login-whoami login-not-logged-in logs marketplace/find-postgres-integration marketplace/install-neon-postgres marketplace/metadata-discovery marketplace/multi-product-install non-interactive project/inspect project/list pull **New evals added in this PR:** inspect list logs project/inspect project/list pull **Also improved existing evals:** curl/explicit curl/implicit env/add env/ls env/update login-not-logged-in login-whoami non-interactiveMelkeyDev · a3a1a5a3 · 2026-05-16
- 2.1ETVfeat(packages/cli): support VCR command (#16883) Adds a `vercel vcr` command family to manage Vercel Container Registry (VCR) repositories and images from the CLI. Testing: - I have manually tests all commands, subcommands and combinations. - We have unit tests for each command, subcommand and utils file. vercel vcr ls (alias: `list`) --- List container registry repositories for a project: - `-p, --project` — Project name or ID (defaults to the linked project) - `--limit` — Number of results to return per page (default: 20, max: 1000) - `-c, --cursor` — Cursor from a previous page to continue listing from - `-F, --format` — Output format (json) Example: ``` ❯ vercel vcr ls Vercel CLI 54.18.6 (Node.js 20.18.0) Name ID Created final-test repo_AilNqzMU5CPZASoBX3xqoaCagoIg 1d ago test-1 repo_4etlr5w79O9LGx1E1dQTHes2kitD 8d ago test-multi-arch repo_bJDBJP0gKmP6SPZSc71oISy6BMEh 8d ago test1 repo_CVSY2AmyvugNN6WOTFKOF5VfeZ6r 8d ago test2 repo_7wsvDBp8xUaRFnzd5ev3dFrAaFT4 7d ago ❯ vercel vcr ls --limit 1 Vercel CLI 54.18.6 (Node.js 20.18.0) Name ID Created final-test repo_AilNqzMU5CPZASoBX3xqoaCagoIg 1d ago > More results available. Re-run with `--cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlIiwiU0siOiIkcmVwb3NpdG9yeV8xI25hbWVfZmluYWwtdGVzdCJ9`. ❯ vercel vcr ls --limit 1 --cursor eyJTSyI6IiRyZXBvc2l0b3J5XzEjbmFtZV9maW5hbC10ZXN0IiwiUEsiOiIkdmNyI3Byb2plY3RpZF9wcmpfdTR5eXpkM3o1ZnJ0ZWhudHljZTVmM29tbnBlZSJ9 Vercel CLI 54.18.6 (Node.js 20.18.0) Name ID Created test-1 repo_4etlr5w79O9LGx1E1dQTHes2kitD 8d ago > More results available. Re-run with `--cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlIiwiU0siOiIkcmVwb3NpdG9yeV8xI25hbWVfdGVzdC0xIn0`. ``` vercel vcr inspect (alias: `get`) --- Show details for a single repository: - `-p, --project` - `-F, --format` Example: ``` ❯ vercel vcr get final1 Vercel CLI 54.18.6 (Node.js 20.18.0) Error: VCR Repository not found. ❯ vercel vcr get test1 Vercel CLI 54.18.6 (Node.js 20.18.0) > Repository test1 Name test1 ID repo_CVSY2AmyvugNN6WOTFKOF5VfeZ6r Project ID prj_U4yYZD3z5fRtEhntyCE5F3oMnPEe Created 8d ago Updated 8d ago ❯ vercel vcr get repo_CVSY2AmyvugNN6WOTFKOF5VfeZ6r Vercel CLI 54.18.6 (Node.js 20.18.0) > Repository repo_CVSY2AmyvugNN6WOTFKOF5VfeZ6r Name test1 ID repo_CVSY2AmyvugNN6WOTFKOF5VfeZ6r Project ID prj_U4yYZD3z5fRtEhntyCE5F3oMnPEe Created 8d ago Updated 8d ago ``` vercel vcr add (alias: `create`) --- Create a container registry repository: - `-p, --project` - `-F, --format` Example: ``` ❯ vercel vcr add new-repo Vercel CLI 54.18.6 (Node.js 20.18.0) > Success! Created repository new-repo ❯ vercel vcr add "invalid repo name" Vercel CLI 54.18.6 (Node.js 20.18.0) Error: invalid repository name ``` vercel vcr rm (aliases: `remove`, `delete`) --- Delete a container registry repository: - `-p, --project` - `--yes` — Skip confirmation prompt - `-F, --format` Example: ``` ❯ vercel vcr rm new-repo Vercel CLI 54.18.6 (Node.js 20.18.0) ? Delete repository new-repo and all of its images? This cannot be undone. no > Canceled ❯ vercel vcr rm new-repo Vercel CLI 54.18.6 (Node.js 20.18.0) ? Delete repository new-repo and all of its images? This cannot be undone. yes > Success! Repository new-repo deleted ❯ vercel vcr rm new-repo --yes Vercel CLI 54.18.6 (Node.js 20.18.0) > Success! Repository new-repo deleted ❯ vercel vcr rm not-found --yes Vercel CLI 54.18.6 (Node.js 20.18.0) Error: VCR Repository not found. ``` vercel vcr tag ls --- List a repository's tags: - `-p, --project` - `--sort-by` — Field to sort by: `updatedAt` (default) or `tag` - `--sort-order` — Sort direction: `asc` or `desc` (default: `desc`) - `--limit` - `-c, --cursor` - `-F, --format` Example: ``` ❯ vercel vcr tag ls test1 Vercel CLI 54.18.6 (Node.js 20.18.0) Tag Image ID Digest Arch Size Created latest image_DIjo4083F2hnFlVzlcJdPGjO90FA b9610c5988ab amd64 36.9MB 6d ago v7 image_XvGyahtJG2AaPKROJJtLe2nlpYR0 776e8c66121f amd64 36.9MB 2d ago v5.5 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago v5.4 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z ❯ vercel vcr tag ls test1 --limit 1 Vercel CLI 54.18.6 (Node.js 20.18.0) Tag Image ID Digest Arch Size Created latest image_DIjo4083F2hnFlVzlcJdPGjO90FA b9610c5988ab amd64 36.9MB 6d ago v7 image_XvGyahtJG2AaPKROJJtLe2nlpYR0 776e8c66121f amd64 36.9MB 2d ago > More results available. Re-run with `--cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJTSyI6IiR0YWdfMSN0YWdfdjciLCJHU0kyUEsiOiIkdmNyI3Byb2plY3RpZF9wcmpfdTR5eXpkM3o1ZnJ0ZWhudHljZTVmM29tbnBlZSNyZXBvc2l0b3J5aWRfcmVwb19jdnN5MmFteXZ1Z25uNndvdGZrb2Y1dmZlejZyIiwiR1NJMlNLIjoiJHRhZ18xI3VwZGF0ZWRhdF8yMDI2LTA2LTMwdDExOjU1OjI0LjU1MHojdGFnX3Y3In0`. ❯ vercel vcr tag ls test1 --limit 1 --cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJTSyI6IiR0YWdfMSN0YWdfdjciLCJHU0kyUEsiOiIkdmNyI3Byb2plY3RpZF9wcmpfdTR5eXpkM3o1ZnJ0ZWhudHljZTVmM29tbnBlZSNyZXBvc2l0b3J5aWRfcmVwb19jdnN5MmFteXZ1Z25uNndvdGZrb2Y1dmZlejZyIiwiR1NJMlNLIjoiJHRhZ18xI3VwZGF0ZWRhdF8yMDI2LTA2LTMwdDExOjU1OjI0LjU1MHojdGFnX3Y3In0 Vercel CLI 54.18.6 (Node.js 20.18.0) Tag Image ID Digest Arch Size Created v5.5 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago > More results available. Re-run with `--cursor eyJTSyI6IiR0YWdfMSN0YWdfdjUuNSIsIkdTSTJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJHU0kyU0siOiIkdGFnXzEjdXBkYXRlZGF0XzIwMjYtMDYtMjZ0MTQ6MjI6MTAuMDI3eiN0YWdfdjUuNSIsIlBLIjoiJHZjciNwcm9qZWN0aWRfcHJqX3U0eXl6ZDN6NWZydGVobnR5Y2U1ZjNvbW5wZWUjcmVwb3NpdG9yeWlkX3JlcG9fY3ZzeTJhbXl2dWdubjZ3b3Rma29mNXZmZXo2ciJ9`. ❯ vercel vcr tag ls test1 --limit 5 --sort-order desc Vercel CLI 54.18.6 (Node.js 20.18.0) Tag Image ID Digest Arch Size Created latest image_DIjo4083F2hnFlVzlcJdPGjO90FA b9610c5988ab amd64 36.9MB 6d ago v7 image_XvGyahtJG2AaPKROJJtLe2nlpYR0 776e8c66121f amd64 36.9MB 2d ago v5.5 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago v5.4 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago v5.3 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago v5.2 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 6d ago > More results available. Re-run with `--cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJHU0kyU0siOiIkdGFnXzEjdXBkYXRlZGF0XzIwMjYtMDYtMjZ0MTQ6MjI6MDguMTc0eiN0YWdfdjUuMiIsIkdTSTJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJTSyI6IiR0YWdfMSN0YWdfdjUuMiJ9`. ❯ vercel vcr tag ls test1 --limit 5 --sort-order asc Vercel CLI 54.18.6 (Node.js 20.18.0) Tag Image ID Digest Arch Size Created latest image_DIjo4083F2hnFlVzlcJdPGjO90FA b9610c5988ab amd64 36.9MB 6d ago v1 image_FoJbt52zZg4ND3e4Xo8kk2688P3l 3e708d77c9c7 amd64 - 9d ago v2 image_FoJbt52zZg4ND3e4Xo8kk2688P3l 3e708d77c9c7 amd64 - 9d ago v3 image_FoJbt52zZg4ND3e4Xo8kk2688P3l 3e708d77c9c7 amd64 - 9d ago v4 image_uMBM8wuJiiO2XC15MM0ereV99C6D a5041998de1a amd64 - 8d ago v5 image_KjcPZI0Zsan7pJCA3a6ZBPzsC03z 77a23d461dcb amd64 - 8d ago > More results available. Re-run with `--cursor eyJQSyI6IiR2Y3IjcHJvamVjdGlkX3Byal91NHl5emQzejVmcnRlaG50eWNlNWYzb21ucGVlI3JlcG9zaXRvcnlpZF9yZXBvX2N2c3kyYW15dnVnbm42d290ZmtvZjV2ZmV6NnIiLCJHU0kyUEsiOiIkdmNyI3Byb2plY3RpZF9wcmpfdTR5eXpkM3o1ZnJ0ZWhudHljZTVmM29tbnBlZSNyZXBvc2l0b3J5aWRfcmVwb19jdnN5MmFteXZ1Z25uNndvdGZrb2Y1dmZlejZyIiwiR1NJMlNLIjoiJHRhZ18xI3VwZGF0ZWRhdF8yMDI2LTA2LTI1dDEyOjA2OjIzLjAwMnojdGFnX3Y1IiwiU0siOiIkdGFnXzEjdGFnX3Y1In0`. ``` vercel vcr tag inspect (alias: `get`) --- Show details for a single tag - `-p, --project` - `-F, --format` Example: ``` ❯ vercel vcr tag inspect test1 latest Vercel CLI 54.18.6 (Node.js 20.18.0) > Tag latest ID image_DIjo4083F2hnFlVzlcJdPGjO90FA Digest sha256:b9610c5988ab5bde170d2097e9919d85374b94f71b5da3dfc54e2d2fb84c0292 Image vcr.vercel.com/marc-codina-enhanced-vtest314/my-sandbox-app/test1:latest Type manifest Arch amd64 Platform linux Size 36.9MB Status Ready Created 6d ago ``` vercel vcr image ls (alias: `list`) --- List images in a repository - `-p, --project` - `--untagged` — Only list images with no tags - `--limit` - `-c, --cursor` - `-F, --format` Example: ``` ❯ vercel vcr image ls test-multi-arch Vercel CLI 54.18.6 (Node.js 20.18.0) Image ID Digest Tags Type Status Arch Size Created image_XTPv9FRCWob68TkdGMUHC9vCXIAz b5d4d203118e v2-multi Image Ready (unoptimized) arm64 - 9d ago image_cTYQi67CmZRrEcfcN1AoyFWz5uqp ee86c2a4150c v1-multi Index - - - 9d ago image_MyBxVlhU2sqIdqDhj7rgf8GomXXX d133e81440a1 <none> Image Ready amd64 - 9d ago image_M9GocfXxMOlXQMKHadFGcXKyVwws cb2fa5d87cea <none> Image Ready (unoptimized) arm64 - 9d ago ❯ vercel vcr image ls test-multi-arch --untagged Vercel CLI 54.18.6 (Node.js 20.18.0) Image ID Digest Tags Type Status Arch Size Created image_MyBxVlhU2sqIdqDhj7rgf8GomXXX d133e81440a1 <none> Image Ready amd64 - 9d ago image_M9GocfXxMOlXQMKHadFGcXKyVwws cb2fa5d87cea <none> Image Ready (unoptimized) arm64 - 9d ago ``` vercel vcr image inspect (alias: `get`) --- Show details for a single image identified by that tag - `-p, --project` - `-F, --format` Example: ``` ❯ vercel vcr image inspect test-multi-arch image_XTPv9FRCWob68TkdGMUHC9vCXIAz Vercel CLI 54.18.6 (Node.js 20.18.0) > Image image_XTPv9FRCWob68TkdGMUHC9vCXIAz ID image_XTPv9FRCWob68TkdGMUHC9vCXIAz Digest sha256:b5d4d203118e450612633d43d2a7ea590c75864c9d83a4e11f2ff1a28e37269f Image vcr.vercel.com/marc-codina-enhanced-vtest314/my-sandbox-app/test-multi-arch@sha256:b5d4d203118e450612633d43d2a7ea590c75864c9d83a4e11f2ff1a28e37269f Type manifest Arch arm64 Platform linux Size - Status Ready (unoptimized) Created 9d ago Tags v2-multi ``` vercel vcr image rm (aliases: `remove`, `delete`) --- Delete an image from a repository - `-p, --project` - `--yes` - `-F, --format` Example: ``` ❯ vercel vcr image ls test2 Vercel CLI 54.18.6 (Node.js 20.18.0) Image ID Digest Tags Type Status Arch Size Created image_zB8fkwDdBRD4Q3DHT5okMKuc94GT afd01ff13078 v3-multi Index - - - 8d ago image_DIWiDpFcDSh3gyMGQo9Ek4jR5UcD eb09066b7857 <none> Image Ready amd64 - 8d ago image_Ml0PUBaNT8SRrYXDOOEiFedAsAEs 63deb08d9c41 <none> Image Ready (unoptimized) arm64 - 8d ago ❯ vercel vcr image rm test2 image_Ml0PUBaNT8SRrYXDOOEiFedAsAEs Vercel CLI 54.18.6 (Node.js 20.18.0) ? Delete image image_Ml0PUBaNT8SRrYXDOOEiFedAsAEs from test2? This cannot be undone. yes > Success! Image image_Ml0PUBaNT8SRrYXDOOEiFedAsAEs deleted ❯ vercel vcr image ls test2 Vercel CLI 54.18.6 (Node.js 20.18.0) Image ID Digest Tags Type Status Arch Size Created image_zB8fkwDdBRD4Q3DHT5okMKuc94GT afd01ff13078 v3-multi Index - - - 8d ago image_DIWiDpFcDSh3gyMGQo9Ek4jR5UcD eb09066b7857 <none> Image Ready amd64 - 8d ago ``` --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>Marc Codina · 2c877938 · 2026-07-02
- 2.1ETVpython: Replace vercel-workers with the new vercel-queue based impl (#17236) Queue subscribers and workflows in the Python builder are currently served through the original `vercel-workers` implementation. Switch the integration to the new `vercel-queue` SDK while keeping backwards compat. `[[tool.vercel.subscribers]]` entrypoints are now introspected at build time via `vercel.queue.get_subscriptions()` and served through generated `vercel.queue.asgi_app()` handler modules; their `queue/v2beta` triggers carry the SDK-registered consumer groups and per-subscription tuning instead of pyproject-declared values. Projects that depend on `celery` or `dramatiq` get the matching `vercel-celery`/`vercel-dramatiq` integration package injected automatically. `[[tool.vercel.workflows]]` entrypoints pick their serving path by SDK generation: `vercel.workflow` runs on vercel-queue starting with `vercel` 0.8.0, so builds against that version or newer serve workflows exactly like subscribers, while older (or undeterminable) versions keep the legacy vercel-workers serving — worker env markers plus an injected pinned `vercel-workers`. Projects that declare a direct `vercel-workers` dependency opt into the legacy integration wholesale: the legacy subscriber schema, direct entrypoint serving, and worker env markers. Both generations keep emitting subscriber Lambdas under the released `_py_subscribers/...` output paths so deployed consumer-group names stay stable. `vercel dev` follows the same split: new-SDK sidecars are served through `vercel.queue.asgi_app()`, and because vercel-queue dispatches deliveries by the registered (consumer group, topic) pair, the dev queue broker now delivers with the SDK-registered consumer groups, introspected at sidecar startup and reported through the new `queueSubscriptions` field on `StartDevServerResult`. Legacy projects keep the vercel-workers dev bootstrap and injection. The CLI no longer injects `config.hasWorkerServices`; the builder makes all queue-serving decisions from project metadata. No integration tests for the new behavior because `vercel.workers` is still unreleased (this commit needs to land first to ensure bidirectional compatibility). --------- Co-authored-by: Nik <nik.sidnev@vercel.com>Elvis Pranskevichus · 17ee7366 · 2026-07-28
- 1.9ETV[python-runtime] Python WebSockets Support (#15993) - Vendor `wsproto` 1.3.2 so uvicorn can handle WebSocket upgrades - Extend `ASGIMiddleware` to handle `websocket` scope (previously only `http`) - End request at `websocket.accept` to match Node.js detached upgrade flow --------- Co-authored-by: Fantix King <fantix.king@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>Ricardo Gonzalez · fe6d98ba · 2026-06-18
- 1.8ETV[python] Improve bytecode knapsack selection with static analysis (#17333) ## Summary `lambdaKnapsack` picked bytecode by `.pyc` size descending, which maximized bytes placed rather than compile time avoided. Functions near the 225MB lambda limit shipped bytecode that was never imported, falling far short of the speedup we get with full bytecode coverage. ## How it works Selection is now per file, in two tiers: modules the app imports at startup first, ranked by measured compile seconds per byte, then everything else. - New static AST import closure in `@vercel/python-analysis`. No user code runs at build time. Seeded from the entrypoint plus Django settings strings, workers, and workflows; bounded by a 30s timeout. - `compileall` now records per-file compile timings, replacing size as the value proxy. This is used in if the import AST ever fails. - Selection is value-ranked across all package groups. Always-bundled packages no longer get guaranteed capacity ahead of public ones. - New `vc.builder.python.bundle.optimize` span reports bytecode coverage percent, so we can watch selection quality in the field. - Kill switch: `VERCEL_PYTHON_DISABLE_BYTECODE_ANALYSIS=1` reverts selection to size ordering (bytecode still ships). Applies to every fill path. When all bytecode fits, nothing is analyzed. Falls back to density-only, then size, so no build packs worse than before. ## Proof I created a Python-heavy FastAPI app (twilio, hubspot, botocore, elasticsearch, etc) and deployed 10 copies each of the old and new selection algorithm. The old algorithm packed `twilio` and `hubspot` based on size. Much of that was generated models never imported by the app and did not give much of a speedup. The new algorithm: bytecode coverage went from 2 of 17 packages to **15 of 17**, imports are **3.01x faster**, and cold TTFB is **1.98x faster**. --------- Signed-off-by: gscho <greg.c.schofield@gmail.com>Greg Schofield · 08a26185 · 2026-08-03
- 1.8ETVauth: Make it possible to store CLI credentials in OS keychain, take 2 (#16264) Storing credentials in OS keychain is materially safer than plaintext files: - keychains are encrypted at rest by the OS, hence protect from cold-boot attacks; - access to the keychain can be mediated by OS security controls (login context, prompts etc); - credentials are less likely to be exposed by accident (e.g dotfile commits, agent reads etc). Specific changes: CLI credentials storage is made configurable via the new `"credStorage"` global config var or the `VERCEL_TOKEN_STORAGE` environment variable (env > config). Possible values are - `"keyring"` -- store credentials in the system keychain, via `@napi-rs/keyring` which is a Node binding for `keyring-rs`, both of which are widely used (the latter by Codex); - `"file"` -- store credentials in `<config-dir>/auth.json`, which is the current behavior and is still the default; - `"auto"` -- use keyring, if available, otherwise fall back to "file". When credentials are successfully written to a keychain, the previous copy in plaintext file is removed to avoid confusion. Additionally, credentials are auto-migrated on storage changes on read, which would allow us to change the default method in the future without breaking sessions. Unlike the previous take in 24686d0ea, which was reverted, this approach does not add an indirect native dependency to `@vercel/oidc` and uses the CLI as the authentication helper instead for cases when keyring reads are deemed necessary (via `cli-exec`). Note: `getVercelToken()` helper exported by `@vercel/oidc` will not work properly when credentials are not stored in plain text (i.e effective `file` mode).Elvis Pranskevichus · fddeb55f · 2026-06-02
- 1.7ETV[python-analysis] Add requirements.txt parsing via `uv-requirements-txt` (#15498) Add `parse-requirements-txt` WIT export for parsing requirements.txt files into structured data (PEP 508 specifiers, VCS URLs, extras, markers, index URLs, etc.). The upstream uv crate has several dependencies that are either too heavy for WASM or pull in async runtimes. These are satisfied by minimal stub crates (same interface, trivial internals): - `uv-client-stub`: offline-only connectivity (no HTTP client) - `uv-configuration-stub`: --no-binary/--only-binary option types - `uv-distribution-types-stub`: requirement wrapper types - `uv-fs-stub`: path utilities + file reading via host-bridge - `fs-err-stub`: absorbs tokio feature flag without pulling in tokio, (`fs-err` is only used in tests, but Cargo pulls it nonetheless). The host-bridge `read-file` function enables the upstream parser to resolve `-r`/`-c` includes through the WASM host. All async I/O resolves synchronously via the host-bridge, so a single-poll executor (`Waker::noop()`) drives the upstream async API. Also rename current `uv-fs-patch` to `uv-fs-stub` for naming consistency. Before: Binary Overview ─────────────── Total (code+data): 1,721,148 bytes (1.64 MB) Code: 499.5 KB ████████▉ 29.7% Data: 1.15 MB █████████████████████ 70.3% .rodata: 1.13 MB .data+.bss: 25.2 KB Top 10 Crates by Size ───────────────────── total code data % ───────────────────────────────────────────────────────────────────────────────────────────── 1. unicode_names2 823.9 KB 4.8 KB 819.1 KB ████████████████████ 49.0% 2. encoding_rs 169.4 KB 40.6 KB 128.8 KB ████ 10.1% 3. core 134.7 KB 88.9 KB 45.8 KB ███ 8.0% 4. unicode_normalization 111.0 KB 2.2 KB 108.8 KB ██ 6.6% 5. ruff_python_parser 106.7 KB 96.2 KB 10.5 KB ██ 6.3% 6. alloc 55.6 KB 55.3 KB 239 B █ 3.3% 7. data_encoding 43.6 KB 42.6 KB 971 B █ 2.6% 8. vercel_python_analysis 23.8 KB 21.9 KB 2.0 KB 1.4% 9. uv_pypi_types 22.1 KB 20.3 KB 1.8 KB 1.3% 10. std 17.1 KB 13.9 KB 3.1 KB 1.0% After: Binary Overview ─────────────── Total (code+data): 3,227,476 bytes (3.08 MB) Code: 1.43 MB █████████████▉ 46.4% Data: 1.65 MB ████████████████ 53.6% .rodata: 1.54 MB .data+.bss: 115.1 KB Top 10 Crates by Size ───────────────────── total code data % ───────────────────────────────────────────────────────────────────────────────────────────── 1. unicode_names2 823.9 KB 4.8 KB 819.1 KB ████████████████████ 26.1% 2. regex_syntax 420.5 KB 113.0 KB 307.5 KB ██████████ 13.3% 3. core 289.8 KB 240.9 KB 48.8 KB ███████ 9.2% 4. regex_automata 246.7 KB 228.8 KB 17.9 KB █████ 7.8% 5. encoding_rs 169.4 KB 40.6 KB 128.8 KB ████ 5.4% 6. alloc 116.5 KB 116.0 KB 502 B ██ 3.7% 7. unicode_normalization 111.0 KB 2.2 KB 108.8 KB ██ 3.5% 8. ruff_python_parser 106.7 KB 96.2 KB 10.5 KB ██ 3.4% 9. aho_corasick 92.1 KB 84.4 KB 7.7 KB ██ 2.9% 10. icu_normalizer 75.1 KB 6.4 KB 68.7 KB █ 2.4%Elvis Pranskevichus · 3c4355fa · 2026-03-13
- 1.6ETV[CLI] Introducing new VC Link Flow (#16809) this prs introduces: - explicit team selection in TTY and nonTTY - Better searching and matching - escape a session --------- Co-authored-by: Jeff See <jeffsee.55@gmail.com>MelkeyDev · 8f10c0b2 · 2026-07-08
- 1.5ETVcli-exec: Improve and harden project-local CLI lookup (#16683) When looking for vercel CLI in local bin-dir (i.e `node_modules/.bin`), we now: * reject binaries not installed by packages other than `vercel`; * stop traversal at the project boundary; * skip world-writable directories or directories owned by a user other than the euid of the process executing `cli-exec`. Major bump because exported `findVercelCli` is made async here (it being sync was an oversight).Elvis Pranskevichus · 3f216059 · 2026-06-17