Why Vercel Edge?
If I had to bet, I’d wager that Vercel’s Edge Runtime is The Next Big Thing.
That’s because Vercel cleverly built it on top of Cloudflare Workers, which solve the primary problems of serverless… at a price.
Say goodbye to coldstarts. Network latency is lower as well, because workers are deployed across Cloudflare’s global data centers. And each process is so cheap from an infra perspective that Cloudflare can keep their pricing ridiculously low. So even with Vercel’s markup, it’s hard to argue against the cost.
Why NOT Vercel Edge?
Vercel Edge's speed, low latency, and low cost come at a price.
Edge workers are emphatically NOT Node.js compatible.
You might not notice it at first, but eventually you’ll try to deploy something to an Edge function and you’ll get all sorts of “X API is not supported” errors. This happens because every line of code that gets bundled into an Edge function needs to be Edge-compatible. Vercel analyzes your code in search of offending API calls. So even if that incompatible line of code is never hit at runtime, Vercel won’t let you deploy it.
If you absolutely MUST use an incompatible package, you’ll either opt for the full Node.js runtime, or you’ll find yourself patching it locally with patch-package or a command like
yarn patch or
How Highlight Supports Edge
We’ve forked it and made a few crucial edits to remove Edge-incompatible API calls. We’ve published our fork as
@highlight-run/opentelemetry-sdk-workers so we can consume it for
opentelemetry-js has a number of Edge-incompatible API calls, but we’re resisting the urge to fork it. The codebase would be a lot to manage. Instead we’re patching those incompatible API calls using
yarn patch in our CI/CD pipeline and bundling it with great care, such that those patched files get published to NPM as part of
Why is this necessary?
Serverless functions shut down the moment the thread frees up. If you’re not waiting for an async process or actively running a command, you can expect your Node.js or Edge worker to abort prematurely.
On the flip side, opentelemetry-js (OTEL for short) assumes a standard, always-up Node.js runtime. Because it is built for a express.js-like server-based environment, it is designed around a paradigm of background asynchronous data export. It doesn’t “await” its flushed spans. As a result, during our testing, a majority of our errors never got sent to Highlight. We were “awaiting” OTEL’s flush function, but the promise would resolve and the process would shut down while OTEL was still queuing up its call to Highlight’s servers.
Fortunately for us, TypeScript doesn’t ACTUALLY make a class’s internals private. Sure, you can label attributes as
private, but once that code is bundled, we can
//@ts-ignore the line and steal that internal data. Which is exactly what we do. We peer into OTEL’s internals and wait for all of its Fetch calls to complete before releasing the serverless process. The internals that we’re relying on are old, stable code that’s unlikely to change in the next year or two.
@highlight-run/next currently relies on manual API endpoint wrapping. You’ll use functions like
EdgeHighlight to wrap your API endpoints.
To simplify instrumentation, an alternative approach could be to use the
next.config.js to auto-wrap endpoints. We’d be excited to implement something of this sort if it weren’t also incredibly complicated and error-prone. A potential implementation would use Rollup and static analysis to generate new endpoints, wrap them and replace your existing code as part of Next.js’s compilation step. As you can imagine, however, this will require quite a bit of validation to make mature.
The other option is to publish a codemod to edit your codebase directly. You’d commit your newly-wrapped API endpoints to your repository. No magic. Of course, you’d have to re-run the codemod after adding new endpoints. Or you could manually wrap them going forward. We’ll see how
@highlight-run/next adoption goes and consider writing the codemod once the community is happy with it.
Other articles you may like
Oct 17, 2023 • 14 min. read
Dec 8, 2022 • 6 min. read
Aug 1, 2022 • 4 min. read