DEV Community

octave Nkurunziza
octave Nkurunziza

Posted on Originally published at blog.hubfly.space

How to migrate from Render to Hubfly space, step by step

Originally published on the Hubfly space blog.

TL;DR

  • What you get: your Render web service and Postgres database running on Hubfly space, same domain, no lost rows.
  • Who it's for: anyone on Render with a web service, maybe a worker, and a Render Postgres database.
  • Time needed: about 1 hour of work, plus a DNS TTL you lower a day ahead. Real downtime is the few minutes your database copy takes.
  • Cost: a small always-on app (0.5 vCPU, 512 MB) plus the smallest managed Postgres costs $4.25/month on Hubfly space vs $13/month on Render's Hobby plan (prices from the official pages, checked 26 Oct 2026).

Your app works on Render. The bill is what made you open this tab: $7 for a half-CPU web service, $6 for a 256 MB database, $10 if you add Key Value, and $25 a month on top once a second person needs the Pro workspace. Moving feels risky, though, because the database is the part you can't get wrong.

This guide moves the app first, copies the data once, switches DNS last, and keeps Render running as your fallback until you're sure. Try it on Hubfly space: the free shared tier gives you 360 compute hours a month with no card, so you can rehearse the move before paying for anything. The always-on Dedicated container in this guide is the $2.23/month paid option.

What you're moving, and what it costs on each side

Same small app on both platforms: one always-on web service with 0.5 vCPU and 512 MB RAM, plus the smallest paid Postgres.

Item Render (Hobby workspace) Hubfly space
Workspace / seats $0 Hobby (1 seat); $25/mo Pro, unlimited seats No seat or project fees
Web service, 0.5 vCPU / 512 MB, always on $7/mo $2.23/mo
Smallest paid Postgres $6/mo, 256 MB RAM, 1 GB storage $2.02/mo, Nano: 0.25 vCPU, 512 MiB, 10 GiB storage
Extra Postgres storage $0.30/GB $0.011/GB-month
Persistent disk / volume $0.25/GB-month $0.011/GB-month (Standard)
Background worker, same size $7/mo $2.23/mo
Redis-compatible store, smallest Key Value $10/mo, 256 MB Redis container, 0.5 vCPU / 256 MB: $1.85/mo
Bandwidth 5 GB included on Hobby, then $0.15/GB 100 GB egress included (cost panel)
App + Postgres total $13/mo ($38/mo on Pro) $4.25/mo

All Render prices come from render.com/pricing, checked on 26 Oct 2026. Hubfly space prices come from its published rates: $0.004 per vCPU-hour, $0.002 per GB-hour of RAM and $0.00001536 per GB-hour of storage, over 730 hours a month.

How the Hubfly space numbers add up:

  • Web container: 0.5 × $0.004 × 730 = $1.46 CPU, 0.5 × $0.002 × 730 = $0.73 RAM, 4 GB disk × $0.00001536 × 730 = $0.04. Total $2.23. That's exactly what the Create Container cost panel shows.
  • Nano Postgres: (0.25 × $0.004 + 0.5 × $0.002) = $0.002/h compute, plus the 30% management fee = $0.0026/h, plus 11 GiB of storage (10 GiB data + 1 GiB system disk) × $0.00001536 = $0.00017/h. That's $0.00277/h × 730 = $2.02.

The Create Container cost panel for a 0.5 vCPU / 512 MB always-on container: $1.46 CPU, $0.73 RAM, $0.04 storage, $2.23 a month.

Where Render is the better choice

Be honest with yourself before you move. Render is ahead on several things, and they may matter more to you than $9 a month:

  • Database backups. Render Postgres has point-in-time recovery for 3 days on Hobby and 7 days on Pro, plus one-click logical exports. Hubfly space managed databases don't have automatic backups yet (the dashboard says "Coming soon"), so you run pg_dump on a schedule yourself.
  • High availability and read replicas for Postgres, listed on Render's pricing page. Hubfly space managed Postgres is a single instance.
  • Compliance: SOC 2 Type II, ISO 27001 and HIPAA workspaces on Render's higher plans (pricing page).
  • Full-stack preview environments on Render's Pro plan, and a free static-site tier.
  • Regions. Hubfly space lets you pick eu-central, eu-north or usa-central for a project. If your users need another region, check that first.
  • Network throughput. The container's Network tab shows a 15 Mbps traffic limiter per container. That's plenty for an API or a web app, but test it if you serve large files directly from the app (put them in Hubfly space Storage instead).

Render also offers up to $10K in migration credits to teams moving to it, so the price gap is narrower for some teams in year one.

If none of those are dealbreakers, here's the move.

Map your Render settings to Hubfly space

Open your render.yaml (Render calls it a Blueprint) or your service's Settings page, and translate each field:

