I Said Deploy To Vercel. Railway Heard Me.

Brett Ridenour Brett Ridenour · June 6, 2026

I had three static HTML checkout mockups for a client. I needed a URL I could text him so he could click through and pick one. The whole thing was supposed to take five minutes.

It took thirty. Not because anything was hard — because Railway deployed before I asked it to, and I spent twenty-five minutes figuring out why a URL I hadn’t created yet was already live.

Here’s the sequence, because if you connect Railway to a GitHub repo and don’t think about it again, this will eventually happen to you too.

The setup

The repo had a Railway service attached from a previous experiment. I forgot it was there. The service was set to watch main. That’s the default. That’s almost always the default.

I committed the three HTML files with a throwaway message — wip: static checkout options — pushed to main, and started writing the Vercel redirect rule I actually wanted. Vercel was the intended target. Static HTML, a custom path, redirect from a subdomain. Clean.

About forty seconds in, my phone buzzed. Railway. Deploy succeeded. A URL was live, pointing to whichever of the three HTML files Railway picked as the index. Wrong one. Cached. Public.

Why this is worse than it sounds

The obvious failure mode is “I deployed the wrong thing.” That’s annoying but fixable — redeploy, swap, move on.

The real failure mode is that the URL is already in the wild before you’ve decided what it points to. If I had texted the wrong link first, the client would have seen the wrong mockup and formed a first impression on something I hadn’t approved. With a paying yacht client, that’s not a “ha, oops” moment. That’s the meeting.

The second failure mode is that Railway’s URL doesn’t match the URL I told him I’d send. He’s expecting something on brettridenour.com. He gets something-production.up.railway.app. Now I’m explaining infrastructure to a man who runs boats.

The actual fix (not what I thought it was)

My first instinct was to undo the deploy. You can’t, really — you can roll back to a previous version, but if there is no previous version (fresh service), there’s nothing to roll back to. Pause is the closest thing.

The fix wasn’t undoing. The fix was understanding Railway’s watch behavior and turning it off for any repo where I’m not explicitly using Railway as the target.

Three settings worth knowing about:

Settings → Service → Source
  - Watch Paths      (only deploy when these globs change)
  - Branch           (which branch triggers deploys)
  - Auto Deploy      (the big red switch — turn this off)

The three settings that decide whether your push becomes a deploy

Watch Paths is the surgical option. If your Railway service only cares about apps/api/**, set that as the watch path and a commit touching public/blog/*.html won’t trigger anything. That’s the right answer for a polyglot repo.

Auto Deploy: off is the brute-force option. Pushes don’t deploy. You go to the dashboard and click Deploy when you mean it. That’s the right answer for a repo where Railway is a side service you reach for occasionally.

What I did, after the fact: turned auto-deploy off on every Railway service in my account that wasn’t actively in production. Took four minutes. The kind of thing you only do once you’ve been bitten.

What I should have done first

Looking back, there’s a one-line check that would have saved the whole thirty minutes:

gh api repos/:owner/:repo/hooks --jq '.[].config.url'

Lists every webhook on the repo. Anything pointing at railway.app, vercel.com, netlify.com, or any other PaaS is a deploy target the next push is going to hit. Run that before any “let me just push some static files” moment and you know exactly what’s about to wake up.

I’d never bothered. The repos I work in tend to have one deploy target. Right up until they don’t.

A repo doesn’t have one deploy target. It has every deploy target you ever connected and forgot about.

— lesson, paid in full

Vercel redirect went up about ten minutes later, pointing to the right HTML file at the right path on the right domain. He clicked through, picked option two, we moved on. He has no idea any of this happened, which is the goal.

But I wrote it down. Because the next time I push to a repo that’s been around for more than a quarter, I want to remember that the silence between git push and a clean prompt isn’t necessarily silence. Somewhere out there, a build runner is already taking my commit message at its word.

Takeaway

If you’ve ever connected a PaaS to a repo, three things are true right now whether you remember it or not:

  1. That service is watching a branch.
  2. Auto-deploy is probably on.
  3. Your next push is its next deploy.

The fix is one toggle. The thirty minutes I spent finding it is the tax for not knowing where the toggle was.

gh api repos/:owner/:repo/hooks before you push. Or just turn auto-deploy off everywhere it isn’t load-bearing. Future you, mid-client-demo, will be grateful.