Skip to content
Docs

How to migrate from Railway to Vercel

Move an app from Railway to Vercel. Most Railpack-built apps deploy through framework detection with no container; Dockerfile apps move as Dockerfile.vercel. Map railway.json to vercel.json and cut over safely.

Ben SabicContent Engineer

To migrate from Railway to Vercel, pick your build path first: apps that Railway built with Railpack or Nixpacks usually deploy on Vercel through framework detection with no container at all, while apps built from a Dockerfile move by renaming it to Dockerfile.vercel. Either way, Vercel builds on every commit and serves the app with automatic scaling. Configuration moves from railway.json and dashboard variables to vercel.json and project environment variables, and stateful pieces such as Railway volumes and databases move to external backing services.

This guide maps each Railway concept to its Vercel equivalent, walks through the migration, and is direct about what doesn't carry over.

Copy link to headingShould your app move?

Vercel runs applications as stateless HTTP services, whether framework-built or containerized. Three questions decide the fit:

  • Does the app serve HTTP and keep no state between requests? Sessions, uploads, and caches must live in a backing service, not on a Railway volume or in process memory.
  • Does it tolerate scale-to-zero? If you already run Railway's app with sleeping enabled, the model is familiar: instances scale down when idle and back up when traffic increases. On Vercel this behavior is automatic rather than opt-in.
  • Is it request-driven? Always-on background workers and queue consumers have no equivalent. Scheduled work does: Railway cron schedules map to Vercel cron jobs, covered in step 6.

Copy link to headingHow Railway concepts map to Vercel

RailwayVercel
railway.json / railway.tomlvercel.json
Railpack or Nixpacks builderFramework detection, zero configuration
builder: DOCKERFILE with dockerfilePathDockerfile.vercel, or entrypoint per service
startCommandCMD / ENTRYPOINT in the image
Injected PORT variablePORT environment variable in project settings, default 80
railway upgit push, or vercel deploy from the CLI
PR environmentsPreview deployments, on by default for every commit
Service variables and reference variablesProject environment variables, plus auto-generated cross-service variables
A project with several servicesOne Vercel project with services routed by rewrites
App sleeping (opt-in)Automatic scale-in after 5 minutes idle in production, 30 seconds in preview
Cron schedulesVercel cron jobs in vercel.json
VolumesExternal storage: databases, caches, or blob storage
preDeployCommandCI step before deploy

If you are still choosing a destination, compare Railway alternatives by application need before moving the web app or its data.

Copy link to headingSteps

Copy link to heading1. Pick your build path

Railway offers two ways to build, and each has a different destination on Vercel:

If Railway built your app with Railpack or Nixpacks, you likely don't need a container. Vercel's framework detection recognizes over 35 frameworks and configures builds automatically, which is the platform's preferred path. Import the repository and check whether detection picks the app up; a Next.js, Nuxt, SvelteKit, Astro, or similar app deploys with zero configuration, and startCommand becomes unnecessary because the framework preset handles startup.

If Railway built from a Dockerfile, or your app isn't a detected framework, copy the Dockerfile to Dockerfile.vercel at the project root. Vercel detects it, builds the image on every commit, pushes it to Vercel Container Registry, and serves it on Fluid compute with Active CPU pricing. If your railway.json pointed at a non-standard path with dockerfilePath, that path moves to the service entrypoint in vercel.json. If Railway built your app from source but it isn't a framework Vercel detects, such as a plain Express or Flask server, this is the one case where migrating means writing a Dockerfile you didn't have: a few lines that install dependencies and start the server on PORT.

Either way, the port contract is the same one Railway taught you: the server reads the PORT environment variable. On Vercel it defaults to 80, and you can change it in project settings to match a hardcoded port; don't rely on an ENV PORT line in the image to change where traffic routes.

Copy link to heading2. Move the start command into the image

Railway lets startCommand in railway.json override how the container starts. Vercel runs the image as built, so anything in startCommand belongs in the Dockerfile's CMD or ENTRYPOINT. If your startCommand chained setup work before the server, such as db:migrate && server, split it: the server start goes in the image, and the migration moves to CI (step 5).

