Key RobotStart free

How to rotate a Railway variable without downtime

Updated October 2026

Railway's API will redeploy your service the moment you write a new variable, unless you tell it not to. Rotating safely means turning that off on purpose, checking the new value works, and only then redeploying for real.

Here's the exact process, from Railway's own docs.

The manual steps

  1. Write the new value with skipDeploys: true so nothing goes live yet: mutation { variableUpsert(input: { projectId, environmentId, serviceId, name, value, skipDeploys: true }) }. Railway's own API guide, checked December 4, 2026, calls this exact pattern out as the rotation recipe: "Use variableUpsert with skipDeploys: true for all services, then trigger deployments manually when ready."
  2. Never send replace: true on the bulk version of this call. Railway's own docs warn it "will delete all variables not included," which turns a single-variable rotation into an outage for every other variable on the service.
  3. Confirm the new value is what you expect: query { variables(projectId, environmentId, serviceId) } returns the current values as a plain object, so you can read it straight back.
  4. Trigger the deploy on purpose: mutation { serviceInstanceRedeploy(serviceId, environmentId) }, or a fresh build with serviceInstanceDeployV2.
  5. Poll deployments(input: { projectId, serviceId, environmentId }, first: 1) until status reads SUCCESS. Anything that lands on FAILED or CRASHED means roll back to the old value before anyone notices.

What breaks if you miss a place

Railway returns authorization failures as HTTP 200 with an errors[] array, not as an HTTP error code. Railway's own docs say this plainly. A rotation script that only checks the HTTP status will treat a failed, unauthorized write as a success, and the old value stays live while you believe it's already rotated.

How to check the old value is actually gone

deploymentRestart only restarts the running process. Railway's docs don't confirm whether a restart alone picks up a variable written with skipDeploys: true, so don't use it to test a rotation. Use the variables query after the real redeploy finishes, and compare it against what you wrote in step 1.

The one variable type this doesn't apply to

A sealed variable is different. Railway's own docs say it's "never visible in the UI nor can it be retrieved via the API," on either side of a rotation. If a credential is sealed, you can write a new value, but you can't read the old one back to confirm anything, by design. Plan around that instead of expecting the same confirm step that works for every other variable.

Or let Key Robot do it

Key Robot does this for you today. It writes the new value with skipDeploys, reads it back, redeploys, waits for the deploy to finish, checks your app, and then deletes the old key at the service. It never uses replace, so your other variables stay.

In our live test on October 26, 2026, the robot changed a key on a real deployed Railway app in 19 seconds, deploy included. When we made the app refuse the next key, the robot put the old one back and redeployed.

See how to rotate a Neon database password for a credential Key Robot already handles, or the rotate hub for every service.

Questions

Does updating a Railway variable redeploy the service automatically?

By default, yes. Railway's own API guide documents skipDeploys to stop that, and its own rotation recipe tells you to use it, then trigger the deployment yourself once you're ready.

Can I read a Railway variable's value back after setting it?

Yes for most variables, through the variables query. The one exception is a sealed variable, which Railway's own docs say is never visible in the UI or retrievable by API, by design.

Is Key Robot rotating Railway variables today?

Yes. Key Robot writes the new value, redeploys, checks your app, and puts the old value back if the check fails.