12/22/22

Full-stack Preview Environments for speed and confidence

Simple, real-world testing of end-to-end changes with full-stack environments for each PR

5 Min Read

Ever ship a new feature, confident with all the tests passing, only to see it go up in flames, like a birthday cake made of jet fuel? "It's not my code!", you shout in disbelief. "The backend has 100% test coverage!" You blame the frontend (in a blameless retrospective sort of way, naturally). Unfortunately for you the frontend is equally well-tested and everything's been triple-checked. So where's the problem? In the integration between frontend and backend, most likely.

Bugs love to hide at the boundaries between systems. This hurts quality and slows us down: shipping with speed is directly downstream of shipping with confidence. Confidence in the whole — not false confidence from testing a part in isolation. And as we leverage more and more cloud infrastructure in our applications, we need confidence we're actually testing The Real Thing and not just our infrastructure mocks.

Preview Environments to the rescue

Using tools like Vercel, frontend developers have enjoyed Preview Environments for several years now. They've become an indispensable part of quickly gaining real-world confidence in changes, by providing environments virtually identical to production for each Pull Request.

On the backend side it's been bleak. It's difficult to spin up a Preview Environment when a cache takes 20+ minutes to provision, or when your Terraform scripts are so complex you'd rather put your faith in the tooth fairy than trust the production deploy will go without a hitch.

This is the part where we would normally tell you "oh you know that problem we've been talking about this whole time? It's not a problem if you use our amazing product because reasons". Except it's not like that: the problem of gaining confidence in software changes is in many ways the fundamental speed limit on Developer Productivity. We'll never be rid of it, but we can at least raise it.

Encore does provide automatic Preview Environments for your backend, and more. "How is that possible?", you ask. You didn't ask? Well I'm glad I'm the one writing this blog post and not you. Encore provides an Infrastructure from Code platform that enables backend developers to declaratively express infrastructure needs directly in your application code. We parse all that code and build a large graph of all the infrastructure that's needed to run it.

The beauty of this approach is you only specify the truly important infrastructure needs. The Cloud Primitives, as we call them. By eliding all the cloud infrastructure noise, Encore can set up your infrastructure in a variety of ways depending on the use case.

If that sounds up your alley, this is the link you've been waiting for.

So we now have two different tools — Vercel for frontend, Encore for backend — that can individually set up Preview Environments. Sounds great, right? Not so fast. Remember at the beginning when we talked about how lots of bugs happen at the boundaries between systems? To solve this for real we need to properly, easily, elegantly, effortlessly hook these Preview Environments up together.

The problem is that turned out to be more difficult than we expected.

Previewing a better, full stack-er future

Since backends are stateful, with databases and caches and Pub/Sub messages, Encore creates a dedicated Preview Environment for each Pull Request based on its PR number and keeps it around while the PR is open.

Vercel on the other hand deals in stateless frontends, so their Preview Environments were tied to a single commit, without any information about the PR number. Without it, it was impossible to automatically figure out which backend environment to communicate with. An old GitHub discussion requested this feature but it never went anywhere.

The only thing left to do was to reach out to Vercel, get together and fix these issues. We didn't expect much to come out of it: Vercel's a multi-billion-dollar behemoth with better things to do than entertain our feature requests. Or so we thought.

Guillermo Rauch, Vercel's CEO, immediately understood the problem and the importance of enabling end-to-end full-stack Preview Environments. Within 5 minutes of the call he set up a shared Slack channel, invited the core build & deploy team, and we started discussing how we can reimagine full-stack collaboration across frontend and backend.

Three days later a new environment variable was born: VERCEL_GIT_PULL_REQUEST_ID.

We got to work and immediately added support for this on Encore's side. Starting today Encore's generated clients provide a seamless way to route API calls to a Preview Environment.

Generate a client with encore gen client -e production -o client.ts ${ENCORE_APP_ID} and wire it up:

// Import Encore-generated client import Client, { Environment, PreviewEnv } from "./client"; // Pull out the pull request id (here shown with Next.js syntax): const prID = process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID; // Set up the backend client const baseURL = prID ? PreviewEnv(prID) : Environment("production"); const client = new Client(baseURL); // Exercise for the reader: use client to make API calls

And just like that everything Just Works™. As an example we built a small app for uptime monitoring, deployed with Vercel+Encore. We then added TLS certificate monitoring, across both frontend and backend, in 91 lines of code. The frontend Preview Environment deployed by Vercel talks to the backend Preview Environment deployed by Encore.

This approach means there's finally a seamless way to set up end-to-end Preview Environments, spanning frontend and backend. Whether you're an Encore user or not, this new Vercel feature will help you quickly gain confidence a new feature will work end-to-end, bridging the testing boundary.

End-to-end Preview Environments

From all of us here at Encore, a sincere thanks to Vercel for being incredibly responsive and shipping a small but vital new feature faster than most large companies can blink.

Encore

This blog is presented by Encore, the development platform for building robust type-safe distributed systems with declarative infrastructure.

Like this article?
Get future ones straight to your mailbox.

You can unsubscribe at any time.