Docs
Get Started

Render and Kuberns are close relatives. Both deploy long-running processes from a Git repository, both give you managed databases alongside them, and both expect an explicit start command. Most of this migration is a one-to-one translation.

The two things that need thought are disks and multi-service repositories. Everything else copies across.

What maps directly

On Render On Kuberns
Web Service A service with a server resource
Background Worker A background worker resource
Repository and branch A service and environment
Build command Detected by the AI agent
Start command A Procfile command for the web process
Environment variables and groups Environment variables, scoped per environment
Managed PostgreSQL A PostgreSQL datastore
Managed Redis / Key Value A Redis queue or cache resource
Custom domains Custom domains with automatic SSL
Service logs The environment's logs

What you move yourself

  • Anything on a Render disk. This is the most important item on the page. The Kuberns documentation does not describe a persistent-disk resource, so plan for disk contents to move into a database or external object storage rather than to travel with the service. Confirm this with the Kuberns team before you migrate a service that depends on a mounted disk.
  • Cron jobs. A Render Cron Job is its own service type. Kuberns does not document a direct equivalent, so decide whether that work becomes an in-application scheduler (Celery beat, node-cron, a framework scheduler) inside a worker, or stays external. Do this before cutover, not after.
  • Private Services and internal URLs. If your services call each other over Render's private network, those addresses do not exist on Kuberns. Confirm how the services will reach each other before you rely on it.
  • Your data. Kuberns provisions an empty database. See Step 5.

Before you start

Do this per Render service, not per repository. A Render account with four services is four inventories.

For each one, record:

  • Repository, branch, and root directory.
  • Build command and start command.
  • Every environment variable, including the ones an environment group supplies.
  • Attached databases, Redis instances, and disks with their mount paths.
  • The custom domain, if it has one, and its current TTL.
  • Health check path.

If you use a render.yaml Blueprint, it holds most of this in one place and is the fastest thing to read.

Take a fresh database dump with pg_dump against the external connection string from the Render dashboard.

Do not delete anything on Render yet. It is your rollback until Step 8 is verified.

Step 1: Connect the repository

Create the service from your Git provider and select the branch Render is deploying. Deploy it as a non-production environment first, on the Kuberns-provided URL. Your live Render service is unaffected.

The Kuberns onboarding step that chooses a deployment type: Connect Custom Repository beside Use Open source Templates, with Select Your Repository active in the sidebar

If several Render services share one repository, see Step 3 before you create anything.

Step 2: Check what the agent detected

The agent reports the framework, root directory, dependency file, base image, web port, build commands, and process commands.

The Kuberns AI agent analyzing a repository: live detection log on the left, and the Setup, Analyze Repository, Configure Env, Build, and Deploy phase stepper on the right

Pay attention to the root directory if your repository has more than one deployable application in it. See agent failures if the result is wrong.

Step 3: Map multi-service repositories

Render encourages one repository to back several services, each with its own root directory. Kuberns has the structure to express the same shape:

Project          your product
└── Service      one deployable application
    └── Environment   one branch, with its own variables and resources

Two patterns work, depending on what your Render services actually are:

  • Separate applications in one repository (an API and an admin panel, different root directories) become separate Kuberns services in the same project, each pointed at its own root directory.
  • One application with several process types (a web process and a worker running the same code) becomes one service with a server resource plus a background worker resource, each with its own Procfile command.

Getting this wrong is recoverable but tedious, which is why it is worth deciding before you create the first service.

Step 4: Recreate variables and provision resources

Add your environment variables to the environment. Key names must match exactly, including case.

Watch for three groups:

  1. Environment group values. Render injects these from a shared group, so they will not appear in a single service's variable list. Collect them from the group itself or they will be silently missing.
  2. Render-generated connection strings. The database and Redis URLs Render supplied must be replaced with the values from your new Kuberns resources, not copied across.
  3. Internal service URLs. Any .internal hostname needs a new value.

The environment's Environment Variables tab listing DATABASE_URL, REDIS_URL, CELERY_BROKER_URL, and CELERY_RESULT_BACKEND, with every value masked

Create the database, cache, and queue resources from the environment's Resources tab.

The environment's Resources tab listing a SERVER, a BACKGROUND WORKER running a celery-start command, a POSTGRES database, and a redis queue, each with its plan, memory, and storage

Connection details for a database, its name, username, password, and hostname, live on its datastore overview page.

Environment variables apply on the next deploy, and saving them triggers one automatically.

Step 5: Move your data

Kuberns gives you an empty managed database and credentials to reach it. Loading the dump is your step.

# PostgreSQL
pg_restore --no-owner --no-acl \
  -h <kuberns-hostname> -U <username> -d <database> \
  render-dump.sql

Use mysql or mongorestore for the other supported database types.

Kuberns does not restore a backup into a running datastore for you, in either direction. Its own backups are dumps you download and load the same way. Test that path once now, while nothing depends on it.

Run this import twice: once now against the test environment, and once again as the final sync during cutover. The first run is where schema and extension problems surface.

Step 6: Validate before cutting over

Work through the test environment on its Kuberns URL with production-shaped data.

  • The application boots and serves requests.
  • Background workers pick up jobs, and any work that used to run as a Render Cron Job now actually fires.
  • Migrations have run.
  • Services that used to talk over the private network still reach each other.
  • Outbound integrations and webhooks reach the new environment.

The environment's Logs tab streaming logs for the web process, each line showing a timestamp, level, source, and message

Cron work is the item most often missed here, because nothing errors when a scheduled job simply never runs.

Step 7: Lower your DNS TTL

Do this a day ahead. Drop the TTL on the records you are about to change to something short, such as 300 seconds, and wait for the old TTL to expire. Your rollback speed on cutover day is set entirely by the TTL you chose the day before.

Step 8: Move the domain

Add the hostname under the environment's Custom Domains, then point DNS at the target Kuberns shows you.

Subdomain   CNAME  api    -> <Kuberns hostname shown in the dashboard>
Root domain A      @      -> <server IP shown in the dashboard>

The Domains tab before a custom domain is added: the default kuberns.site URL marked Active, an empty custom-domain list, and the Add Custom Domain button

The domain moves through DNS verification, SSL provisioning, and activation. See DNS, SSL, and activation if it stalls.

Run the final data sync immediately before the switch, while the Render service is not accepting writes.

Rollback

Keep the Render services running, with their databases attached, until you are confident. With a short TTL, rolling back is pointing DNS back at Render.

The rollback stops being clean once the Kuberns environment has taken writes, because that data then exists only on Kuberns.

Common problems

A variable is missing that you know you set. It came from a Render environment group. Group values do not appear in a service's own variable list.

The wrong application deployed from a shared repository. The root directory is wrong. Correct it in the deployment configuration.

Workers are idle. Every non-web process needs its own resource on the environment.

Scheduled work never runs. Render Cron Jobs are a separate service type and do not migrate. That work needs a new home.

Files written by the application disappear. The service depended on a Render disk. This needs external object storage.