Deploy Express + Mongoose | API with MongoDB on Supported Versions
Express 5 and Mongoose 9 on Railway, health check reads the database
MongoDB
Just deployed
/data/db
Just deployed
Deploy and Host an Express + Mongoose API on Railway
An Express 5 API on Mongoose 9 and MongoDB, on versions that are still supported.
About Hosting Express with Mongoose
The Express/Mongoose starter most people deploy has not been touched since July 2023. It pins Mongoose 7, which reached end of life in 2024 and predates the MongoDB 8 server the same template deploys beside it. Around two thirds of its deployments never come up.
This one tracks current releases and pins them, and fixes two things that make a Mongo-backed service confusing to operate when it goes wrong.
It connects before it listens. Mongoose buffers commands while disconnected, so a server that starts listening first turns a connection problem into requests that hang until they time out. Awaiting the connection makes a bad MONGO_URL fail immediately, in the deploy logs, where you can see it.
The health check reads the connection state. A deployment that cannot reach Mongo reports unhealthy rather than looking fine and erroring on every request.
Common Use Cases
- A JSON API over a document model, where the shape of the data is still moving
- The backend for a front end you host separately
- A starting point that already has validation, error handling and shutdown wired
Dependencies for Express + Mongoose Hosting
- MongoDB, included in this template, with authentication enabled and a persistent volume
- Nothing else.
Deployment Dependencies
- Mongoose documentation: https://mongoosejs.com/docs
- Express: https://expressjs.com
- Source: https://github.com/ak40u/express-mongoose-railway-starter
Implementation Details
| Method | Path | Does |
|---|---|---|
| GET | / | Lists the endpoints |
| GET | /health | 200 when connected to MongoDB, 503 when not |
| GET | /notes | Last 100 notes, newest first |
| POST | /notes | Creates a note from {"body": "..."} |
The MongoDB service runs with a generated root password and starts with --ipv6 --bind_ip ::,0.0.0.0, because Railway private networking is IPv6 and the default bind would leave it unreachable from the API.
Build and deploy settings live in railway.json in the repository, so if you fork it they travel with your code rather than staying behind in this template.
Why Deploy Express + Mongoose on Railway?
A database, a private network and a domain from one deploy, with the database credentials generated rather than left as a placeholder. Push to the repository and the next deploy ships.
Template Content