Deploy Node.js and Express
Deploy a Node.js API with a production start command and a reachable HTTP port.
This guide uses Express, but the same web-service setup works for other Node.js HTTP frameworks when their production server binds to the configured port.
Prepare the server
For an ESM project with "type": "module" in package.json, a minimal server.js is:
import express from "express";
const app = express();
app.use(express.json());
app.get("/health", (_request, response) => {
response.json({ status: "ok" });
});
app.get("/", (_request, response) => {
response.json({ message: "Hello from Openstead" });
});
const port = Number(process.env.PORT || 3000);
const server = app.listen(port, "0.0.0.0");
process.on("SIGTERM", () => {
server.close(() => process.exit(0));
});For CommonJS, use require("express") instead of the import. Declare Express as a production dependency and commit the lockfile.
Add a production start script:
{
"scripts": {
"start": "node server.js"
}
}Merge this into the existing manifest rather than replacing its other fields.
Deploy the service
Create a Web Service from the repository:
| Setting | Plain JavaScript | Compiled TypeScript |
|---|---|---|
| Build method | Railpack | Railpack |
| Build command | Leave empty if no build is needed | Your build script, such as npm run build |
| Start command | npm run start | Start compiled output, such as node dist/server.js |
| Port | 3000 | 3000 |
| Health check path | /health | Your implemented health route |
Ensure the build emits the path used by the start command. Development tools such as nodemon should not be the production process.
Connect a database
Create a managed database in the application's permitted private network and add its connection URL as a service variable. Use the database driver's connection pool, set sensible connection and query timeouts, and keep the total pool size within the database's limits as replicas increase.
Prisma, Sequelize, Knex, and similar tools need their own schema migration commands. Put the appropriate release migration in a paid pre-deploy command. Keep generated clients and production dependencies in the final artifact.
Connect a separate frontend
A browser-based frontend calls the API's public HTTPS URL. Configure CORS for the exact frontend origin and configure authentication cookies deliberately. A private database URL or private service hostname belongs only in backend code.
Troubleshooting
If the release never becomes ready, check 0.0.0.0, PORT, and the health path. If the runtime cannot find a module, confirm it is in production dependencies and was not omitted from the build. If an upload disappears after deployment, move it to a persistent disk or object storage.