Migrate from Render to Bahriya

Render runs your app as a web service, background worker, or cron job, built from your repository and configured through environment groups or a render.yaml. Bahriya uses the same service shapes but deploys a container image you build, spread across the regions you choose, with configuration supplied as environment variables and secrets. This guide maps each Render concept to Bahriya and walks the move.

Updated 3 Aug 20263 min read

Render runs your app as a web service, background worker, or cron job, built from your repository and configured through environment groups or a render.yaml. Bahriya uses the same service shapes but deploys a container image you build, spread across the regions you choose, with configuration supplied as environment variables and secrets. This guide maps each Render concept to Bahriya and walks the move.

What maps to what

RenderBahriya
Web serviceAn HTTP container
Background workerA worker container
Cron jobA cron job
Build from repo / native runtimeA Dockerfile producing an image
render.yaml blueprintContainer settings (Console fields or Reis flags)
Environment groupsEnvironment variables and secrets
Secret files / secret env varsSecrets (encrypted, injected as env vars)
Render PostgresAn external database via a connection secret
Render Key Value / RedisBahriya Memcached, or an external cache via a secret
Instance type / scalingResources, replicas, and autoscaling
onrender.com domain + custom domainsDefault hostname with automatic TLS + custom domains

1. Containerise

If you deploy a Render Docker service you already have a Dockerfile — carry it over. If you use a native runtime, write a Dockerfile that installs dependencies and starts your app on a single port:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:app"]

Render sets a PORT for you; keep reading it from the environment and bind to 0.0.0.0. Declare the port with --port on Bahriya (default 8080). Build and push the image:

docker build -t ghcr.io/myorg/api:v1.0.0 .
docker push ghcr.io/myorg/api:v1.0.0

2. render.yaml and environment groups to env and secrets

Render's blueprint and environment groups collect your configuration in one place. On Bahriya, split it:

  • Non-sensitive values become plain environment variables.
  • Sensitive values (database URLs, API keys, secret files) become secrets — created once, attached to the project, and wired to the variable name your app expects.

Health check paths defined in render.yaml map to --healthcheck — see Health Checks.

3. Managed database and cache

  • Database. Render Postgres becomes an external database of your choosing, reachable over the network, with its connection string stored as a secret wired to DATABASE_URL. Provision the new database, migrate your data, and confirm connectivity from a Bahriya container before cutting over.
  • Cache. For a Memcached-compatible cache use Bahriya Memcached. For Redis or another engine, connect to an external instance via a secret, exactly as you do the database.

4. Scaling

Render scales by instance type and count. On Bahriya, set minimum CPU (millicores) and memory (MB), a replica count, and — for automatic scaling — a maximum replica count. Setting --max_replicas above --replicas enables autoscaling between the two. See Resources and Scaling.

5. Deploy

From the Console follow Deploy Your First Container, or with Reis:

reis container:create \
  --type http \
  --name "Web API" \
  --handle web-api \
  --image ghcr.io/myorg/api:v1.0.0 \
  --registry ghcr \
  --port 8080 \
  --healthcheck /healthz \
  --cpu 500 \
  --memory 512 \
  --replicas 2 \
  --max_replicas 8 \
  --regions falkenstein-1 \
  --regions virginia-1 \
  --env APP_ENV=production \
  --secrets DATABASE_URL=database-url

Choose regions close to your users from the four that are live — see Regions.

6. Point your domain and cut over

Your container is reachable at https://web-api.<region>.x.on.bahriya.app with automatic TLS. Test there, then add your production domain, verify it, and move DNS across — see Custom Domain Setup. Keep the Render service running until traffic has drained, then suspend and remove it.