Render (render.yaml field) Hubfly space equivalent
type: web service A Hubfly space Cell container with an HTTP domain
type: worker (background worker) A container with no public domain
runtime + buildCommand / startCommand Git repository source: a root Dockerfile wins, otherwise the build is detected from your package files. Or deploy a Docker image. Override the start command in Configuration → Process Settings → Command
plan: 0.5c-512mb Dedicated tier, CPU 0.5, RAM 512 MB, Auto Sleep off
envVars with value Configuration → Environment Variables, with a Secret toggle per value
envVars with generateValue: true Copy the existing value from Render (so sessions survive), or generate a new one with openssl rand -base64 32 and paste it as a secret
envVars with fromDatabase / connectionString Connect the database to the app: Hubfly space creates a dedicated database user and a DATABASE_URL secret in the project
envVarGroups Project-level environment variables, inherited by containers you create in the dashboard (not by containers in a Compose stack, so set those values in the stack itself)
disk (mountPath, sizeGB) A volume mounted at the same path. Volumes survive redeploys and can grow but never shrink
healthCheckPath Configuration → Health Check: a Docker-style test command (CMD-SHELL … or a JSON array) with interval, timeout, start period and retries. Use a tool your image actually contains (how to write one)
preDeployCommand (migrations) A one-off job in a Compose stack, with your app waiting on service_completed_successfully (how to set it up)
Private network hostnames Each container gets a private DNS name like shop-api-<id>.eucentral.hubfly.internal, shown on the Review step and the Network tab
autoDeployTrigger Deploy on push, or deploy after CI succeeds
Custom domains Network → Add Domain → Custom Domain

Two things don't map one-to-one. Cron jobs: run your scheduler inside a small worker container. And Render's outbound IPs are shared ranges per region, so any third-party allowlist that names them needs the new addresses after the move.

Step 1: Lower your DNS TTL a day ahead

Log in to your DNS provider and set the TTL on your app's records (the www CNAME to your-app.onrender.com, and the apex record) to 300 seconds. Do it at least 24 hours before the switch.

Why: resolvers cache your old record for as long as the old TTL. If it's 1 day, some visitors keep hitting Render for a day after you switch. With 5 minutes, the switch is over in 5 minutes.

Step 2: Create the project and the database

  1. In the dashboard, click Create Project, name it (shop), choose Cell and the region closest to your users. Under Advanced Options, set a monthly budget cap if you want a hard ceiling. At 100% of the cap, running workloads stop and new deploys are blocked, so set it above your expected bill.
  2. Create a second project with the Managed service platform, choose PostgreSQL and the Nano size.
  3. Pick the same major version Render runs. Render creates new databases on Postgres 18 by default; Hubfly space offers 18, 17 and 16. Check yours with SELECT version(); and match it. pg_dump can't dump a server newer than itself, and restoring into an older major version can fail.

