Deploy Express + Prisma | API with Postgres and Migrations That Run
Express 5 and Prisma 7 on Railway, migrations run in the pre-deploy step
Just deployed
Just deployed
/var/lib/postgresql/data
Deploy and Host an Express + Prisma API on Railway
An Express 5 API on Prisma 7 and Postgres, deployed with its database migrations in the pre-deploy step.
About Hosting Express with Prisma
The interesting part of this template is where the migrations run.
The Express/Prisma starter most people deploy has not been updated since January 2023. It pins Prisma 4, long past end of life, and its build script is yarn migrate:deploy && tsc - it applies migrations during the build. Builds have no database attached, so the migration cannot connect and the build fails before TypeScript is ever invoked. Fewer than half of its deployments come up.
Railway has a step meant for this. The repository ships a railway.json declaring preDeployCommand: npm run migrate, which runs after the build and before the new version takes traffic, when DATABASE_URL exists. Migrations apply on every deploy, and a failed migration stops the rollout instead of putting new code in front of an old schema.
Common Use Cases
- A typed REST API with a real relational schema behind it
- The backend half of a front end you host separately
- A starting point for a service that will grow a real data model, with migrations already wired
Dependencies for Express + Prisma Hosting
- Postgres, included in this template, on a persistent volume
- Nothing else. The API has no other external dependency.
Deployment Dependencies
- Prisma documentation: https://www.prisma.io/docs
- Express: https://expressjs.com
- Source: https://github.com/ak40u/express-prisma-railway-starter
Implementation Details
Endpoints:
| Method | Path | Does |
|---|---|---|
| GET | / | Lists the endpoints |
| GET | /health | Runs SELECT 1, so it reports unhealthy when Postgres is unreachable |
| GET | /notes | Last 100 notes, newest first |
| POST | /notes | Creates a note from {"body": "..."} |
Three details worth knowing before you extend it:
- Prisma 7 changed how connections are configured.
urlis no longer allowed in schema.prisma; the CLI reads it from prisma.config.ts and the runtime gets it through a driver adapter -new PrismaClient({ adapter: new PrismaPg(...) }). - The lockfile is committed and audited clean. Railway refuses to build when the committed lockfile carries a HIGH advisory, and Prisma's own dependency tree currently pulls a vulnerable find-my-way, so package.json overrides it forward. Run
npm audit --audit-level=highbefore pushing. - Build and deploy settings live in the repository, in railway.json, not only in this template. Fork it and they travel with your code.
Why Deploy Express + Prisma on Railway?
Postgres, a private network and a domain in one deploy, and the migration step happens where it can actually reach the database. Push to the repository and the next deploy migrates and ships.
Template Content