Skip to main content
Compute is in preview, and the v1alpha API can change.
This guide moves a Node server-rendered app from Vercel to a Compute workload on the general-purpose runtime. When you finish, your app runs as a container with its secrets, a public URL, a rollback path, and deploys from CI.

How Vercel concepts map to Compute

Before you begin

  • Install datumctl and the compute plugin, and log in. For more information, see Compute commands.
  • Enable Compute for your project. Compute turns on the first time you run a datumctl compute command in the project. For more information, see Limits and quotas.
  • Use an app that runs as a long-lived Node server. Your framework needs a server build, not a Vercel-only build output.
  • Choose a place to push images. For a private registry, see Use images from a private registry.

Migrate the app

1

Containerize the app

Vercel builds your app for you. On Compute, you provide the image. The following Dockerfile builds an Astro app with the Node adapter. Adjust the build output paths and the CMD for your framework:
Follow these rules:
  • Listen on ::, not 0.0.0.0. Instances have IPv6 addresses only. An app bound to IPv4 starts but never answers. Make your server read the host from an environment variable, as HOST does here.
  • Serve plain HTTP on one port. The load balancer terminates TLS. You pass the port as --http-port when you deploy.
  • Keep secrets out of the image. Add .env* to .dockerignore. Secrets arrive at runtime from a Secret.
  • Tag every build with a new, unique tag. Datum doesn’t replace an Instance when the image tag is unchanged, so a moved tag does nothing.
Build and push the image. On Apple Silicon, build for linux/amd64:
A new GitHub Container Registry package is private, and Datum pulls without credentials unless you configure a pull Secret. Either make the package public in the GitHub package settings, or follow the private registry steps in Configuration.
2

Move your environment variables into a Secret

Export the variables from Vercel. Save the file outside your repository, and never paste its contents into a chat:
Vercel never exports sensitive variables. For a variable of type Sensitive, vercel env pull writes the literal text [SENSITIVE]. It looks like a real value, so it ends up in your Secret. Get these values from the original provider, or generate a new value where only your app has to match it. Run vercel env ls to see which variables are Sensitive.
Drop the Vercel-only variables, such as VERCEL, VERCEL_URL, and VERCEL_ENV. If your code reads them, replace them with your own variables.Create a Secret named APP-secrets in the default namespace, with one key for each variable. For the steps, see Secrets. Create it with datumctl apply, then check for leftover Vercel placeholders. The following command prints key names only, never values:
3

Deploy the workload

Run the command from a folder outside your repository. It writes a workload.yaml file into the current folder, which you shouldn’t commit:
The last line of the output is the public URL. For the locations that your project can use, see Placement and scaling.Use general-purpose for a standard container image. The unikernel runtime needs datumctl compute build instead of docker build. A workload keeps its runtime class. To change it, deploy under a new name and destroy the old workload.
4

Verify before you switch traffic

Watch the rollout and read the app’s output:
While a rollout runs, the edge can return an HTML error page instead of your app. Poll a health route until it returns 200 before you judge the result.A new *.datumproxy.net hostname might not resolve on your machine right away. Look it up through a public resolver and pin the address:
Compare the app with Vercel page by page: key routes, data from your CMS or API, forms, sign-in, and anything that calls a third party. Test login-protected pages and email forms yourself.
5

Switch your domain

Attach your hostname to the load balancer. For the full flow, including domain verification, see Custom domains:
If Datum runs your domain’s DNS, attaching a hostname writes the record and takes over that name. Check what the name points to today before you attach it. For apex domains and other records, see Point a domain at a load balancer.Before and after you switch, keep these points in mind:
  • Keep the Vercel project until you’re sure. Pointing DNS back at Vercel is your fallback.
  • Build with the final domain. If your app builds absolute URLs, sitemaps, or canonical links at build time, build the image with the production domain.
  • Keep search indexing off on the *.datumproxy.net URL. Otherwise the staging copy is indexed as a duplicate of your site. If your app has an “allow indexing” setting, turn it off in the Secret and turn it on at cutover.
  • Don’t change the framework adapter on a branch that Vercel deploys. Merging an adapter change, such as @astrojs/vercel to @astrojs/node, to the branch that Vercel watches breaks Vercel and your rollback path. Keep the change on a separate branch until DNS has moved.
6

Deploy from CI

Vercel deploys on every push. On Compute, build and push the image in your pipeline, then run datumctl compute deploy with the new tag. Log in as a service account. For the workflow, see GitHub Actions, and for service accounts, see Service accounts.A common pattern is a push to main that deploys staging, and a published release that deploys production with the release tag. Don’t run destroy in the pipeline, because it removes the URL and the load balancer settings.

Roll back and update

To roll back, redeploy the last good tag. The image is already in the registry, so nothing is rebuilt:
Don’t re-tag an image to roll back. Treat tags as immutable. To fix the bug for good, revert the change and publish a new, higher version.
A flag-based datumctl compute deploy replaces the workload’s whole template and placements with what the flags describe. Pass --http-port and your other flags again on every deploy. For what the command keeps and removes, see Configuration.
Instances read a Secret only when they start. After you change a Secret, restart the workload:

Protect the app with basic authentication

Vercel password protection maps to basic authentication on the load balancer. Run the following command and type the password when prompted:
Basic authentication protects every route on the load balancer, including health routes, and webhooks that call the URL get 401. To protect a single route, use a SecurityPolicy. For both methods, see Basic authentication.

Replace Vercel-only features

Check each feature that your app uses. The examples use Astro and Node, and the same pattern applies to other frameworks.
For rate limiting, use the rightmost X-Forwarded-For entry as the client address. The Datum edge appends the real client IP there, and the leftmost entries are client-controlled. The framework’s own client address is an internal address, so don’t use it.

Plan for these gaps

  • Preview URLs for each branch aren’t available.
  • Vercel-managed features such as Edge and Serverless Functions, ISR and its cache, Analytics, and Web Vitals have no direct equivalent. Check each one that your app uses.
  • With more than one replica, the cache and any in-memory state are no longer shared. Add a shared store before you scale out.
  • Use scoped tokens in the Secret, not personal ones, before you move real traffic.

Troubleshooting

For other problems, see Compute troubleshooting.

Clean up

To remove the workload and its URL, run the following command. The Secret stays:
Last modified on November 9, 2026