Deploy React Router | Accounts and Per-User Data on Postgres
React Router 8, Prisma 7. Accounts and per-user data, ready to use.
Just deployed
Just deployed
/var/lib/postgresql/data
Deploy and Host React Router Stack on Railway
Accounts, sessions and per-user data on Postgres, built on React Router 8, React 19 and Prisma 7.
Sign up, log in, write notes, delete them. Your notes, not anyone else's. Nothing to wire together after deploying.
About Hosting React Router Stack
The Remix Indie Stack template builds from a repository last touched in April 2022, and its package.json says "remix": "*" and "@remix-run/react": "*", with React 17 and Prisma 3.
"*" is not a version. It resolves to whatever npm publishes today, against application code written for Remix 1.x. The install and the code cannot agree, and no deployment of it succeeds: that template reports 0% health.
Remix has since merged into React Router, now at 8. This template is the same idea rebuilt on it: the thing the Indie Stack was actually for, a working account system with per-user data, on versions that exist.
Common Use Cases
- A starting point for an app with user accounts, where sign-up, login, sessions and per-user data already work.
- A reference for account handling done carefully: constant-time login, ownership checked in the query, logout that cannot be triggered by another site's GET request.
- A replacement for the Remix Indie Stack on current React Router and Prisma.
Dependencies for React Router Stack Hosting
Deployment Dependencies
- app, built from ak40u/react-router-stack-railway-starter (public)
- Postgres
ghcr.io/railwayapp-templates/postgres-ssl:16
Implementation Details
Five decisions worth understanding:
- Login takes the same time whether or not the account exists. A missing user is compared against a real hash of a random value, computed once at startup, rather than returning early. It has to be a genuine hash: bcrypt rejects a malformed one in well under a millisecond, against about 200 ms of real work, and that gap alone tells an attacker which emails are registered. Measured on a deployment, not assumed.
- Ownership is part of the query. Deleting a note filters on
userIdas well asid, so guessing someone else's id changes nothing. A check the caller is trusted to have made is not a check. - Logging out is a POST. A GET would let any page on the internet sign your users out with an
<img src="/logout">. - Migrations run pre-deploy, not at build. The build container has no database.
prisma generatedoes run at build, because generated client code has to be in the image: build and pre-deploy are different containers, and files written in the second do not survive. - The health check asks the database. A process that is up but cannot reach Postgres is not serving anything.
Configuration
Nothing to fill in. DATABASE_URL is wired to Postgres over the private network, and SESSION_SECRET and the database password are generated.
Changing SESSION_SECRET signs everyone out. That is the point of it: it is the lever you pull if you think a session has leaked.
Why Deploy React Router Stack on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying React Router Stack on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
Template Content
