Every request Vercel's CDN handles triggers routing work that averages more than 80 million instructions per second. Some of that work is metadata lookup: before the CDN can serve a response, it has to know which target paths exist and how each one should be served. When the needed metadata isn't cached, it must be fetched first — and on large, frequently deployed sites, that fetch was happening far too often.

The cost of one-path-at-a-time metadata

Routing rules disconnect the request path from the path of the content or function that answers it. /blog/hello-world may map to the dynamic route /blog/[slug], and a request for that page's React Server Component payload may map to /blog/[slug].rsc. Resolving a single request can therefore require checking several target paths.

Frameworks declare this structure at build time through framework-defined infrastructure: application code states which outputs are static, which need Functions, and which responses are cacheable or regenerable. Those declarations become Build Output API outputs, from which Vercel generates the routing metadata the CDN reads. At request time, Bloom filters in global routing eliminate paths that definitely don't exist; whatever remains needs an exact metadata lookup.

The original design stored metadata as one object per target path, fetched and cached independently. Each new deployment produced a new set of cache keys, so the first lookup for every path was a miss. That was tolerable for small projects deploying rarely, but large deployments can hold hundreds of thousands of paths, and frequent deploys made cache misses a standing cost.

Bundling paths into shards

The fix was to collect metadata for many paths into a single file, called a shard, with a size bound so a lookup never transfers more than it should. Fetching one shard populates the cache for every path assigned to it.

A per-path cache fill warms one path. A shard fill warms every path assigned to that shard. A per-path cache fill warms one path. A shard fill warms every path assigned to that shard.

An index inside each shard lets the CDN jump to a single path's record without decoding, decompressing, or parsing the other entries. A fetch warms many paths; a lookup still parses only the record it needs.

Per-path lookups needed a dependent HEAD and GET, while the new path fetches one bounded shard after the Bloom filter check and looks the path up locally. Per-path lookups needed a dependent HEAD and GET, while the new path fetches one bounded shard after the Bloom filter check and looks the path up locally.

Layout: JSONL, offsets, and Base64 pointers

Shards reuse JSONL layouts already used for other large routing datasets at Vercel, combining the sorted alternating key-value records from Bulk Redirects with directly addressable Base64 structures first built for the Bloom filters. The layout stays decoupled from the search structures above it, so each workload can take only the properties it needs:

  • Inspectable, sorted key-value JSONL records with random access
  • Optional inline indexes for low-overhead binary search
  • Embedded Base64 data with offset-based decoding
  • Bounded shards that control transfer and cache costs

Inside a shard, sorted target paths and their metadata are stored as alternating JSONL records. An inline index records the start position of each entry as a fixed-width pointer. Every pointer is a whole number of six-bit Base64 characters, so a pointer can be decoded in place — no parsing of the index line as JSON and no decoding of the full Base64 string.

The routing process binary-searches the encoded paths using build-time byte offsets, then parses only the matching JSON value. The routing process binary-searches the encoded paths using build-time byte offsets, then parses only the matching JSON value.

Selecting the shard costs nothing extra: as with Bulk Redirects, the first metadata fetch for a deployment already identifies which shard holds a given path. Within the shard, the routing process binary-searches the encoded paths via the index pointers, taking O(log n) pointer reads and string comparisons, then parses the metadata value on the next line. The remainder of the shard stays unparsed.

Choosing a shard size against real cache behavior

The initial assumption was that most deployments' path metadata would fit in one shard, and since indexing and binary search kept parsing cheap, the first shards were multi-megabyte. That trade only pays off if the shards stay cached near the request. Each routing process keeps a small least-recently-used (LRU) cache of recent shards in memory, backed by a larger cache shared region-wide. With few shards per deployment, LRU hits were expected to dominate and offset the cost of transferring large files.

Testing showed the opposite split: the regional cache hit rate was high, but the LRU hit rate was low, because requests spread across many processes per region. Transferring multi-megabyte shards also proved more expensive than anticipated.

Large shards made LRU misses too slow, while tiny shards made regional misses too common. Production testing found a practical balance at approximately 200 KB. Large shards made LRU misses too slow, while tiny shards made regional misses too common. Production testing found a practical balance at approximately 200 KB.

Shards of about 200 KB struck the balance — regional hit rate stayed high, and LRU misses became cheap to fill. Production measurements showed lower average and P99 lookup latency:

Metadata lookup metric

Before: per-path metadata

After: indexed shards

Improvement

P99 latency

215.8 ms

19.1 ms

91% lower

Average latency

8.59 ms

1.81 ms

79% lower

Standard deviation

44.9 ms

19.0 ms

58% lower

The compaction work we skipped

Fewer entries per shard would lower transfer cost, but at the price of a higher shard count. We also evaluated compacting entries without changing the shard count, testing three encodings:

  • Front-coding sorted paths so each stores only its difference from the previous one
  • Splitting a shard into JSONL documents that deduplicate metadata
  • A custom serialization format with a smaller footprint

Offline simulations measured encoded size and lookup cost for each. All three shrank shards substantially, but predicted only modest latency gains, so the encoding, compatibility, and rollout effort did not justify the migration. If a future workload makes more indexing or compression worthwhile, it will land in the shared library.

Rolling out a correctness-critical lookup safely

This lookup runs on requests to every deployment. If the sharded metadata ever disagreed with the per-path metadata, the result could be a stale route, a wrong status code, or a 404 on a path that exists. We checked for that divergence offline first, using a harness that built test deployments and looked up every path both ways, comparing the answers.

In production, behind a feature flag, the routing system performed both lookups on a random share of requests while still serving the old result, comparing the new answer against the old one in the background. We watched this shadow mode for several weeks without slowing production requests.

Mismatches turned up, and they were extremely rare. One was a bug in the old encoding, which packed paths into RFC 2047 encoded words to fit non-ASCII text into ASCII-only fields; it surfaced only when an emoji was split across two words. The new format stores paths as plain UTF-8, where that bug cannot occur. Catching that edge case raised confidence in the comparison, and the shards began serving production traffic.

Build savings unlocked by the new path

With shards in production, the build pipeline dropped work they made redundant:

  • Skipping the per-path metadata upload saves about 9.7 seconds.
  • Writing route group metadata into the manifest saves about 4.5 seconds.
  • Not uploading the files those two changes left empty saves about 2.4 seconds.

Together those cuts save roughly 16.6 seconds. Across all deployments the deploy step is about 10% faster; for metadata-heavy deployments, where these steps dominate, we estimate closer to 25%.

Results and availability

Faster metadata lookups improved route resolution overall: for large sites, P99 route resolution is now roughly twice as fast. On Vercel's own marketing and docs sites, P99 metadata lookup latency fell from 203 ms to 31 ms, while median lookup latency stayed around 0.7 ms.

Indexed-shard deployments measured 19.1 ms P99 path-metadata lookup latency, versus 215.8 ms for legacy-format deployments in the same production window. Indexed-shard deployments measured 19.1 ms P99 path-metadata lookup latency, versus 215.8 ms for legacy-format deployments in the same production window.

The application-facing Build Output API contract is unchanged: frameworks still describe what the application needs, and Vercel changes how the CDN serves it. Deployments built after July 17, 2026 already use the new metadata shards; older deployments need a redeploy to pick up the faster lookups.