UpuaiUpuai

Migrar do Railway para a Upuai: do railway.json ao upuai.toml

Guia para levar um app do Railway para a Upuai: o que cada chave do railway.json vira no upuai.toml, variáveis, banco Postgres, domínio e a conta em reais.

Equipe Upuai· Upuai Cloud13 min de leitura
Ilustração de um arquivo de configuração sendo convertido em outro, a caminho de um servidor no Brasil

Se o seu app roda no Railway com um railway.json na raiz, migrar do Railway para a Upuai é, na maior parte, um trabalho de tradução: cada chave do arquivo vira uma chave do upuai.toml, uma tela do painel ou um aviso honesto de que a função não existe aqui. Este guia faz a tradução chave por chave e depois cuida do que fica em volta: variáveis, banco Postgres, domínio e a conta em reais. A tabela “Chaves sem equivalente” lista o que não existe aqui, e “Quando vale ficar no Railway” diz quando ficar é a decisão certa.

Há um motivo extra para revisar essa configuração agora. Na doc de Config as Code, consultada em 07/10/2026, o Railway marcou o formato como legado (“Config as Code is deprecated. Prefer Infrastructure as Code”), com os arquivos existentes funcionando para serviços antigos até 01/12/2026. Quem ainda depende do railway.json ou do railway.toml vai ter que mexer nele de qualquer jeito; é a hora de decidir onde ele vai morar.

Se você ainda está comparando opções, comece por Alternativa ao Railway no Brasil e pelo comparativo Vercel, Railway, Heroku ou Upuai.

Antes de migrar: o que o seu projeto usa no Railway

Faça um inventário antes de tocar em qualquer arquivo. Para cada serviço, anote:

  • Comandos: o que é web, o que é worker, e o build e o start de cada um.
  • Bancos: a versão maior do Postgres (15, 16, 17 ou 18) e as extensões ativas (SELECT extname FROM pg_extension;).
  • Volumes: o caminho montado (requiredMountPath) e o tamanho ocupado.
  • Variáveis: as que usam referência, como ${{Postgres.DATABASE_URL}} ou ${{ shared.API_KEY }}, e as fornecidas pela plataforma, como RAILWAY_PUBLIC_DOMAIN.
  • Domínios e DNS, serviços com cronSchedule, e numReplicas, region e multiRegionConfig, se existirem.

O inventário decide quantos serviços o projeto precisa na Upuai (banco conta como serviço) e se algo cai na categoria sem equivalente.

Do railway.json ao upuai.toml, chave por chave

Os dois arquivos declaram build e deploy dentro do repositório. O upuai.toml fica em <rootDirectory>/upuai.toml, e o rootDirectory é o diretório de trabalho dos comandos. Precedência: o que você editar na UI vence o toml, que vence o Procfile. A doc está em /docs/upuai-toml; as chaves abaixo foram conferidas no schema público do Railway e no upuai-toml-v1.json em 07/10/2026.

Um railway.json típico:

{
  "$schema": "https://railway.com/railway.schema.json",
  "build": {
    "builder": "RAILPACK",
    "buildCommand": "pnpm build"
  },
  "deploy": {
    "startCommand": "node dist/server.js",
    "preDeployCommand": "pnpm prisma migrate deploy",
    "preDeployTimeoutSeconds": 300,
    "healthcheckPath": "/health",
    "healthcheckTimeout": 120,
    "numReplicas": 1,
    "sleepApplication": true
  }
}

O mesmo serviço em upuai.toml:

#:schema https://upuai.com.br/schemas/upuai-toml-v1.json

[build]
builder = "railpack"
buildCommand = "pnpm build"

[deploy]
startCommand = "node dist/server.js"
releaseCommand = "pnpm prisma migrate deploy"
releaseTimeoutSeconds = 300
healthCheckPath = "/health"
healthCheckTimeout = 120

O sleepApplication sumiu de propósito; a tabela “Chaves sem equivalente” explica.

Chaves com equivalente direto

