Config as Code deprecation: what exactly detaches a service from its old config file?
fersanchez160276-png
HOBBYOP

a day ago

I’m migrating a project from Config as Code to IaC before the December 1 deprecation, and I want to be sure I don’t lose the deploy settings of a service that is in production. I have two services in one project and their config file setup is different, so I have three questions.

Question 1 — My API service has the “Railway Config File” field in Settings empty, but the service still reads a railway.toml that lives in a subdirectory of the repo. Once I define that service in .railway/railway.ts, what actually stops the old railway.toml from being applied? Does the IaC file take precedence automatically, or do I have to delete or rename the toml file?

Question 2 — My cron service has a custom file name in that field: railway.cron.toml. The docs say to open the service settings and clear the config file path field. Is clearing that field the whole step, or does anything else need to happen for the service to stop reading it?

Question 3 — If I use a named partial that declares only those two services, is my Postgres database and its attached volume safe? They are not declared in the file at all, and I want to be certain a plan or an apply will never delete them.

Awaiting User Response

5 Replies

Railway
BOT

a day ago

For the API service, IaC does not take precedence automatically. Until it is migrated, the railway.toml is still read at deploy and overrides service settings, and railway config plan refuses to manage a service still on Config as Code. Remove the file from the repo, yourself or with railway config migrate --apply --delete-files, which writes .railway/railway.ts, clears the Railway Config File setting and deletes the CaC files it found.

For the cron service, clearing the config file path field in Settings is the documented step: future deploys stop reading railway.cron.toml. migrate --apply clears it for you, and deleting the file too leaves nothing to read.

For Postgres, a named partial only deletes resources it owns, which is only what its file declares, so an undeclared database and volume are left alone by its plan and apply. Deletes are also marked destructive before you confirm.

One caution: once a named partial is applied, that environment can't take a whole-project file until named ownership is released with railway config partials release. If one repo holds everything, migrating every service together into one whole-project file is simpler, but then include Postgres, since a whole-project apply deletes omitted resources. Also, each declared service's env block is its complete variable list, so unlisted existing variables are planned as deletes unless marked preserve() (railway config pull writes them that way). See the migration guide.


Status changed to Awaiting User Response Railway • 1 day ago


Railway

