Moving an app from Replit to Vercel takes four steps: push the Replit App to GitHub, import that repository into Vercel, set the build configuration for the shape of app you have, then re-create the database, the file storage, and the secrets by hand. Only the code travels. The other three you rebuild.

A published Replit App holds more than code. There is a development database, a separate production database, a file bucket, and two different places secrets can live. Vercel imports the code and nothing else, so the rebuilding happens before the domain moves.

Checked on 15 August 2026, three of the eight organic Google results for this query described moving into Replit rather than out of it. Replit’s import documentation names Vercel, Bolt, Lovable and Base44 as sources you can bring projects in from, and documents no route the other way. This walkthrough is built from Replit’s and Vercel’s own current documentation, checked on 15 August 2026, rather than from a hands-on run of one app.

What moves to Vercel, and what stays on Replit

Your code moves to Vercel. The two databases, the App Storage files, both secret lists, the publishing type and the .replit.app URL do not: each one is re-created on a service you pick, and the table below maps them one by one.

What it isComes out with the repoWhere it lands on VercelOwner afterwards
Application codeYesThe GitHub repo Vercel buildsYou, in GitHub
Built frontend assetsRebuilt from sourceThe CDN, from your output directoryVercel
Development databaseNoA Postgres you choose and pay forYour database provider
Production databaseNoThe same Postgres, restored from a dumpYour database provider
App Storage filesNoWhatever object storage you pickYour storage provider
Secrets in the Project EditorNoVercel environment variablesYou, per environment
Secrets in the Publishing paneNoVercel environment variablesYou, per environment
Publishing typeNoA Vercel Function, a Cron-triggered route, or no direct equivalentVercel
The .replit.app URLNoA .vercel.app URL plus your own domainVercel and your registrar

Replit documents four publishing types: Autoscale, Static, Reserved VM, and Scheduled. Autoscale and Static map directly. A Scheduled deployment can map to Vercel Cron when the work can run behind a production HTTP route and finish within normal Function duration limits. A Reserved VM has no direct equivalent because it provides a process that runs continuously. Read the wrong-destination section if the work must stay running or cannot fit those Function limits.

Is your Replit app a static frontend or an Express server?

A Replit app is either a static frontend, which Vercel serves from its CDN with almost no configuration, or a Node server, which Vercel collapses into a single function. One directory settles it. If the repo has a server/ folder holding an Express entrypoint, you have the second kind, and two documented Vercel behaviors are about to matter.

The common shape for an Agent-built Node app is an Express server that also serves the built React frontend, with a Vite build in front and a Postgres schema behind it. That shape is practitioner corroboration rather than anything Replit documents, so treat it as a pattern and not a rule, and check your own repo: look for a server/ or api/ directory, a file that imports express and calls app.listen, and a build script writing to dist or build.

