Dawnrose

Docs Getting started

Coming from Railway, Heroku or Vercel

This page maps Railway, Heroku and Vercel to Dawnrose, so you can move an app one piece at a time. For how Dawnrose is organized, see the introduction.

Side by side

DawnroseRailwayHerokuVercel
ProjectProjectAppProject
ServiceServiceProcess type or add-onThe app itself
EnvironmentEnvironmentPipeline stageProduction, Preview
Pull request environmentPR environmentReview appPreview deployment
VariablesVariablesConfig varsEnvironment variables
Cron serviceCron scheduleHeroku SchedulerCron job
dawnrose.jsonrailway.jsonProcfilevercel.json

From Railway

Railway uses the same building blocks, so most things carry over by name.

  • References such as ${{ Postgres.DATABASE_URL }} and ${{ shared.KEY }} work as written when the services keep their names, with or without spaces inside the braces. See References.
  • Private hostnames change from <service>.railway.internal to <service>.dawnrose.internal.
  • Provided variables start with DAWNROSE_, such as DAWNROSE_PRIVATE_DOMAIN and DAWNROSE_PUBLIC_DOMAIN. Not every RAILWAY_ variable has one; see the full list.
  • railway.json isn’t read, but dawnrose.json has the same build and deploy sections and the same names for the fields it has, such as buildCommand, startCommand, preDeployCommand, healthcheckPath and cronSchedule. Copy it to dawnrose.json. Fields Dawnrose doesn’t know are ignored. Set builder to AUTO or DOCKERFILE: Nixpacks builds aren’t available.
  • CLI. up, link, run, shell, logs, add and domain have the same names in dawn, and railway variables is dawn vars.

From Heroku

  • Builds. There are no buildpacks. Dawnrose detects Node.js, Python, Go and static sites and writes a Dockerfile for them. For other languages, such as Ruby, PHP or Java, add a Dockerfile. See Builds.
  • Procfile. The web: line is the start command for Node.js and Python builds, unless you set one. Other lines aren’t read: put a release: command in the service’s pre-deploy command, and run a worker: as a second service from the same repository with that start command. A worker doesn’t need to listen on a port.
  • Add-ons. Adding a database doesn’t set DATABASE_URL on your app the way a Heroku add-on does. Add Postgres or Redis from a template and reference it: DATABASE_URL=${{ Postgres.DATABASE_URL }} or REDIS_URL=${{ Redis.REDIS_URL }}. For other add-ons, use the provider directly and keep its keys in sealed variables.
  • Dynos become replicas, each with a CPU and memory limit.
  • CLI. heroku config:set is dawn vars set, heroku logs --tail is dawn logs -f, and heroku run is closest to dawn exec, which runs in a running replica. git push heroku becomes a push to GitHub with auto-deploy on, or dawn up.

From Vercel

  • Next.js builds as a Node.js app: Dawnrose runs your build script, then your start script (next start) as a server that keeps running on $PORT. API routes run in the same server.
  • Static sites. A Vite, Create React App, Angular or Astro project with a build script and no start script is served by nginx (see Builds). There’s no fallback to index.html, so reloading a client-side route gets a 404 unless you use your own Dockerfile and nginx config.
  • Functions. A Dawnrose function is one TypeScript or Python file with no packages, and an HTTP function listens on $PORT. Anything bigger is a service. Services keep running unless you set Sleep after idle.
  • vercel.json isn’t read. Move redirects, rewrites and headers into your app. A cron job becomes a cron service, which runs a command rather than calling a path.
  • Previews become pull request environments on Hobby and Pro, deploy hooks the service’s deploy hook, and Blob storage an S3-compatible bucket.
  • CLI. vercel is dawn up, and vercel env pull is dawn vars pull > .env.

Moving a database

Add the database from a template, turn on its TCP proxy, then copy the data from your machine with the usual tools. Stop writes to the old app first. For Postgres:

pg_dump --format=custom --no-owner --no-acl "$OLD_DATABASE_URL" > app.dump
dawn shell --service Postgres
pg_restore --no-owner --no-acl --dbname "$DATABASE_PUBLIC_URL" app.dump

The Postgres template runs version 16. Other databases work the same way, with their own tools and their *_PUBLIC_URL variable. Turn the proxy off when you’re done.

Moving a domain

Add the domain to the service and create its TXT record while the CNAME still points at your old host: verification only checks the TXT record. Switch the CNAME once the app works on its generated domain. The certificate is issued when the CNAME reaches Dawnrose. See Custom domains.

Let your agent do it

With your agent connected over MCP, you can hand it the move: it creates services and databases, sets variables, deploys, reads build logs and fixes what fails.

What isn’t there yet

Dawnrose is new. Check that you don’t depend on these:

  • One region for now. The FAQ says where apps run.
  • No SLA, published uptime figure or status page.
  • No GPUs.
  • No SAML or single sign-on. People sign in with Google, GitHub or an email and password.

Checklist

  1. The app listens on 0.0.0.0 and the port in $PORT.
  2. Each process is a service with a start command.
  3. Variables are copied, secrets sealed, and values the old platform set for you, such as DATABASE_URL, are references.
  4. Data is restored, and the app works on its generated domain.
  5. Your domain points at Dawnrose, and the old app is stopped.