Copy link to heading3. Move configuration and variables

Recreate Railway's service variables as environment variables in your Vercel project settings, marking secrets as sensitive. Railway's reference variables, which share values between services in a project, map to Vercel's auto-generated cross-service environment variables: when you define multiple services, Vercel creates the variables each service needs to call the others, so URLs aren't hardcoded on either platform.

railway.json settings that configured the platform rather than the app have no destination: restartPolicyType and healthcheckTimeout are managed by the platform, and there's no healthcheckPath equivalent for containers, so validate deployments on their preview URLs instead.

Copy link to heading4. Move state out of the app

  • Railway Postgres, MySQL, or Redis move to managed equivalents, such as services from the Vercel Marketplace, and the connection string becomes an environment variable. Export from Railway with standard tooling such as pg_dump, and import on the new host.
  • Volumes have no equivalent. Files an app writes to a volume move to blob storage; anything else that must survive restarts moves to a database or cache.
  • In-process state such as sessions moves to a managed cache.

Copy link to heading5. Replace preDeployCommand with a CI step

Railway runs preDeployCommand before each deployment goes live, most often for database migrations. Vercel has no deploy-time hook for containers, so run migrations from CI before the deploy, or as a separate pipeline step. This is also where any setup you removed from startCommand in step 2 belongs.

Copy link to heading6. Recreate cron schedules

Railway cron schedules run a service on a timer. On Vercel, cron jobs defined in vercel.json invoke an HTTP endpoint on a schedule, so a Railway cron service becomes a route in your app that performs the work when called. The scheduled task must fit the request model: it runs when invoked and finishes within function duration limits, rather than running as a standalone process.

Copy link to heading7. Verify and cut over

Railway's PR environments have a direct counterpart: every commit to a Vercel project gets a preview deployment with its own URL, no configuration required. Test the app on preview URLs against production backing services in read-only paths first, then shift traffic by updating DNS. Keep the Railway services running until Vercel serves production traffic cleanly, then remove them. For container apps, vercel dev runs the image locally with your Docker daemon, so behavior differences reproduce on your machine rather than in production.

Copy link to headingWhat doesn't map from Railway

  • Volumes. No attached persistent disk exists. Data on volumes must move to external storage before migrating.
  • Always-on workers. Background processes that aren't request-driven don't fit. Restructure them around HTTP invocation, keep them on Railway, or use cron jobs where a schedule fits.
  • preDeployCommand. No deploy hook; migrations belong in CI.
  • healthcheckPath. There's no container health-check configuration; preview deployments are where you validate before traffic shifts.
  • Two networking features. Secure Compute and Static IPs aren't supported with custom container images yet. If external services allowlist your Railway egress today, plan around that.

Copy link to headingFrequently asked questions

Copy link to headingDo I need a Dockerfile to move from Railway to Vercel?

Only if you had one on Railway, or your app isn't a framework Vercel detects. Apps that Railway built with Railpack or Nixpacks usually deploy through Vercel's framework detection with zero configuration. Everything else moves with a Dockerfile.vercel.

Copy link to headingWhat replaces railway.json on Vercel?

vercel.json covers routing, services, and cron jobs, while build settings come from framework detection or the Dockerfile, and runtime settings such as PORT live in project environment variables. Settings like restartPolicyType and healthcheckTimeout have no equivalent because the platform manages instances.

Copy link to headingWhat happens to my Railway Postgres?

It moves to a managed database, such as one from the Vercel Marketplace. Export with standard tooling like pg_dump, import on the new host, and update the connection string environment variable. Databases don't run on Vercel itself.

Copy link to headingDo I keep PR environments?

Yes, and without setup. Vercel creates a preview deployment with its own URL for every commit by default, which covers what Railway's PR environments provide.

Copy link to headingHow does pricing compare to Railway's usage-based model?

Both platforms bill on usage rather than fixed instances, so the model is familiar. On Vercel, containerized apps run as Vercel Functions with Active CPU pricing: cost follows the CPU time your code uses, and idle instances scale to zero automatically rather than as an opt-in.

More Vercel Services guides