How to Migrate an Application from Render to xCloud
Updated September 24, 2026 · 17 min read
This guide shows you how to move a Render workload to xCloud. You will inventory each Render service, choose xCloud’s native Git or Docker workflow, move configuration and state, validate on a temporary domain, and then cut over DNS with a rollback window. It is for application owners who can access the source repository, the Render workspace, the DNS zone and the destination server. If you are still deciding, see xCloud vs Render first.
Keep Render running until the xCloud deployment, data, background processes, schedules, HTTPS and production traffic have all been verified. This process does not guarantee zero downtime.
If you are moving a WordPress site rather than an application, use Migrate an existing WordPress website in xCloud instead.
Choose the correct xCloud deployment path
Use native Git for a supported, single web application. Use Docker Compose for unsupported runtimes or workloads that need several cooperating services. A Render project does not map automatically to one xCloud site.
| Render component | xCloud destination | Migration note |
|---|---|---|
| Node.js or PHP web service | Native Git deployment | Recreate the branch, build script, start command, port, environment and database connection. xCloud’s native Git flow currently supports Node.js and PHP application types. |
| Python, Ruby, Go, Rust or another runtime | Custom Docker application from Git | xCloud may detect these runtimes, but its native Git flow does not support them. Create a tested Docker Compose definition that references an image or builds from the application’s Dockerfile. |
| Docker web service | Custom Docker application from Git | Create a Compose definition that references the existing image or Dockerfile, then preserve the exposed application port, health behaviour and runtime environment. |
| Multiple web, private or worker services | Docker Compose on a Docker + NGINX server | Define each process as a separate service. Map only the intended public port to the primary domain. |
| Background worker | Docker Compose service | Do not attach a public domain to a process that should not accept incoming traffic. |
| Render cron job | xCloud cron job | Translate the schedule, command, user, working directory, environment and container context. Render evaluates cron schedules in UTC and allows no more than one active run per job. |
| Render PostgreSQL | An external PostgreSQL service, or a deliberately self-managed Docker database | xCloud’s native database guide documents MySQL and MariaDB, not a managed PostgreSQL replacement. Use a logical export and a destination that supports the required PostgreSQL version and extensions. |
| Render Key Value | A compatible Redis or Valkey destination | Render does not document a downloadable Key Value backup. Plan and test a client-driven transfer if the data must move. |
| Render persistent disk | Docker named volume or eligible bind mount | Export only the contents below Render’s configured mount path. Render disk snapshots are recovery artifacts, not documented portable exports. |
| Render custom domain and managed TLS | xCloud domain and a newly issued certificate | The Render-managed certificate does not move with the domain. Provision HTTPS on xCloud after DNS points to the destination. |
Prerequisites
- Owner or administrator access to the Render workspace and every service being moved.
- Access to the application’s source repository and the production branch.
- A current inventory of Render web services, private services, workers, cron jobs, databases, Key Value instances, disks, domains and environment groups.
- A server connected to xCloud. Docker deployments require the Docker + NGINX stack.
- Repository access configured in xCloud for private source code. See how to integrate a Git provider with xCloud.
- Access to the DNS zone for every production domain.
- A tested backup or portable export for each stateful component.
- A destination for every database, queue, cache, object store and persistent directory.
- A maintenance window for the final sync and a short write freeze if production data can change.
- Enough time to validate the xCloud deployment before changing DNS.
- A rollback owner who can restore the previous DNS records and re-enable writes on Render.
Step 1: Inventory the Render project
Record every Render resource before creating the xCloud destination. In Render, open each service and capture its type, repository, branch, root directory, runtime or Docker source, build command, pre-deploy command, start or Docker command, health-check path, environment references, disk mount path, custom domains and auto-deploy behaviour.
If the project uses a Blueprint, download or copy its render.yaml from the Render Dashboard. Treat it as an inventory, not as an xCloud deployment file. A generated Blueprint omits environment-variable values and uses sync: false for secrets, so inspect service-local variables, environment groups and secret files separately.
Expected result: You have a component list that accounts for every public service, internal service, worker, schedule, data store, persistent path, domain and secret source.
Step 2: Classify every service by its destination
Assign each Render component to one row in the deployment-path table above. A single supported Node.js or PHP web service can use xCloud’s native Git flow. Use a custom Docker application from Git when the runtime is not supported by native Git. Use Docker Compose when several processes must share a network, configuration or persistent storage.
Do not expose a Render private service or worker as a public web service merely to fit the destination. Recreate private dependencies inside the Compose network or point the application to an appropriately secured external service.
Expected result: Every source component has one named xCloud or external destination, and no Render-only private hostname remains in the plan.
Step 3: Build a configuration inventory without copying secrets into Git
Create a key-only inventory of environment variables and secret files. Render values can come from the service, an environment group, render.yaml, a generated value, another service or a managed database. Record the final purpose and destination value for each key, but do not commit credentials to the repository or migration notes.
Replace Render-specific references such as internal service hostnames, generated database URLs, Key Value URLs, PORT assumptions and /etc/secrets/ file paths. Render recommends binding web services to 0.0.0.0 and its PORT variable, with 10000 as the default. Configure the application for the host and port expected by the selected xCloud flow instead of carrying that default forward without review.
Expected result: You have a secret-safe mapping from every required key or file to its xCloud or external destination value.
Step 4: Prepare portable backups and exports
Create an export that can leave Render for every stateful component. Do this before modifying or deleting any Render resource.
- Render PostgreSQL: Use a downloadable logical export where the plan supports it, or use
pg_dumpfrom an authorized client. Point-in-time recovery creates another Render database and is not an external migration export. Include every required database and schema, then verify that the export can be read. - Render Key Value: Decide whether the data is disposable, can be rebuilt, or needs a client-driven transfer. Render’s Key Value documentation does not provide a downloadable backup workflow.
- Persistent disk: Transfer files from the configured mount path with Render’s documented SSH/SFTP or Magic Wormhole route. Use the database engine’s own dump utility for a database stored on a disk.
- Application repository: Confirm that the destination branch contains every required source file, Dockerfile, Compose file, migration and dependency lock file.
Render does not retain PostgreSQL backups after the database is deleted. Keep the source database and downloaded exports until the xCloud application has passed production validation.
Expected result: Each stateful component has a portable, verified export plus a separate Render-side recovery point where the service supports one.
Step 5: Prepare the application for xCloud
Make the repository deployable through the selected xCloud path. For native Git, confirm the supported app type, branch, deploy script, web root or serving mode, start command and application port. For Docker, create a Compose definition that uses build: to reference the application’s Dockerfile or image: to reference an existing image. Confirm that the complete Compose project starts outside Render and does not depend on Render-only hostnames, secret injection, disk paths or service references.
Move any Render pre-deploy task into a controlled xCloud deployment step only after checking its behaviour. Render runs pre-deploy commands on separate compute, and their filesystem changes do not reach the deployed service. Database migrations should be safe to rerun or protected against concurrent execution.
Expected result: The repository contains a destination-ready deployment definition with no required Render-only runtime dependency.
Step 6: Create the xCloud destination on a temporary domain
Deploy the web application before attaching the production domain. In xCloud, open Sites, choose New Site, and use one of these paths:
- Select the native Git deployment flow for a supported Node.js or PHP application, connect the repository, choose the branch and review the detected configuration.
- Select Custom Docker → Docker Compose From Git for a containerized deployment. Use a Docker + NGINX server, enter the Compose filename, let xCloud detect the exposed ports, and select the primary service port that should receive the domain. See how to deploy a custom Docker application from a Git repository.
Choose xCloud’s generated demo or staging domain. Do not change production DNS yet.
Expected result: xCloud completes an initial deployment and the application responds on a temporary HTTPS URL.
Step 7: Configure environment variables and service connections
Enter the destination environment in xCloud and restart or redeploy the application. Set production-like values for the temporary environment, including database URLs, cache or queue URLs, object-storage credentials, callback origins, allowed hosts, encryption keys and application base URLs.
For native Git, use the environment configuration offered during site creation or the site’s Environment area. For Docker Compose, provide the environment file or variables required by the Compose services. Keep secrets out of public repositories.
Expected result: The application starts without missing-variable errors and connects only to intended test or destination services.
Step 8: Restore databases and persistent files
Restore each portable export into its destination, then update the application connection values. Use the destination database provider’s documented restore procedure and verify row counts, schema objects, required extensions and application-level reads. Copy exported files into the exact persistent path expected by the destination application.
For Docker, store persistent data in named volumes or eligible bind mounts included by xCloud’s Docker backup system. Do not copy a Render disk snapshot as though it were a portable filesystem export. Render documents snapshots as in-place recovery for the full disk state.
After restoring data and files, create an xCloud backup where the selected site type supports it. See Back up and restore Docker apps. Do this before enabling production workers, schedules or traffic.
Expected result: The temporary deployment reads the restored data and files, and a destination-side backup exists before cutover.
Step 9: Recreate workers and scheduled jobs
Start asynchronous processes only after the restored data is stable. Define background workers as separate Docker Compose services without a public domain, or as Supervisor processes for a native Git site. Start each one only long enough to process a controlled test item.
Recreate each Render cron job in the xCloud cron interface at the server level or under Site → Tools → Cron Jobs. Translate the job’s full execution context, not only its command: select the intended site user, use an absolute working directory, load the required environment, and run containerized jobs inside the correct Compose service. Convert the Render UTC schedule to the timezone used by the destination. Render prevents overlapping active runs for the same job, but you should not assume the destination has identical behaviour. Add an application lock when concurrent execution would be unsafe.
Use Run Now and View Output for a controlled test where the job is safe to run. After testing, disable the xCloud workers and cron jobs until the final synchronization is complete.
Expected result: Each worker processes a test item once, and each schedule completes with the expected output and no duplicate execution.
Step 10: Validate the temporary deployment
Complete an end-to-end validation before DNS cutover. Check all applicable items:
- The public application loads and its health endpoint returns the expected status.
- Login, logout, password reset, uploads, downloads, forms, search and API requests work.
- Database reads and writes reach the destination database.
- Persistent files remain available after a redeploy or controlled restart.
- Workers consume test jobs and record the expected result.
- Cron jobs use the intended timezone and do not overlap unsafely.
- Private service calls resolve through the new internal or external addresses.
- Transactional email, webhooks, OAuth callbacks and third-party allow lists use the temporary or future production origin as intended.
- Logs contain no Render-only hostnames, missing secret files, connection failures or write attempts to ephemeral paths.
Expected result: The xCloud deployment passes the same critical user journeys and background-process checks as the Render deployment.
Step 11: Prepare the production cutover
Lower DNS TTL early enough for the previous value to expire before the maintenance window. Record the current authoritative DNS answers and keep a copy of every record you will change. Add the production domain in xCloud only when the application is ready to receive it; see how to go live from a staging domain.
For a stateful application, announce a short write freeze or maintenance window. Put both environments into maintenance or read-only mode, block writes through the temporary domain, and pause workers and cron jobs on both platforms. Run the final database export, file sync and destination restore, then perform a controlled validation against xCloud before allowing production writes.
Do not promise zero downtime. Render persistent disks disable Render’s zero-downtime deploy behaviour, and any stateful final sync can require a visible maintenance period.
Expected result: Writes and asynchronous processing are paused on both platforms, the destination contains the final production state, and the rollback records are ready.
Step 12: Switch DNS and issue HTTPS
Point the production domain to the destination records shown by xCloud. Change only the records required for the xCloud site, then verify the authoritative DNS response instead of relying only on a browser or local cache.
Install a new certificate through xCloud’s SSL controls after DNS resolves to the destination; see how to install a Let’s Encrypt SSL certificate. Render’s managed certificate is not documented as exportable and does not follow the domain. If the domain uses restrictive CAA records, confirm that they permit the certificate authority used for the destination.
Keep the Render services available but read-only while traffic moves. After the production domain and application checks pass, enable only the xCloud workers and schedules, then remove maintenance mode on xCloud.
Expected result: The production domain resolves to xCloud, HTTPS is valid, and requests no longer depend on Render infrastructure.
Verification checklist
The migration is complete only when the application, data, background processes and domain all work from xCloud. Verify from more than one network or DNS resolver where practical.
- The authoritative DNS response points to the xCloud destination.
- The production certificate is valid for every required hostname.
- Critical frontend and API journeys pass on the production domain.
- New database writes appear only in the destination database.
- Persistent uploads survive a controlled restart or redeploy.
- Workers process new jobs once.
- Cron jobs run at the intended time and complete successfully.
- Email, webhooks, OAuth and third-party callbacks accept the production domain.
- xCloud backups include the intended database, files or Docker volumes for the selected site type.
- Monitoring and logs show no calls to Render internal hosts or decommissioned services.
Keep Render available through the agreed rollback window. Remove it only after stakeholders accept the xCloud deployment and the latest backups have been verified.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The app deploys but does not answer HTTP requests | The service still binds to Render’s host or PORT=10000, or xCloud routes to the wrong Docker port |
Bind to the host and application port required by the destination. In Docker, select the service port that actually serves HTTP. |
| A native Git deployment rejects the runtime | The application uses Python, Ruby, Go, Rust or another runtime outside xCloud’s native Git support | Create a tested Docker Compose definition that references an image or builds from the application’s Dockerfile, then deploy it on a Docker + NGINX server. |
| The app starts but cannot reach a database or internal service | The environment still contains a Render internal URL or private hostname | Replace it with the destination connection value, verify network access and allow lists, then restart the dependent services. |
Secrets are missing although render.yaml was copied |
Generated Blueprints omit secret values, and environment groups or secret files were not inventoried | Recheck service-local variables, linked environment groups and secret files. Enter destination values through xCloud’s environment controls. |
| PostgreSQL restore is incomplete | The export covered only one database or schema, or required extensions were not prepared | Recreate the export for every required database and schema, prepare compatible extensions, restore again and compare application-level data. |
| Files disappear after a redeploy | Data was written outside a persistent Docker volume or eligible bind mount | Move runtime data to an explicitly persistent path, restore the file export and test another controlled redeploy. |
| A worker is publicly reachable | It was modelled as a web service instead of a non-public process | Remove the public route and run it as a separate Compose service. |
| A cron job runs at the wrong time | Render’s UTC schedule was copied without checking the destination timezone | Convert the schedule deliberately and verify the next run time. |
| A cron job overlaps | The destination does not reproduce Render’s single-active-run behaviour | Add an application or distributed lock and test it before enabling the production schedule. |
| HTTPS issuance fails | DNS has not reached xCloud, proxying interferes, or CAA records do not permit issuance | Verify authoritative DNS, temporarily remove incompatible proxying where required, review CAA and retry issuance. |
| Some users still reach Render | Cached DNS responses still use the old TTL | Keep Render healthy, wait for the previous TTL to expire, and check authoritative plus public resolver responses before decommissioning. |
Common mistakes
- Treating a Render project as one service. Render can separate the web process, worker, cron job, private service, database, Key Value instance and disk. Missing one component causes a partial migration.
- Using native Git for every runtime. xCloud’s native Git flow supports Node.js and PHP application types, not every runtime Render supports.
- Assuming
render.yamlcontains secrets. Generated Blueprints intentionally omit secret values. - Using a recovery snapshot as a portable export. Render PostgreSQL point-in-time recovery and disk snapshots restore inside Render. They are not documented migration packages.
- Copying only application files. Stateful applications also need database exports, persistent disk contents, queues, caches and object storage decisions.
- Turning on workers before the final sync. This can send duplicate notifications, consume jobs twice or write to the wrong database.
- Changing DNS before testing HTTPS and state. Validate through the temporary xCloud domain first.
- Deleting Render resources too early. Keep the source and exports through the rollback window.
Rollback guidance
Rollback means returning traffic and writes to Render while the source is still intact. If a blocking issue appears during the cutover:
- Put both environments into maintenance or read-only mode and pause workers and cron jobs on both platforms.
- Capture any write delta accepted by xCloud after the final sync.
- Decide which database is authoritative, then apply or explicitly discard the xCloud delta before resuming writes. If reverse synchronization is unavailable, rollback may require accepting data loss.
- Restore the previous DNS records from the saved copy.
- Confirm that authoritative DNS points back to Render and wait for traffic to drain from xCloud.
- Re-enable the Render web service, writes, workers and cron jobs in a controlled order.
- Keep the failed destination and its logs for diagnosis, but do not let it continue processing production jobs.
A DNS rollback does not merge data automatically. Plan the write freeze and reconciliation process before cutover so you know which environment is authoritative.
Frequently asked questions
Can I import render.yaml directly into xCloud?
No. Use it as a source inventory. Render-specific service types, plans, regions, generated references, private networking and secret handling must be translated to xCloud’s native Git or Docker workflow.
Should I use native Git or Docker on xCloud?
Use native Git for a supported single Node.js or PHP web application. Use Docker for unsupported runtimes, and Docker Compose for multi-service applications, background processes or persistent-volume requirements.
Does xCloud replace Render PostgreSQL automatically?
No. xCloud’s native database documentation covers MySQL and MariaDB. Choose a compatible external PostgreSQL destination or deliberately run PostgreSQL in Docker, then use a logical export and restore.
Can I move a Render persistent disk snapshot to xCloud?
Render documents disk snapshots for in-place recovery, not as downloadable migration artifacts. Transfer ordinary files from the mounted path through Render’s documented file-transfer methods, and use a database-aware export for any database stored on the disk.
Will the migration have zero downtime?
Do not assume it will. A stateful application normally needs a short write freeze and a final synchronization. DNS caches can also send traffic to both platforms during the transition.
When can I delete the Render services?
Only after the production domain, HTTPS, application flows, destination data, workers, cron jobs, backups and monitoring have passed validation and the rollback window has ended.
Related xCloud documentation
- Deploy Git projects in one click with xCloud
- Deploy a custom Docker application from a Git repository
- Deploy custom Docker with xCloud
- Add an external database on xCloud
- Create a database for a site or web application
- Add a custom cron job in xCloud
- Back up and restore Docker apps
- Go live from a staging domain
- Install a Let’s Encrypt SSL certificate
- Migrate an application from Railway to xCloud
Render references
- Infrastructure as code
- Web services
- Private services
- Background workers
- Cron jobs
- Configure environment variables
- Deploys
- PostgreSQL backups
- Key Value
- Persistent disks
- Custom domains
- TLS certificates
If you run into any issues migrating your application from Render, feel free to reach out to our support team for help.