For the API service, IaC does not take precedence automatically. Until it is migrated, the `railway.toml` is still read at deploy and overrides service settings, and `railway config plan` refuses to manage a service still on Config as Code. Remove the file from the repo, yourself or with `railway config migrate --apply --delete-files`, which writes `.railway/railway.ts`, clears the Railway Config File setting and deletes the CaC files it found. For the cron service, clearing the config file path field in Settings is the documented step: future deploys stop reading `railway.cron.toml`. `migrate --apply` clears it for you, and deleting the file too leaves nothing to read. For Postgres, a named partial only deletes resources it owns, which is only what its file declares, so an undeclared database and volume are left alone by its plan and apply. Deletes are also marked destructive before you confirm. One caution: once a named partial is applied, that environment can't take a whole-project file until named ownership is released with `railway config partials release`. If one repo holds everything, migrating every service together into one whole-project file is simpler, but then include Postgres, since a whole-project apply deletes omitted resources. Also, each declared service's `env` block is its complete variable list, so unlisted existing variables are planned as deletes unless marked `preserve()` (`railway config pull` writes them that way). See the [migration guide](https://docs.railway.com/infrastructure-as-code#migrating-from-config-as-code).

fersanchez160276-png
HOBBYOP

a day ago

Thanks — that answers my Postgres question. Two follow-ups, because my setup doesn’t match the assumptions.

First, my API service’s “Railway Config File” field is empty. It was never set; the service just picks up a railway.toml that sits at the root of what railway up uploads. Does railway config plan refuse that service too, or only a service with an explicit config file path set? Related: railway config migrate status reports “No services in production read Config as Code” for my project, and railway config migrate --show reports “No Config as Code files found”, so migrate --apply --delete-files has nothing to act on. What is the manual equivalent for a service in that state?

Second, about variables. My file declares no env block at all and sets variables: { managed: false } at the project level. Does that take existing variables out of scope entirely, or are they still planned as deletes? I need to be certain that an apply can never remove a production variable.


Status changed to Awaiting Railway Response Railway • 1 day ago


Railway
BOT

a day ago

On variables: variables: { managed: false } does not take them out of scope. There is no unmanaged marker for variables at the project or service level, and leaving out the env block does not opt a service out. For a service that already has variables, the plan treats a missing env as an empty list and every live variable shows up as a destructive delete. The apply behaves the same way. The only way to keep them is to list each one as preserve(). railway config pull writes them that way, or you can build that list from your key names inside the config file. Deletes are marked destructive, and a non-interactive apply also needs --confirm-destructive, so review the plan before you confirm.

On the API service: a railway.toml at the root of the uploaded source keeps overriding that service's settings at deploy time, whatever the Railway Config File field says, until December 1. We can't confirm from here whether railway config plan refuses that service, given the migrate commands report nothing. The manual equivalent is to copy every value the toml sets (build and start commands, healthcheck, restart policy, pre-deploy command, watch patterns and so on) into the service's settings or your IaC definition, then remove the file from what railway up uploads. After that, nothing is left to override the settings, and nothing the file controlled is lost when it stops being read.


Status changed to Awaiting User Response Railway • 1 day ago


Railway

On variables: `variables: { managed: false }` does not take them out of scope. There is no unmanaged marker for variables at the project or service level, and leaving out the `env` block does not opt a service out. For a service that already has variables, the plan treats a missing `env` as an empty list and every live variable shows up as a destructive delete. The apply behaves the same way. The only way to keep them is to list each one as `preserve()`. `railway config pull` writes them that way, or you can build that list from your key names inside the config file. Deletes are marked destructive, and a non-interactive apply also needs `--confirm-destructive`, so review the plan before you confirm. On the API service: a `railway.toml` at the root of the uploaded source keeps overriding that service's settings at deploy time, whatever the Railway Config File field says, until December 1. We can't confirm from here whether `railway config plan` refuses that service, given the migrate commands report nothing. The manual equivalent is to copy every value the toml sets (build and start commands, healthcheck, restart policy, pre-deploy command, watch patterns and so on) into the service's settings or your IaC definition, then remove the file from what `railway up` uploads. After that, nothing is left to override the settings, and nothing the file controlled is lost when it stops being read.

fersanchez160276-png
HOBBYOP

4 hours ago

Update from my side: I went ahead and ran it, so I can answer two of the open points with measurements instead of guesses. Posting them in case they help someone else, and because they contradict the automated answers above.

On whether railway config plan refuses a service still on Config as Code — it did not refuse either of my two services. One has the “Railway Config File” field empty and picks up a railway.toml from the root of what railway up uploads; the other has an explicit railway.cron.toml. The plan ran normally on both and produced 0 to add, 4 to change, 0 to destroy.

On variables: { managed: false } — on my project it did take variables out of scope. My file declares no env block at all, and the plan header printed variables: unmanaged · 8 on Railway not managed. Not a single variable appeared as a change or a delete, in the plan or in the apply. The apply reported only the two services. I ran the plan again afterwards and no variable showed up then either.

So, at least for this project, a missing env block with managed: false did not turn live variables into destructive deletes.

Two things I still can’t answer, and these are my actual questions:

First, the detach step. My railway.toml is still at the root of what railway up uploads and still overrides the service settings on every deploy. Today that is harmless, because the IaC file sets the same ten values. But what is the correct way to detach it before December 1 — delete the file, rename it, or something in the dashboard? And for a service whose “Railway Config File” field was always empty, is there anything at all to do, or does it simply stop being read on that date?

Second, something I could not explain. After a successful apply, a second plan still reports one line: deploy.restartPolicyType (null → "ON_FAILURE") on the API service. Everything else saved and disappeared from the plan, including restartPolicyMaxRetries on the same service and restartPolicyType: "NEVER" on the cron. Is ON_FAILURE the platform default and therefore not stored explicitly, so the plan keeps proposing it? Re-applying changes nothing.


Status changed to Awaiting Railway Response Railway • about 4 hours ago


Railway
BOT

4 hours ago

To detach the API service, remove railway.toml from the source that railway up uploads. Deleting it or renaming it to something other than railway.toml / railway.json both work, since the file is only picked up by that name. There is no dashboard step for a service whose Railway Config File field was never set. Clearing that field only matters for a custom path like railway.cron.toml, and for the cron service you should both clear it and remove the file. If you do nothing, Config as Code files stop being read on 2026-12-01 and deploys keep running on the service settings, so with your IaC file already setting the same ten values, nothing is lost either way.

On the plan not refusing either service: our documented behavior is that railway config plan stops when a service is still managed by railway.json or railway.toml. Your run, with both services planned normally while one still has an explicit config path, does not match that, and we could not establish from here why the check did not trigger for your project. Removing both files and clearing the cron path puts the services in the documented migrated state regardless.

On the restart policy: On Failure (with up to 10 restarts) is the platform default. We could not confirm whether the plan keeps showing null → "ON_FAILURE" because the default is stored as an empty value, but since re-applying changes nothing, the service is already running with On Failure.


Status changed to Awaiting User Response Railway • about 4 hours ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...