The database takes about 1.5 to 3 minutes to provision. Open its Connect page and copy the connection URI. Note two things that differ from Render: the port is not 5432 (it's shown in the URI), and TLS is required (sslmode=require).

Why a managed database instead of a Postgres container: you get a connection page, users with read-only or read-write presets, an IP allowlist and a SQL editor, for about $2 a month. More on that setup.

Step 3: Deploy the app next to Render

In the Cell project, click Create → Create Container:

  1. Source: name it (shop-api). Choose Git repository and connect your repo, or Docker image if you already push an image (pin a tag, like your-org/shop-api:2026-10-24).
  2. Resources: choose Dedicated, drag CPU to 0.5 and RAM to 512 MB, and untick Auto Sleep. The panel says "Always-On Runtime Mode Active" and the estimate reads $2.23/month.
  3. Configuration: add every variable from Render's Environment tab. Toggle Secret for keys and passwords. Watch out: Chrome may autofill your login email and password into a new variable row. Check each row before you continue.
  4. Review → Deploy Container. A small image is Running in about 20 seconds.

Now open Network → Add Domain → Auto Endpoint, enter your app's port and click Create Subdomain. You get an HTTPS URL like shop-api.eu1.hubfly.app within seconds.

The Network tab after adding an auto endpoint: one active domain with TLS, the private network alias and the CNAME DNS target.

If you see a 502, your app is listening on 127.0.0.1. Make it bind to 0.0.0.0 and the port you entered (the 1-line fix).

Point the new app at a throwaway copy of your data first (Step 4 without the write freeze), click through the main pages, and fix anything that breaks. Render is still serving your users the whole time.

Step 4: Copy the database

This is the only step with downtime. Keep it short.

  1. Stop writes. Put the app in maintenance mode, or scale your Render worker to zero, so no new rows land in the old database during the copy.
  2. Dump from Render. Copy the External Database URL from your Render database's Connect menu. Render allows external connections from anywhere by default unless you set an IP allow list, and it requires TLS (Render docs).
pg_dump "postgresql://USER:PASSWORD@your-db-host.render.com/your_db?sslmode=require" \
  --format=custom --no-owner --no-acl --file=render.dump
Enter fullscreen mode Exit fullscreen mode
  1. Restore into Hubfly space. Use the URI from the Connect page. First open the database's network settings and click Add my IP. An empty allowlist means any IP can try to connect, so never leave it empty on a production database. After the move, keep only the addresses you really need, and check that the app still connects after each allowlist change.
pg_restore --no-owner --no-acl \
  --dbname="postgresql://admin:PASSWORD@your-db.db.hubfly.app:PORT/app?sslmode=require" \
  render.dump
Enter fullscreen mode Exit fullscreen mode

--no-owner --no-acl matters: your Render user doesn't exist on the new server, so without these flags the restore fills your screen with role errors. Restore into an empty database, as Render's own backup docs advise.

  1. Check the copy. Compare row counts on your biggest tables on both sides:
psql "$RENDER_URL"  -c "SELECT count(*) FROM orders;"
psql "$HUBFLY_URL" -c "SELECT count(*) FROM orders;"
Enter fullscreen mode Exit fullscreen mode

Once the counts match, delete render.dump from your laptop. It holds every row of your production data.

How long it takes depends on size. A 93 MB database with a million rows dumps in about 1.3 seconds and restores in about 2 seconds on a laptop; your network is usually the slow part. For multi-gigabyte databases, rehearse the copy once so you know the number before the real night.

  1. Point the app at the new database. Connect the database to the shop-api project from the database's apps section, or paste the URI as a DATABASE_URL secret. Restart the container and check the auto endpoint URL again.

Step 5: Switch DNS

  1. In the Hubfly space dashboard, open Network → Add Domain → Custom Domain on your container and add your domain. The dashboard asks you to pick a verified domain, so add and verify it first, using the DNS records it shows you.
  2. At your DNS provider, replace the old Render record with the CNAME target shown on your container's Network tab. For www, that means swapping the CNAME from your-app.onrender.com to the new target. For an apex domain, use your provider's ALIAS/ANAME/flattening feature if it has one.
  3. Remove the custom domain from Render once traffic has moved, so Render stops trying to renew its certificate.

With a 300-second TTL, most traffic moves within minutes. TLS on the new side is issued automatically (Let's Encrypt).

Step 6: Keep Render as a fallback for a week

Don't delete anything on Render yet. Leave the old service idle and the old database untouched for about a week. If something goes wrong in the first hours, point DNS back. Any rows written on Hubfly space since the switch exist only there, so freeze writes and copy them back before Render takes traffic again.

Before you delete the Render database, take one last export. Render keeps logical exports for seven days after creation, so download it rather than leaving it there.

Then set up your own backups on the new side. Run this every night from a machine whose IP is on the database allowlist:

pg_dump "$HUBFLY_URL" --format=custom --no-owner --no-acl --file=backup-$(date +%F).dump
Enter fullscreen mode Exit fullscreen mode

Copy each file to a Hubfly space Storage bucket with any S3 client (the endpoint is shown in the Storage workspace) and keep 7–14 days. At $0.011 per GB-month, two weeks of small dumps cost cents. That replaces the point-in-time recovery you had on Render, minus the "any second" precision.

What can go wrong

  1. pg_dump: error: aborting because of server version mismatch. Your local pg_dump is older than Render's Postgres (often 18). Install the Postgres client tools for the same major version as the server (check with pg_dump --version), then run the dump again.
  2. The app returns 502 on the new URL. It's bound to 127.0.0.1 or to a different port than the one you entered for the endpoint. Bind to 0.0.0.0 and match the port.
  3. Login sessions break after the switch. Your session or JWT secret came from generateValue on Render and you created a new one. Copy the existing value from Render's Environment tab instead of generating a fresh one, or every user gets logged out.

Takeaway

A Render-to-Hubfly-space move is a settings translation, one pg_dump/pg_restore, and a DNS change. Do the app first, rehearse the data copy, switch DNS last and keep Render around for a week. For the small app above, the monthly bill goes from $13 to $4.25; on a Pro workspace, from $38 to $4.25. What you give up is Render's built-in PITR and HA, so replace them with scheduled dumps before you delete anything.

Read next: How to move your app from Railway to Hubfly space and Docker health checks that catch real problems.

Go further on Hubfly space

  • Deploy on every push from GitHub Actions with a signed webhook: guide.
  • Roll out the next version safely to 10% of traffic with a weighted load balancer: guide.
  • Move a whole Compose stack (web, worker, Redis) in one import: guide.

Price your Render setup on Hubfly space: open Create Container, set the same CPU and RAM as your Render plan, and the cost panel shows the monthly price before you deploy anything.

Top comments (0)