How to Deploy a Node.js App on Railway
A step-by-step guide to deploying a Node.js and Express app on Railway, using a one-click starter template or your own code.
In this post, we’ll deploy a Node.js app on Railway, first with a one-click starter template and then with your own code. Before you begin, make sure you have:
- A GitHub account (required for Railway authentication)
- Basic familiarity with Node.js and JavaScript
- (Optional) A custom domain if you want to use one instead of the default Railway subdomain

Node.js is an open-source, event-driven JavaScript runtime built on Chrome’s V8 engine, commonly used for APIs, real-time apps and microservices. Its npm registry gives you a large library of packages to build on.
Deploy a Simple Node.js App on Railway
Launch the Node.js one-click starter template (or the button below); the free trial is enough to try it.
You'll be given an opportunity to change the default repository name and set it private, if you'd like. Accept the defaults and click Deploy; the deployment will kick off immediately.

Once the deployment completes, a simple Node.js app will be available at a default xxx.up.railway.app domain - launch this URL to access the app. You should see the landing page, confirming your app is live! If you are interested in setting up a custom domain, I covered it at length in a previous post - see custom domains on Railway.

If you want to modify the app, here's a few things to understand first:
- The
app.jsfile only covers the default/route, which returns a simple HTML landing page. To customise this, add your own routes using the Express framework (current template below).
const express = require('express');
const path = require('path');
const indexRouter = require('./routes/index');
const app = express();
const PORT = process.env.PORT || 3000;
// Serve static files from the "public" directory
app.use(express.static(path.join(__dirname, 'public')));
// Use the router for handling routes
app.use('/', indexRouter);
// Catch-all route for handling 404 errors
app.use((req, res, next) => {
res.status(404).sendFile(path.join(__dirname, 'views', '404.html'));
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
});- Railway runs its
startscript (node app.js). Add anengines.nodefield if you need a specific Node.js version; otherwise Railway uses the current LTS release. - Railway sets a
PORTvariable automatically and the app listens on it, falling back to3000when you run it locally.
Deploy Your Own Node.js App
If you already have a Node.js app in a GitHub repository, create a new project in Railway, choose Deploy from GitHub repo and select your repository. Railway detects package.json, installs your dependencies and runs your start script. Make sure your server listens on process.env.PORT, then go to Settings → Networking and click Generate Domain to get a public URL.
Next Steps: Taking Your App Further
Now that you have a basic Node.js app deployed, here are some ways to enhance it:
- Add more routes and features: Extend your application by adding more endpoints and functionality. Consider implementing RESTful API endpoints, authentication with JWT, file upload capabilities, etc.
- Implement a database: Connect a PostgreSQL or MySQL database to store persistent data. Railway makes this simple with one-click database provisioning and automatic connection string injection.
- Set up continuous deployment: the template creates a copy of the code in your GitHub account, and Railway redeploys automatically whenever you push to it.
- Monitor your application: Keep track of your app's performance and resource usage with Railway's built-in metrics dashboard, monitor CPU and memory usage, track deployment history and rollback if needed.
- Finally, optimise costs: Remove unused services, turn on Serverless for services that can sleep when idle, and monitor your usage in the billing dashboard.
Ready to try it? Launch the Node.js template.
Frequently Asked Questions
Why does my app show “Application failed to respond”? Almost always because the server is listening on a fixed port. Railway provides a PORT variable, so listen on process.env.PORT instead of a hard-coded number.
Which Node.js version does Railway use? The version in the engines.node field of package.json or in an .nvmrc file. If neither is set, Railway uses the current LTS release.
Is Railway free for Node.js apps? New accounts get a 30-day trial with a one-time $5 credit, then move to the Free plan with $1 of usage credit a month. That’s enough for a small app like this one.