railway.jsonupuai.tomlObservação
build.builder (RAILPACK, DOCKERFILE, NIXPACKS)build.builder (railpack, dockerfile)Mesmos builders, em minúsculas. NIXPACKS vira railpack; se o build dependia de nixpacksPlan ou nixpacksConfigPath, vire Dockerfile (ver a tabela “Chaves sem equivalente”).
build.buildCommandbuild.buildCommandMesmo nome.
build.dockerfilePathbuild.dockerfilePathRelativo ao rootDirectory.
deploy.startCommanddeploy.startCommandCom vários processos, use [processes.<nome>].
deploy.preDeployCommanddeploy.releaseCommandRoda antes do rollout, na mesma imagem e variáveis; se falhar, o tráfego não troca.
deploy.preDeployTimeoutSecondsdeploy.releaseTimeoutSeconds10 a 1800 segundos; padrão 300.
deploy.healthcheckPathdeploy.healthCheckPathC maiúsculo. Sem a chave, o padrão vem do framework detectado.
deploy.healthcheckTimeoutdeploy.healthCheckTimeout0 a 600 segundos.
deploy.numReplicasprocesses.<nome>.instancesO schema aceita 1 a 50; o plano limita: 1 no teste, 5 no Starter, 8 no Plus, 10 no Pro, 25 no Business.

Com web e worker no mesmo serviço:

[processes.web]
command = "node dist/server.js"

[processes.worker]
command = "node dist/worker.js"
instances = 2

Chaves que viram tela ou comando

railway.jsonNa UpuaiObservação
deploy.cronScheduleAba Agendador do serviçoSem chave no toml v1.
deploy.requiredMountPathAba Volume ou upuai volume add --path /data --size 5Disco ReadWriteOnce: o serviço roda com uma única réplica.
deploy.limitOverrideBotão Ajustar RecursosDentro do envelope do plano.

Chaves sem equivalente

railway.jsonPor que não existeO que fazer
deploy.sleepApplicationTodo serviço roda com no mínimo 1 instância.Conte o serviço o mês inteiro; se ele vive dormindo, veja “Quando vale ficar no Railway”.
deploy.region, deploy.multiRegionConfigUm datacenter, em Belo Horizonte.Precisa de várias regiões? Fique no Railway.
deploy.restartPolicyType, restartPolicyMaxRetriesSem chave no toml v1; o roadmap da doc lista restartPolicy.Nada a configurar hoje.
deploy.overlapSeconds, drainingSecondsSem chave no toml v1.O health check decide quando a versão nova recebe tráfego.
build.watchPatternsO auto-deploy segue o rootDirectory.Ver a regra abaixo.
environmentsO toml v1 é por serviço, não por ambiente.Variáveis ou UI do serviço.
nixpacks*, railpackVersion, runtime, registryCredentials, ipv6EgressEnabledSem chave no toml v1.Plano Nixpacks customizado vira Dockerfile.