What your repo hasWhat Vercel does with itWhat you change
No server directory, a Vite or React build onlyServes the build output from the CDNSet the build command and output directory
An Express entrypoint calling app.listenTurns the app into one Vercel Function on Fluid computePut the entrypoint where Vercel looks for it
Express serving the built frontend via express.static()Runs the function and serves none of those assetsBuild the frontend into public/**

That third row produces a green build serving a blank page. Vercel’s Express documentation is direct: “express.static() will be ignored and will not serve static assets.” Static files belong in the public/** directory instead. The same page settles the other half: “your Express application becomes a single Vercel Function and uses Fluid compute by default.”

Vercel looks for the Express app at app, index, or server, at the repo root or under src/, and the file has to export the app or call listen:

// src/index.js
const express = require('express');
const app = express();

app.get('/api/health', (req, res) => res.json({ ok: true }));

module.exports = app;

If you are on Lovable rather than Replit, the same job carries a different set of traps, and deploying a Lovable app to Vercel covers those.

Get the code into a repository Vercel can import

Take Git rather than the zip download. A zip gives you the same files, but Vercel’s automatic redeploys and Preview deployments both key off a connected repository, so the zip costs you the two features you are moving for. The click-by-click connection lives in Replit’s Git pane, and the full four-part export gets its own page in this cluster.

Delete .replit and replit.nix in the same commit. They configure the Replit workspace and mean nothing elsewhere. Railway’s migration guide gives the same instruction for its own platform: “Remove the .replit and replit.nix files from your repository before pushing.”

You should end up with a repository holding your package.json, your source directories, and no .replit file. Nothing about your database or your uploaded files is in it.

The Vercel build settings for a Replit app

Import the repository at Vercel’s New Project screen and set the framework preset to what the repo actually builds with. For a Vite frontend that is Vite, with npm run build and an output directory of dist. For a static site with no build step, leave the build command empty and point the output directory at the folder holding index.html. Replit’s own naming does not decide this; the build script does.

For the Express case the preset is Other. Vercel builds the repo, bundles the server into one function, and serves anything under public/** from the CDN. If your build currently writes the frontend somewhere Express then serves, change the output path to public and drop the express.static() call. Leaving it in does no harm, and it also does nothing, which is how people spend an afternoon debugging a router.

A green build means the bundle compiled, not that the app answers. Open the .vercel.app URL, type a nested route directly instead of clicking through, and check the network tab for a bundle returning 200. Whether a Replit app is ready for production at all is a separate question the deployment does not touch.

The Replit production database, and why Agent cannot reach it

Every Replit App has two Postgres databases. The documented split is that the development database is “where you and Agent experiment while building”, while the production database “stores the live data that powers your published app”. Agent “is not able to modify the production database”, and structure crosses over only at publish time: “any changes you’ve made with Agent to the structure of your development database (adding and deleting columns or tables) are applied to your production database.”

So the rows you have been reading in the workspace are not your customers’ rows. Dump the production one, and take its connection string from the right place: Replit’s connection details page says you can “connect to your production database from any PostgreSQL-compatible SQL client using the connection string from the production database’s Settings tab”.

pg_dump "<connection string from the production database Settings tab>" -Fc -f replit-production.dump
pg_restore -d "$NEW_DATABASE_URL" --no-owner --no-privileges replit-production.dump

Restore into whichever Postgres you picked, point Vercel’s DATABASE_URL at it, and keep Replit published while you check the copy.

Founders leaving Replit usually arrive here carrying one specific fear, some version of “if I change my deployment region, does that wipe my production database”. The documented answer is narrower and more useful. Replit’s publishing help page says “you cannot change publishing geography in place after you publish an app. To move the app, remix it and publish the remix in the new region”, and that “the remixed app may receive a different .replit.app subdomain, so connect a custom domain first if you need a stable URL, and re-add any deployment secrets”. The database region cannot be changed in place either. Remixing is not deleting, but it hands you a new app with new secrets to re-enter, which is most of a migration performed by accident.

Take a dump before you touch anything and a second one after the last write. What the first hour looks like when a production database goes away is why that sentence is not padding.

Moving Replit Secrets and App Storage by hand

Secrets are set twice on Replit and have to be set twice again on Vercel. Replit’s publishing troubleshooting page puts it plainly: “Secrets you set in the Project Editor do not automatically carry over to your published app. Add all production Secrets and environment variables in the Publishing pane.” Read both lists before you migrate. The Project Editor list is what your development app used; the Publishing pane list is what your live users have been hitting, and where they disagree the Publishing pane wins.

On Vercel every value is entered per environment, so a key set in Production and missed in Preview gives you an app that works on the live URL and fails on every pull request. Missing values are also quiet: the build succeeds and the failure arrives at runtime as an undefined value or a login that stops working. How environment variables behave across a local file and a hosting dashboard covers that mechanism.

Files are the harder half. Replit renamed Object Storage to App Storage, and the current documentation says “App Storage is powered by Google Cloud Storage (GCS)” and that Replit “connects all buckets you create to your account and makes them available to all your Replit Apps”. Buckets belong to your account rather than to the App, so deleting an App and cancelling a plan have different consequences for your files. As of 15 August 2026 there is no documented bulk export either: the App Storage documentation describes downloading a file by selecting “the download icon to the right of the file”, or reaching the bucket through the Replit App Storage SDK for JavaScript and Python or the Google Cloud Storage client library. Past a handful of files that means writing a script, and it deserves real time in the plan.

When is Vercel the wrong place for a Replit app?

Vercel is the wrong destination when the app needs a process that stays running. Every Express app on Vercel becomes one function with a request-shaped lifetime, so WebSocket servers, in-memory job queues, setInterval loops, and work continuing after the response is sent all stop behaving the way they did on a Reserved VM.

Two published numbers decide most of the rest. Vercel’s function limits currently give a maximum duration of 300 seconds by default on every plan, an 800 second maximum on Pro and Enterprise, a 1800 second extended maximum in beta, and a hard cap of 4.5 MB on a function’s request or response body. A video upload endpoint or a long import job that ran fine on a Reserved VM will meet one of those two. Both were checked on 15 August 2026 and both move, so read the page rather than this sentence when you plan around them.

Railway is the usual answer for an always-on server, and it publishes its own Replit migration guide covering the zip export, the .replit cleanup, pasting variables through its Raw Editor, pg_dump into pg_restore, and the Replit key-value store to Redis path. Vercel publishes no equivalent. AWS is the other common destination and a much larger job. Picking a host is a different question from executing the move and belongs on its own page.

If your app is an always-on server plus a production database plus a bucket of user uploads, this is a move rather than a deploy, and the parts that break are rarely the ones in the build log. If you would rather not run it yourself, having the move done for a fixed price is the other option.

What breaks after the import, and what fixes it

SymptomLikely causeFirst fix
Every route returns 404Wrong output directory, or an Express entrypoint Vercel does not look forCheck the output directory against your build script, and the entrypoint against app, index, or server
Green build, blank page, bundle 404sThe frontend was served by express.static()Build the frontend into public/**
Home page works, refreshing a nested route 404sNo single-page-app rewrite for a client-routed buildRewrite unmatched paths to index.html
App loads, API calls fail on an undefined valueA Publishing pane secret was never re-entered on VercelCompare that list against Vercel’s variables, per environment
Requests still go to a .replit.app hostThe old URL is hardcoded in the frontendSearch the repo for replit.app
Database connection refused or timing outStill pointing at the Replit databaseConfirm DATABASE_URL is the restored database, then check the provider’s connection rules
Uploads succeed, files 404 laterThe bucket is still Replit App StorageMove the bucket, or point the app at new storage credentials
Long request returns a 504The function hit its maximum durationSplit the work, or move that endpoint to a host that runs a process
Large upload returns a 413The 4.5 MB body cap on a Vercel FunctionUpload direct to storage with a signed URL

Check the Vercel URL before you move the domain

Run this against the .vercel.app URL while Replit is still published and still taking real traffic. Nothing changes for customers until DNS does, which makes it the only free rehearsal you get.

  1. 01 Load the home page and three nested routes by typing the URL directly, then refresh each one
  2. 02 Sign up, sign in, sign out, and reset a password on a test account
  3. 03 Write one record and read it back, then confirm it landed in the restored database and not the Replit one
  4. 04 Upload a file and fetch it again from a fresh browser session
  5. 05 Exercise every paid or external integration once, and confirm no key is visible in the browser network tab
  6. 06 Compare Vercel's environment variables against the Replit Publishing pane list, line by line
  7. 07 Read Vercel's build and function logs for errors the page did not show you

The rollback here is leaving the domain where it is. Keep Replit published, keep its production database taking the writes, and treat Vercel as a copy until every line above passes. After the cutover, hold off on deleting the Replit App: a remixed app can receive a different .replit.app subdomain, so the old URL is not something you can casually recreate.

One loose end nobody resolves cleanly is what happens to the Replit Agent workflow you have been building in. Most people keep the workspace, keep committing from it, and let GitHub carry changes to Vercel. That works, and it also means the thing you were paying Replit for is doing a smaller job than it was.

Common questions about moving from Replit to Vercel

Does deploying to Vercel move my Replit database?

No. Vercel deploys the repository, and a Replit App’s Postgres data lives outside it, in a development database and a separate production database. Create a new Postgres, restore a dump of the Replit production database into it, and set DATABASE_URL on Vercel to point at the new one. Until then the deployed app either has no database or is still writing to Replit’s.

Why does my Replit app 404 on Vercel?

Usually because the build output is not where Vercel serves from, or because the app relied on express.static(), which Vercel’s documentation states is ignored and will not serve static assets. Move the build output into public/**. If only nested routes 404 while the home page works, the cause is different: a client-routed build needs a rewrite sending unmatched paths to index.html.

Do Replit Secrets transfer to Vercel automatically?

No, and they do not transfer inside Replit either. Replit documents that secrets set in the Project Editor do not automatically carry over to your published app, and that production secrets belong in the Publishing pane. That leaves two lists to reconcile, and the Publishing pane list is the one your live users have been running against.

Should I move my Replit app to Railway instead of Vercel?

If your app needs a process that stays running, probably yes. Railway runs an always-on server and publishes a first-party migration guide for this exact move, covering the export, the .replit cleanup, the variable paste, and the pg_dump to pg_restore path. Vercel fits a static frontend or an API that answers per request.

Can I cancel my Replit plan after moving to Vercel?

Only once the data is genuinely elsewhere. The repository is safe on GitHub, but the production database and the App Storage bucket are Replit-side, and App Storage buckets belong to your account rather than to an individual App. Restore the dump, copy the files out, verify both from the Vercel URL, then look at the plan.

Does Vercel run my Express server the same way Replit did?

No. On Vercel the whole Express app becomes a single Vercel Function on Fluid compute, scaling per request rather than staying up between them. Anything assuming a long-lived process, including in-memory caches, WebSocket connections, background timers, and work started after a response was sent, needs rethinking. The documented function limits apply too: a 300 second default duration and a 4.5 MB cap on request and response bodies.

Everything here was checked against Replit’s and Vercel’s current documentation on 15 August 2026. The function limits and the App Storage naming are the two most likely to have moved since.