Docs
Get Started

This is the one migration that starts with a question rather than a checklist.

Kuberns runs long-running container processes. Vercel runs framework builds, serverless functions, and a static edge network. For a backend, a worker, or a server-rendered application that wants to stay up, that difference works in your favour. For a project built around edge execution and provider-specific features, some of it should probably stay where it is.

So the first job is deciding what moves. Do that before you create anything.

Start with an assessment

Answer these about your project:

  1. Does it need a process that stays up? Background jobs, websockets, long requests, in-memory state, a queue consumer. If yes, Kuberns is a natural home for it.
  2. How much of it is serverless-specific? Edge middleware, edge-runtime routes, and anything relying on per-request isolation behaves differently on a single long-running server.
  3. Where does your data already live? Most Vercel projects use an external managed database. If yours does, there may be no data migration at all.
  4. Do you depend on Vercel product features? Image optimization, their cron, their analytics, and their storage integrations are platform features, not portable code.
  5. Who consumes your static frontend? A marketing site served from an edge network is not obviously better off on a container.

Three honest outcomes

Most teams land in one of these, and it is worth naming yours out loud.

Move everything. A server-rendered application with jobs, a database, and no edge dependency. This is the common case for backends and full-stack applications, and the rest of this page is written for it.

Split it. Backend, workers, and data services move to Kuberns; the static or edge-heavy frontend stays on Vercel and calls the new API. This is a legitimate destination, not a failed migration.

Stay. A purely static site, or an application built specifically around edge execution, gains little. Kuberns is a poor fit for that, and saying so early saves a week.

What maps directly

On Vercel On Kuberns
Project A service inside a project
Production branch An environment
Preview deployments Additional environments, one per branch rather than per pull request
Framework preset and build Detected by the AI agent
Environment variables per environment Environment variables, scoped per environment
External database integration Keep it as-is, or move to a managed datastore
Custom domains Custom domains with automatic SSL
Runtime logs The environment's logs

What does not move

  • Edge middleware and edge-runtime routes. These need to run on the Node runtime instead. Middleware usually still works as ordinary server code; anything relying on edge-specific APIs does not.
  • Serverless function semantics. On Kuberns your code runs in one continuous process. Anything that assumed a fresh isolate per request, or used the filesystem as scratch space between invocations, needs review.
  • Provider image optimization. This is a platform feature. It needs a library, an external service, or pre-built images.
  • Vercel Cron. Scheduled work becomes an in-application scheduler inside a worker, or stays external.
  • Preview deployments per pull request. Kuberns environments are branch-based. You get preview environments, but per branch rather than per PR.

Before you start

Collect:

  • The repository, the production branch, and the root directory if it is a monorepo.
  • Every environment variable, for all three Vercel environments. They differ, and the differences matter.
  • Your build command and output directory.
  • The database and any storage integrations, with their connection strings.
  • Custom domains and their current TTLs.
  • Your cron schedules.

Do not remove the Vercel project. It is your rollback until Step 6 is verified.

Step 1: Prepare a long-running start command

This is the one code-level change most Vercel projects need. Your application must start a server that stays up and listens on the port Kuberns provides.

web: next start -p $PORT

The exact command depends on your framework, but the shape is the same: a production server that runs continuously and reads its port from the environment rather than hard-coding one.

Confirm this works locally before going further. Build the application, run the production start command, and load it in a browser. If that does not work on your machine, it will not work on Kuberns.

Step 2: Connect the repository

Create the service from your Git provider and select your production branch. Deploy it as a non-production environment first, on the Kuberns-provided URL. Your live Vercel deployment is unaffected.

The Kuberns onboarding step that chooses a deployment type: Connect Custom Repository beside Use Open source Templates, with Select Your Repository active in the sidebar

For a monorepo, note the root directory before you start.

Step 3: Check what the agent detected

The agent reports the framework, root directory, dependency file, base image, web port, build commands, and process commands.

The Kuberns AI agent analyzing a repository: live detection log on the left, and the Setup, Analyze Repository, Configure Env, Build, and Deploy phase stepper on the right

Two fields deserve a second look on a Vercel migration:

  • Web port. Your process must listen on the port the agent reports.
  • The start command. Detection may propose a build-and-serve command rather than the production server command from Step 1. Correct it here.

See agent failures if the result is wrong.

Step 4: Recreate variables and provision resources

Add your environment variables, matching key names exactly, including case. Take them from your Vercel Production environment, not Development.

Two things to watch:

  1. Build-time versus runtime variables. Framework-prefixed public variables are baked in at build time. If one changes, a redeploy is required, not just a variable update.
  2. Integration-injected values. Anything a Vercel integration supplied automatically will not be in your own variable list. Collect those from the integration.

The environment's Environment Variables tab listing DATABASE_URL, REDIS_URL, CELERY_BROKER_URL, and CELERY_RESULT_BACKEND, with every value masked

If you are keeping an external database, your existing connection string carries over unchanged and there is nothing to migrate. If you are moving the database onto Kuberns, create it from the environment's Resources tab.

The environment's Resources tab listing a SERVER, a BACKGROUND WORKER running a celery-start command, a POSTGRES database, and a redis queue, each with its plan, memory, and storage

Connection details for a managed database live on its datastore overview page. If you are importing data, load your dump with the standard client for that database, as described in the Heroku guide. Kuberns does not restore a dump into a running datastore for you.

Environment variables apply on the next deploy, and saving them triggers one automatically.

Step 5: Validate before cutting over

Work through the test environment on its Kuberns URL.

  • The application boots and stays up. A process that exits after responding is the classic serverless-to-container failure.
  • Server-rendered pages, API routes, and any middleware behave as they did.
  • Scheduled work now actually fires, wherever you moved it.
  • Static assets and images load.
  • Outbound integrations and webhooks reach the new environment.

The environment's Logs tab streaming logs for the web process, each line showing a timestamp, level, source, and message

Watch memory as well as correctness. A continuous process accumulates what a fresh isolate per request used to discard.

Step 6: Move the domain

Lower your DNS TTL a day ahead, to something short such as 300 seconds, and wait for the old TTL to expire. Rollback speed is set entirely by that decision.

Then add the hostname under the environment's Custom Domains and point DNS at the target Kuberns shows you.

Subdomain   CNAME  app    -> <Kuberns hostname shown in the dashboard>
Root domain A      @      -> <server IP shown in the dashboard>

The Domains tab before a custom domain is added: the default kuberns.site URL marked Active, an empty custom-domain list, and the Add Custom Domain button

The domain moves through DNS verification, SSL provisioning, and activation. See DNS, SSL, and activation if it stalls.

Rollback

Keep the Vercel project deployed until you are confident. With a short TTL, rolling back is pointing DNS back at Vercel.

If you kept your database external, rollback stays clean for as long as both platforms can reach it, which is a real advantage of the split approach.

Common problems

The process starts and then exits. The start command builds or renders and finishes instead of serving. It needs to be a production server that stays up.

The application is unreachable although the deploy succeeded. It is listening on a hard-coded port instead of the one the environment provides.

A public variable has the wrong value. Build-time variables are baked in at build. Redeploy rather than only updating the value.

Middleware behaves differently. It was running on the edge runtime and is now ordinary server code. Edge-specific APIs need replacing.

Images are unoptimized or failing. Provider image optimization does not migrate and needs a library or external service.

Scheduled jobs never run. Vercel Cron is platform configuration and does not travel with the repository.