A regra de auto-deploy, no lugar do watchPatterns: um push deploya o serviço quando toca o rootDirectory dele ou um caminho que não pertence ao rootDirectory de nenhum outro serviço. Mexer em apps/api deploya só a API; mexer no lockfile, numa config da raiz ou em packages/* deploya todo mundo.

Variáveis de ambiente e referências entre serviços

As variáveis entram pela tela do serviço, com Importar .env (cole o export do Railway) ou pelo Editor raw, e pelo CLI com upuai variables set KEY=VALUE. Três ajustes:

  1. Referências. No Railway, ${{Postgres.DATABASE_URL}} aponta para outro serviço, ${{ shared.API_KEY }} para uma variável compartilhada e ${{ PORT }} para o próprio. A Upuai usa a mesma sintaxe ${{...}}, mas o alvo precisa existir aqui: troque Postgres pelo nome do seu banco na Upuai. Se a referência não resolve, o editor avisa “Referência vai literal pro container” antes de aplicar; é o erro que só apareceria no primeiro request em produção.
  2. RAILWAY_*. RAILWAY_PUBLIC_DOMAIN, RAILWAY_PRIVATE_DOMAIN e RAILWAY_TCP_PROXY_PORT não existem aqui. Um grep -r RAILWAY_ . mostra onde trocar pelo endereço do serviço na Upuai.
  3. Segredos vão de painel a painel, sem commit. O toml v1 não tem bloco de variáveis.

O banco Postgres: dump no Railway, restore na Upuai

A ordem abaixo evita os dois erros mais comuns: versão diferente e extensão faltando.

  1. Crie o banco na Upuai com a mesma versão maior do Railway (15, 16, 17 ou 18, escolhida na criação). Versão igual tira a dúvida.
  2. Ative as extensões antes do restore: upuai db extensions enable postgis (ou pgvector, ou a que o inventário apontou), pelo painel ou pelo CLI, sem reiniciar. Restore que encontra CREATE EXTENSION sem a extensão para no meio.
  3. Gere o dump no Railway: pg_dump -Fc "$DATABASE_URL" -f app.dump.
  4. Libere o acesso público do banco só para o seu IP: upuai db public enable --allow 203.0.113.10/32.
  5. Restaure: upuai db restore -f app.dump. É um pg_restore com --clean --if-exists --no-owner --no-acl, e pede confirmação antes de sobrescrever.
  6. Confira e feche: upuai db connect, contagem das tabelas principais, uma query real do app. Depois, upuai db public disable.

Esse é o ensaio. Na virada, você repete do passo 3 ao 6 com a escrita pausada (ver “Domínio e a virada sem susto”). Para backup, retenção por plano e redimensionamento, leia PostgreSQL gerenciado no Brasil e /docs/postgres.

Domínio e a virada sem susto

  1. Teste no endereço da Upuai primeiro. Rode o app nele com o banco do ensaio, bata nas rotas que importam e leia os logs. Nada de DNS ainda.
  2. Baixe o TTL do registro DNS para 300 segundos (ou o mínimo do provedor) um dia antes. A troca propaga em minutos, e a volta também.
  3. Adicione o domínio: upuai domain add app.exemplo.com.br mostra os registros DNS a criar e verifica sozinho quando eles propagam.
  4. Dump final com a escrita pausada. Coloque o app do Railway em somente leitura ou manutenção, rode o dump e o restore finais, confira, e só então troque o DNS.
  5. Mantenha o Railway no ar por alguns dias. Se algo aparecer, a volta é trocar o registro de novo.

A conta em reais: uso por segundo em dólar contra plano fixo em real

O Railway cobra o uso por segundo, em dólar, com um mínimo mensal por plano. A Upuai cobra um plano fixo em real, que limita o que você reserva no workspace. Nenhum é mais barato em abstrato; por isso o cenário é declarado.

Preços do Railway (página de preços ao vivo, consultada em 07/10/2026):

  • Free: US$ 0 por mês, com 30 dias de teste e US$ 5 em créditos; depois, US$ 1 de uso incluído por mês, sem cobrança. Até 1 vCPU e 0,5 GB por serviço, 0,5 GB de volume.
  • Hobby: mínimo de US$ 5 de uso, que já inclui US$ 5 de crédito. Até 48 vCPU e 48 GB por serviço, volume de até 5 GB, workspace de uma pessoa (membros só no Pro), 7 dias de logs.
  • Pro: mínimo de US$ 20, com US$ 20 de crédito e assentos ilimitados.
  • Tarifas: memória US$ 0,00000386 por GB por segundo; CPU US$ 0,00000772 por vCPU por segundo; volume US$ 0,00000006 por GB por segundo; saída US$ 0,05 por GB.

Preços da Upuai (página de preços ao vivo e código do produto, 07/10/2026):

  • Teste: 15 dias, sem cartão. 2 vCPU, 2 GB, 4 GB, 1 projeto com 2 serviços de 1 instância, 1 ambiente.
  • Starter: R$ 19 por mês (R$ 190 por ano). 4 vCPU, 4 GB, 10 GB, 2 projetos, 3 serviços por projeto, 1 ambiente, 5 domínios, logs de 24 horas.
  • Plus: R$ 49 por mês. 8 vCPU, 8 GB, 25 GB, 3 projetos, 1 ambiente.
  • Pro: R$ 99 por mês. 16 vCPU, 16 GB, 50 GB, 5 projetos, 2 ambientes (staging).
  • Business: R$ 199 por mês. 24 vCPU, 24 GB, 100 GB, 10 projetos, 3 ambientes, equipe colaborativa.

O cenário: média de 0,35 vCPU e 0,75 GB de RAM somando app e banco, 1 GB de volume e 5 GB de saída, 30 dias (2.592.000 segundos) no Hobby.

ItemContaValor
CPU0,35 × 0,00000772 × 2.592.000US$ 7,00
Memória0,75 × 0,00000386 × 2.592.000US$ 7,50
Volume1 × 0,00000006 × 2.592.000US$ 0,16
Saída5 × 0,05US$ 0,25
Total no Hobbyos US$ 5 de crédito do mínimo já estão consumidosUS$ 14,91

Em reais, com a PTAX de venda do Banco Central de 06/10/2026 (último dia útil disponível na manhã de 07/10), R$ 4,9698: R$ 74,10 e, com 3,5% de IOF, R$ 76,69. Com a PTAX de 02/10/2026 (R$ 5,2238): R$ 77,89 e R$ 80,61 com IOF. Os 3,5% são a alíquota do Decreto nº 12.499/2025 para compras internacionais no cartão; o 6,38% que ainda circula é a antiga. O spread do emissor não está na conta, e o número muda a cada fatura, porque o câmbio muda.

Do outro lado, o Starter custa R$ 19 fixos. O envelope é do workspace inteiro, somando app e banco: um serviço novo nasce com 1 vCPU e 1 GB no Starter (0,5 vCPU e 512 MB no teste), e um banco gerenciado nasce igual, então app mais Postgres do cenário cabem em 4 vCPU e 4 GB. A assinatura é no cartão de crédito, com nota fiscal (NFS-e) automática a cada cobrança. O detalhe de cada plano está na página de preços.

Quando vale ficar no Railway

  • O app cabe no Free do Railway. Se 1 vCPU e 0,5 GB por serviço bastam e o uso fica dentro do US$ 1 por mês, nenhum plano fixo compete com isso.
  • Você precisa de multirregião ou de dormir sem tráfego. region, multiRegionConfig e sleepApplication não têm equivalente na Upuai.
  • Você precisa de staging abaixo de R$ 99. Teste, Starter e Plus têm 1 ambiente; o segundo entra no Pro.
  • Um time de várias pessoas por menos de R$ 199. Equipe colaborativa é do Business; o Pro do Railway dá assentos ilimitados por US$ 20 de mínimo.

Migrar com a sua IA: a skill oficial e as decisões que continuam sendo suas

Se o app foi criado com Claude Code, Cursor ou Codex, a migração também pode ser feita por lá. O CLI da Upuai (a partir da v0.17.0) instala a skill oficial sozinho na primeira execução num projeto linkado, em .claude/skills/upuai/SKILL.md; upuai skill status mostra a versão. Fora do Claude Code, npx skills add saiph-ti/upuai-cli --skill upuai. A doc está em /docs/ai-deploy.

Com a skill, a IA conhece o upuai.toml, os comandos do CLI e o fluxo de deploy: peça a ela que converta o railway.json com as tabelas de “Do railway.json ao upuai.toml, chave por chave” e liste as variáveis a ajustar. O que ela não decide por você: a versão do Postgres, a hora de pausar a escrita, o plano que cabe no seu uso e se algum item sem equivalente é impeditivo. Se o projeto nasceu com IA, Criou um app com IA? Como colocá-lo no ar na Upuai complementa este guia.

Perguntas frequentes

Preciso reescrever código para migrar do Railway? Na maioria dos casos, não. Muda configuração: o railway.json vira upuai.toml, as variáveis são importadas e as referências RAILWAY_* e ${{...}} são ajustadas. Código que lê PORT e DATABASE_URL do ambiente roda igual.

O sleepApplication tem equivalente? Não. Todo serviço roda com no mínimo 1 instância; para não rodar, o serviço é excluído. Se o app depende de dormir para caber no orçamento, é um dos casos de “Quando vale ficar no Railway”.

Dá para testar antes de pagar? Sim: 15 dias, sem cartão. O prazo começa quando o primeiro serviço entra no ar (primeiro deploy concluído, ou primeiro banco ou bucket criado). No fim, sem plano, os serviços pausam e os dados ficam guardados por 15 dias antes de serem apagados.

Dá para migrar sem tirar o app do ar? Sem janela nenhuma, não, e desconfie de quem prometer isso. O que dá é encolher a janela: ensaio antes, TTL baixo, dump final com a escrita pausada e troca de DNS em seguida. A janela é o tempo do dump final, do restore e da propagação; os dois primeiros você mede no ensaio.

Comece pelo inventário, converta o arquivo com as tabelas, ensaie o restore e vire o domínio com o TTL baixo. 15 dias grátis, sem cartão; depois, planos a partir de R$ 19 por mês. Começar 15 dias grátis, ver os planos ou abrir a doc do CLI.

Fontes (consultadas em 07/10/2026): Railway, Config as Code · schema do railway.json · Railway, preços e planos · Railway, variáveis · Railway, regiões · PTAX do Banco Central (venda, 02/10 e 06/10/2026) · Decreto nº 12.499/2025 (IOF de 3,5%) · Upuai: /docs/upuai-toml, /docs/postgres, /docs/upuai-cli, /docs/ai-deploy e /pricing.

Faça deploy no Brasil em 5 minutos

PaaS brasileira, preços em Real, infraestrutura LGPD-native.

Ver planos

Artigos relacionados