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
| Railway | Vercel |
|---|---|
railway.json / railway.toml | vercel.json |
| Railpack or Nixpacks builder | Framework detection, zero configuration |
builder: DOCKERFILE with dockerfilePath | Dockerfile.vercel, or entrypoint per service |
startCommand | CMD / ENTRYPOINT in the image |
Injected PORT variable | PORT environment variable in project settings, default 80 |
railway up | git push, or vercel deploy from the CLI |
| PR environments | Preview deployments, on by default for every commit |
| Service variables and reference variables | Project environment variables, plus auto-generated cross-service variables |
| A project with several services | One 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 schedules | Vercel cron jobs in vercel.json |
| Volumes | External storage: databases, caches, or blob storage |
preDeployCommand | CI 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.
Copy link to headingRelated resources
- Migrate to Vercel from Fly.io, Render, or Google Cloud Run
- Does Vercel support Docker deployments? and How to migrate from GHCR to Vercel Container Registry guides
- Run any Dockerfile on Vercel on the Vercel blog
- Container images, Vercel Container Registry, and Cron jobs in the Vercel Docs
- 7 ways to use Docker containers on Vercel