<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ivanpetrus</title>
    <description>The latest articles on DEV Community by ivanpetrus (@ivanpetrus).</description>
    <link>https://dev.to/ivanpetrus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4121377%2Fd9da2dc8-bbd5-44fd-b777-b2c5548db141.jpg</url>
      <title>DEV Community: ivanpetrus</title>
      <link>https://dev.to/ivanpetrus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivanpetrus"/>
    <language>en</language>
    <item>
      <title>Deploy a Node/TypeScript API to Railway in 15 minutes (with a worker-friendly setup)</title>
      <dc:creator>ivanpetrus</dc:creator>
      <pubDate>Fri, 11 Sep 2026 19:54:48 +0000</pubDate>
      <link>https://dev.to/ivanpetrus/deploy-a-nodetypescript-api-to-railway-in-15-minutes-with-a-worker-friendly-setup-1o64</link>
      <guid>https://dev.to/ivanpetrus/deploy-a-nodetypescript-api-to-railway-in-15-minutes-with-a-worker-friendly-setup-1o64</guid>
      <description>&lt;p&gt;This walkthrough deploys a simple Express API to Railway, sets env vars, and notes how to add a second service later for a queue worker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; Some links are affiliate links. I may earn a commission at no extra cost to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll end up with
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A deployed Node/TS HTTP service&lt;/li&gt;
&lt;li&gt;HTTPS URL on Railway&lt;/li&gt;
&lt;li&gt;Env-based config (&lt;code&gt;PORT&lt;/code&gt;, &lt;code&gt;DATABASE_URL&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;A clear path to add a worker process (BullMQ etc.) as a second service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Companion repo
&lt;/h2&gt;

&lt;p&gt;Clone or fork the starter and deploy it as-is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ivanpetrus/railway-node-ts-api" rel="noopener noreferrer"&gt;github.com/ivanpetrus/railway-node-ts-api&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node 20+ locally&lt;/li&gt;
&lt;li&gt;A GitHub repo (or Railway CLI)&lt;/li&gt;
&lt;li&gt;~15 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Minimal API
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`listening on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt; scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsx src/index.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tip: Railway sets &lt;code&gt;PORT&lt;/code&gt; for you — don't hardcode &lt;code&gt;3000&lt;/code&gt; in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Railway project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up / log in via this link (includes starter credits when eligible): &lt;a href="https://railway.com?referralCode=Bmv7KL&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=railway_deploy_15m" rel="noopener noreferrer"&gt;Railway&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;New Project → Deploy from GitHub (connect the repo)
Or deploy the companion repo above.&lt;/li&gt;
&lt;li&gt;Pick the repo + root directory if monorepo&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3 — Build &amp;amp; start settings
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Step 4 — Environment variables
&lt;/h2&gt;

&lt;p&gt;Add at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NODE_ENV=production&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;any secrets your app needs (&lt;code&gt;DATABASE_URL&lt;/code&gt;, &lt;code&gt;JWT_SECRET&lt;/code&gt;, …)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never commit &lt;code&gt;.env&lt;/code&gt;. Rotate anything you pasted into chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Public URL &amp;amp; health check
&lt;/h2&gt;

&lt;p&gt;Generate a Railway domain (or custom domain).&lt;br&gt;
Hit &lt;code&gt;/health&lt;/code&gt; — you should see &lt;code&gt;{ "ok": true }&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional: add a worker later
&lt;/h2&gt;

&lt;p&gt;For BullMQ / background jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;strong&gt;second Railway service&lt;/strong&gt; from the same repo&lt;/li&gt;
&lt;li&gt;Same build, different start command (e.g. &lt;code&gt;node dist/worker.js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Share env vars; put Redis as a plugin/add-on or external Redis&lt;/li&gt;
&lt;li&gt;Cap concurrency so one spike doesn't OOM the service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where a lot of solo apps get burned — happy to write a follow-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost mindset (solo)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start tiny; watch the usage dashboard after 24h&lt;/li&gt;
&lt;li&gt;Separate web vs worker so a stuck job doesn't take down HTTP&lt;/li&gt;
&lt;li&gt;Set memory limits / restart policy before you "optimize code"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Railway is a fit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Solo/small team, Node/TS API + optional worker&lt;/li&gt;
&lt;li&gt;Want GitHub → deploy without babysitting VMs&lt;/li&gt;
&lt;li&gt;Not a fit if you need multi-region edge at Google scale on day one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Ship the healthcheck first. Add the worker second. Keep env vars boring.&lt;/p&gt;

&lt;p&gt;Deploy link (affiliate): &lt;a href="https://railway.com?referralCode=Bmv7KL&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=railway_deploy_15m" rel="noopener noreferrer"&gt;Railway&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want the same app on a classic VPS/PaaS instead, next post compares &lt;strong&gt;Railway vs DigitalOcean&lt;/strong&gt; for a solo Node API.&lt;/p&gt;

&lt;p&gt;Questions / stuck on build commands? Drop an error log snippet in the comments.&lt;br&gt;
In the service settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build command:&lt;/strong&gt; &lt;code&gt;npm run build&lt;/code&gt; (or &lt;code&gt;pnpm&lt;/code&gt;/&lt;code&gt;yarn&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start command:&lt;/strong&gt; &lt;code&gt;npm run start&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Watch the first deploy logs for &lt;code&gt;listening on …&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the build fails on TypeScript, ensure &lt;code&gt;typescript&lt;/code&gt; is in dependencies/devDependencies and &lt;code&gt;tsconfig&lt;/code&gt; emits to &lt;code&gt;dist/&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>typescript</category>
      <category>railway</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
