Moving from Render
Move a Render web service to Deplane with one command, or from the dashboard (From the dashboard): 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.
From the dashboard
New app → Import from another platform (/import, or /import/render with Render already picked) does the same import without the CLI, in four steps:
- Connect. Create a Render API key (the Render Dashboard, Account Settings → API Keys → Create API Key), paste it into the masked field and press Read. Render has no read-only keys: the key can change everything your account can, in every workspace you belong to. Deplane only reads with it (GET requests), inside the request that carries it, and never stores it. Delete the key in the same place when the import is done.
- Pick. The page lists the services the key can see (at most 100, with a filter box), with their kind. Pick the web service to import, or type its ID (
srv-...) or name. A link/import/render?ref=NAMEfills it in, and a key that sees exactly one service checks it at once. Picking runs the check: the report, nothing created. - Review. The same ✓ / ⚠ / ✗ report as
--check, with the Plan section and the allow list rule, then Code and name, filled in: the repository and branch Render builds, preselected when the repository is among the ones you gave the Deplane GitHub App access to (the match is made only inside your own grants; otherwise the page shows the repository's name and a Connect GitHub link that brings you back), with the commit Render runs when the repository has it. An image service deploys the image it runs instead, when it is public; a private registry is a ⚠ line, and the page asks for a repository instead. The Deplane app's name is the service's, made a Deplane name, with a suffix when a team already holds it. Import asks for your passkey. - Import. The page follows each step (the Postgres check, the app with its secrets, release command, instances, workers and cron jobs, the database copy, the Redis, then the GitHub connection and the build, or the image), lists what exists so far, and ends with the live address, the switch-over checklist and the reminder to delete the key. Cancel import stops it between two steps.
A failed or cancelled import has Delete what it created: the app, the database and the Redis this import made, nothing else, after your passkey. Then import again. The rest is as for Heroku's From the dashboard: the code comes from GitHub (previews off) or a public image, the key is used inside the requests that list, check and start the import and dropped, only you signed in to the dashboard can do it, and a team runs one import at a time.
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.