Moving from Render
Move a Render web service to Deplane with one command: deplane import render reads the service on Render, with the background workers and cron jobs built from the same repository, shows what moves and what stays, then creates the Deplane app with its secrets, workers, cron jobs and release command, copies the Postgres database, adds a Redis for a Key Value, and deploys your code. Render keeps serving your users until you switch.
The command runs on your own computer with your Render API key, which never leaves it. It only reads Render: nothing there is changed. The command and its flags are in the CLI reference, and every error has a fix in Troubleshooting and error codes. It works like Moving from Heroku, which explains the switch-over in more detail.
Before you start
- Install the Deplane CLI and run
deplane login. - Have the service's code in a folder: a checkout of the repository Render deploys, at the commit it runs. The report shows that commit and whether your folder is at it.
- Create a Render API key: in the Render Dashboard, Account Settings → API Keys → Create API Key.
The Render API key. Render has no read-only keys: a key can do everything your account can, in every workspace you belong to. The CLI only reads with it (GET requests to api.render.com). Delete the key when the import is done.
Give the key to Deplane in one of three ways, never as a flag:
- run
deplane import render my-web --checkin a terminal and paste it at the hidden prompt; - set it for one command:
RENDER_API_KEY=rnd_... deplane import render my-web --check(it lands in your shell history; the prompt does not); - or pipe it in from a password manager:
op read op://Private/render/key | deplane import render my-web --check.
A key piped on stdin wins over RENDER_API_KEY. The CLI says which one it used, never the key itself. It is never written to disk, never printed, left out of --debug, and never sent to Deplane.
Let Deplane reach the database
Render's DATABASE_URL is the database's internal address, which only works inside Render. The import copies the database through its external address instead, which Render controls with the database's IP allow list (Networking → Access Control on the database's page):
- By default, a Render database accepts connections from any address (
0.0.0.0/0, always over TLS). Nothing to do. - If the list is empty, external access is off: the report has a ✗ line. Add the addresses the line shows (Deplane's importer addresses), run the command again, and remove them after the switch.
- If the list has other addresses only, the report has a ✗ line naming the ones to add.
Without a Deplane login, --check cannot read Deplane's addresses: it says so, and the import checks them before it creates anything.
Check first
$ deplane import render shop --check
Render service shop (web service, region frankfurt, repo github.com/acme/shop@main, commit 1a2b3c4) → Deplane app shop
Code
✓ Deploys /home/me/shop with Railpack: Detected Node 22, port 3000.
✓ Your folder is at commit 1a2b3c4, the one Render runs.
Processes
✓ web: 2 × standard on Render → 2 large instance(s).
✓ pre-deploy command → release command `npm run migrate`.
✓ shop-worker (background worker): 1 × starter on Render → worker shop-worker, 1 small instance(s): `node worker.js`.
✓ nightly (cron job): `0 3 * * *` on Render → cron job nightly, `0 3 * * *` (UTC), on a small instance: `node nightly.js`.
Data
✓ Postgres (shop-pg, basic_1gb, Postgres 16): copied into a new Deplane database shop-db ...
⚠ Key Value shop-cache (starter): a new Deplane Redis shop-redis ... Its data is not copied ...
Config vars
✓ 3 copied as secrets: APP_URL, SECRET_KEY_BASE, SENDGRID_API_KEY.
✓ Not copied, Deplane sets them: DATABASE_URL, PORT, REDIS_URL.
Domains
⚠ www.shop.example points at Render ... It moves when you switch ...
Plan
✓ Fits your Team plan: after the import the team uses 5 of 40 instances and 5.8 GB of 16 GB memory.
Nothing was changed (--check). Run the command again without --check to import.
✓ is what moves as it is, ⚠ is what you should know or do yourself, and ✗ is what stops the import. --check --json prints the same report as one JSON document. Then run the command again without --check (in a terminal it asks first; from a script, add --yes). The flags are the same as for Heroku: --source DIR, --name NAME, --check, --yes.
What moves
| On Render | On Deplane |
|---|---|
| The web service | The app. Instances as on Render (with autoscaling, its maximum). Railpack starts your Procfile's web line or your Dockerfile's CMD; the report warns when that differs from Render's start command. |
| Background workers built from the same repository, branch and root directory | Workers, with the same start command and instances. |
| Cron jobs built from the same repository, branch and root directory | Cron jobs, with the same schedule (UTC on both). Day and month names (MON-FRI) and 7 for Sunday are converted to Deplane's numbers; a schedule Deplane cannot run is a ✗ in the report, before anything is created. |
| The pre-deploy command | The release command. |
| Instance types | Free and Starter (512 MB): small. Standard (2 GB): large. Larger: large, with a warning that Deplane has less memory (2 GB at most). See Limits. |
| Environment variables and linked environment groups | Secrets. The service's own value wins over a group's. A worker's or cron job's variables are added; where one sets a name differently from the web service, the web service's value is used and the report names it. Not copied: RENDER, RENDER_*, IS_PULL_REQUEST, PORT, and the DATABASE_URL and REDIS_URL that Deplane sets. |
Render Postgres (DATABASE_URL) | A new Deplane database, copied once through the external URL (copy mode), attached as DATABASE_URL. |
Render Key Value (REDIS_URL), up to 256 MB | A new, empty Deplane Redis (Valkey 8, 256 MB), attached as REDIS_URL. |
| The code | Your folder, built by Railpack, or by your Dockerfile if it has one. |
What does not move
- Redis data is not copied. A Key Value larger than 256 MB gets no Deplane Redis.
- Secret files are listed by name and not copied: Deplane has no secret files. Store each as a secret and write it to a file in your start command.
- Variables that use Render's private network (hosts like
dpg-...-a,red-...or another service's name) are copied, with a warning: they do not resolve on Deplane. - Suspended workers and cron jobs are listed and not created.
- Disks are not copied: add a disk and copy the files yourself.
- Static sites are not imported: deploy their folder with
deplane launch. Private services become apps with a public URL. - Deplane runs in one region, in Europe.
Switch over
The first import is a rehearsal: Render keeps serving, and writes made there after the copy are not in the Deplane database. When the Deplane app works:
- Before the day: run
deplane domains add HOSTNAME --app APPfor each custom domain and add the TXT record it shows. Make sure your plan has room for one more database (the report's Plan section says if it does not). - Stop writes on Render: suspend the web service and its workers and cron jobs (each service's Settings → Suspend Service). Render has no maintenance mode, so the site is down from here until DNS moves.
- Copy the data again and move the app to the copy in one release:
``sh
deplane db import --name APP-db-final --mode copy --yes # paste the External Database URL at the prompt
deplane db switch APP-db-final --from APP-db
``
- Switch DNS to the target
deplane domains addshowed, and wait for the certificate (deplane domains check HOSTNAME --app APP). - Keep the Render services suspended until the app has run well on Deplane, then delete them. Remove Deplane's addresses from the database's allow list.
- Delete the rehearsal's database:
deplane db destroy APP-db. - Delete the Render API key in Account Settings → API Keys.
Limits
The Heroku import's limits apply: Postgres up to 5 GB and versions as for every Postgres import, a new 256 MB Redis without its data, 10 workers and cron jobs per app, sizes up to 2 GB, and copying the database needs a person logged in to the CLI. The import is built on Render's public API; tell support@deplane.io if Render answers something the CLI does not expect.
This page is also available as Markdown. AI agents can start at /llms.txt.