Skip to main content

Preview Environments Compared: What Railway's Auto-Delete, Render's Full Copies, and Fly.io's DIY Wiring Each Cost a Team Shipping Daily

11 min readDora NodaDora Noda
Share
On this page

A team that merges one pull request a day runs roughly forty preview-days a month without ever thinking about it. Twenty PRs, each open about two days, each with a live copy of the app — and that copy has a meter attached. The three platforms developers actually compare in 2026 handle that meter in three completely different ways: Railway spins up a per-PR environment and deletes it on merge, Render provisions a full copy of your Blueprint infrastructure per preview, and Fly.io hands you a GitHub Action and wishes you luck.

The compute bill is only the opening line. The real cost of previews is everything around it: stale environments from PRs nobody merged, a database clone per PR that bills like production, and the CI glue a team writes and maintains when the platform punts on lifecycle. This post puts all three models on one ledger for the same typical workload, then names what a self-hosted platform should default to instead.

Here is the map before the math:

RailwayRenderFly.io
TriggerToggle in project settings; env per PRBlueprint previews.generation (automatic or [render preview])You wire it (typically superfly/fly-pr-review-apps)
TeardownAuto-deleted on merge/closeAuto-destroyed on merge/close; optional expireAfterDaysAction destroys the app on close — if the workflow runs
Data copied?No — preview Postgres starts emptyNo — datastore/disk copies exclude data; seed via initialDeployHookYour choice — usually a Neon/Turso branch or migrations-from-scratch
BillingPer-second metering on your workspace planPer-second, same rates as normal services; needs Pro workspace ($25/mo)Per-second Machines; no plan fee
Plan gateHobby ($5) or Pro ($20, incl. $20 usage)Pro workspace required for multi-service previewsNone

Two surprises hide in that table. First, neither Railway nor Render copies production data into previews — both give you an empty database and a seeding hook. Second, all three bill per second while a preview is alive, so the variable that actually moves the bill is not which vendor you pick. It is how long your PRs stay open.


The ledger: one team, 20 PRs a month​

Assumptions, stated up front so you can re-run the math: a typical small backend — one web service (0.5 vCPU / 512 MB), one worker the same size, one small Postgres. The team opens 20 PRs a month and each stays open about 2 days. That is 40 preview-days a month. All prices are list prices as of October 2026, and every total below is preview spend only — production is a separate line.

Railway. Metered at roughly $20 per vCPU-month and $10 per GB-month of RAM. The two services draw 1 vCPU and 1 GB combined, so about $30 per continuous month, or $1.00 per preview-day. A small Postgres template with its volume lands near $0.55 per preview-day. Total: about $1.55 per preview-day, ~$62 a month — on a Pro workspace ($20 including $20 of usage), that means the $20 base plus roughly $42 of overage.

Render. Previews bill like normal services, prorated by the second — and unless you override them, they inherit your production plan. With sensible overrides (Starter web at $7, Starter worker at $7, Basic 256 MB Postgres at $6 plus ~$1 of storage), the stack is $21 per continuous month: $0.70 per preview-day, ~$28 a month, plus the $25 Pro workspace previews require — ~$53 all-in.

Without overrides, on Standard production plans ($25 per service), the same previews cost roughly $1.87 per preview-day, or $75 plus the workspace — **$100 all-in**. That override block in render.yaml is worth about $47 a month. Write it on day one.

Fly.io. Two shared-cpu-1x 256 MB Machines at $2.19 per continuous month each is $4.38 per month, or $0.15 per preview-day — about $6 a month. The database is where teams improvise: Fly's Managed Postgres starts at $38 a month, which nobody multiplies per PR, so preview apps typically point at a Neon or Turso branch (pennies to free at this scale) or migrate an empty Postgres from scratch. Realistic all-in: under $10 a month in infrastructure — plus the CI workflow you now own, priced honestly below.

40 preview-days/moInfra preview spendPlan/workspace feeRealistic total
Railway~$62 metered$20 Pro (incl. $20 usage)~$62
Render (preview-plan overrides)~$28$25 Pro~$53
Render (prod-plan default)~$75$25 Pro~$100
Fly.io + Neon/Turso branch~$6–10$0~$6–10 + your workflow

Now the sensitivity row, because averages lie: if your PRs stay open two weeks instead of two days — the normal state of a team with slow review — every metered line above multiplies by seven. Railway's $62 becomes $430. Render's $28 becomes $196. Fly.io's $6 becomes $42.

Preview spend scales with review latency, not with shipping. The cheapest preview optimization available on any platform is merging faster.


Railway: the delete is free, the meter runs while open​

Railway's model is the closest to "it just works." Flip on PR environments in project settings and every pull request gets a temporary environment containing its own instance of every service in the project. Merge or close the PR and the environment is deleted. Domains are provisioned automatically as long as the base environment's services use Railway-provided domains.

The gotcha is the database. Each environment's Postgres starts empty — an empty preview shows an empty app — so teams end up gating seed fixtures on RAILWAY_ENVIRONMENT_NAME to keep demo data out of production. That works, but it is a second data path to maintain: your seed script becomes load-bearing preview infrastructure, and the day it rots, every preview silently renders a blank product.

The billing shape rewards short-lived PRs and punishes forgotten ones symmetrically, because everything meters per second. There is no expiry timer to configure — teardown is tied to the PR event, so a PR that sits open for a month bills for a month. And one sharp edge in the docs: Railway will not deploy a PR branch from someone outside your workspace, so open-source-style fork PRs never get previews at all.

Render: full-fidelity copies behind a $25 gate​

Render's previews are the most faithful of the three: each PR gets a fresh copy of the whole Blueprint — services, datastores, environment groups — kept current on every commit and destroyed on merge or close. Manual mode provisions only for PRs titled [render preview]; automatic mode provisions for everything except PRs tagged [skip preview]. Root directories and build filters can suppress previews for PRs that touch unrelated paths, which matters in monorepos.

But "full copy" overpromises in exactly one place: data. Datastore and disk copies explicitly exclude production data, so like Railway you seed via initialDeployHook. Teams that assumed preview-equals-clone discover this the first time a preview boots against an empty schema.

The pricing structure has two gates. First, multi-service preview environments require a Pro workspace at $25 a month flat — unlimited members since the April 2026 replan, but still a fixed fee before the first preview boots. Second, previews default to production plans and instance counts unless you set previews.plan / previewPlan overrides.

Forgetting the override on a Standard-tier production stack roughly doubles the preview line, as the ledger above shows. Render also offers expireAfterDays to kill previews after inactivity — but the default is no expiry, so stale PRs bill until someone closes them.

Fly.io: the cheapest meter and a lifecycle you own​

Fly.io has no native preview feature. The documented path is the superfly/fly-pr-review-apps GitHub Action — or a hand-rolled flyctl workflow — that creates an app per PR, deploys the branch image, posts the URL as a PR comment, and destroys the app on close. Fly's own docs carry a review-apps blueprint walking through exactly this shape.

The meter is genuinely the cheapest of the three: per-second Machines with no plan fee, and stopped machines cost only their rootfs disk at $0.15 per GB-month. A preview that idles between review clicks can even scale to zero if you configure it. The database story is pick-your-own-adventure — Neon branch-per-PR with a delete-branch action on close is the cleanest pattern teams report, Turso forks are the SQLite-flavored equivalent — and either is dramatically cheaper than cloning a $38 Managed Postgres per PR.

The price is ownership. The destroy step is a workflow job, and workflow jobs have failure modes platform teardown does not: a force-push race, a workflow disabled on a fork PR, a renamed job that no longer matches the close event — each leaves an orphan app billing until someone notices. There is no dashboard that lists "all previews" because previews are just apps with a naming convention.

Small teams absorb this fine; it is one YAML file. But it is your YAML file, and the on-call for preview sprawl is whoever merged the workflow PR.


The three line items beyond compute​

Stale-preview sprawl. All three platforms tie teardown to merge-or-close, which means the failure mode is identical: PRs that stay open. A month-old PR with three requested changes is a month of preview billing on every platform. Render at least offers expireAfterDays; Railway and Fly.io give you no timer, only the PR event. If your team's median PR age is measured in weeks, budget previews at the sensitivity row, not the headline row.

Per-PR database bills. Nobody's previews copy data, but everybody's previews still run a database. On Render that is a full-price Basic Postgres per PR unless you point previews at one shared database via previewValue overrides — a legitimate cost move that trades isolation for savings. On Railway it is metered Postgres-per-environment. On Fly.io it is whatever your branch strategy costs, which is usually near zero and occasionally a surprise Neon bill. The database, not the web service, is the line item teams forget to model.

CI glue maintenance. Fly.io's workflow tax is visible, but the other two have quieter versions: Railway's seed-gating logic, Render's Blueprint override blocks and [skip preview] title discipline. Each is small. Each rots. Budget a few hours a quarter for "previews are broken again," on every platform, forever.

What self-hosted should default to​

Here is the part the vendor tables never include: on machines you already own, the marginal cost of a preview is approximately zero. A Hetzner node you pay for whether it idles or not does not bill extra because a namespace appeared on it. That flips the design question from "which meter is cheapest" to "how do I get lifecycle I don't have to babysit."

The default worth copying is boring on purpose: one namespace per PR, created by a controller that watches pull-request events, torn down through owner references when the PR closes — the same declarative shape the platform-engineering guides recommend over create-script/delete-script pairs that inevitably drift into orphans. Add a TTL (Kubernetes' TTL patterns plus a simple reaper for namespaces past N days without commits) so review latency can't turn into sprawl, and the Render-default-no-expiry footgun disappears by construction. Seed data comes from a sanitized snapshot job, not production credentials, and because the preview runs on the same fleet as production, there is no second billable surface at all — no per-preview Postgres SKU, no workspace fee, no per-second meter.

That is the line item to beat: not Fly.io's $6, but zero marginal dollars with teardown you can audit in one controller instead of three vendors' dashboards. Any self-hosted preview story that reintroduces per-environment billing — a managed database per PR, a second cluster for staging — should have to justify itself against that default.


Forty preview-days a month cost roughly $62 on Railway, $53 on Render with overrides ($100 without), and under $10 on Fly.io plus a workflow you maintain — until review latency multiplies all of it. Pick the bill you can audit: Railway if you want the delete handled, Render if you want full-fidelity copies and already pay for Pro, Fly.io if you want the cheapest meter and will own the lifecycle. And if previews are on track to become your largest untracked line item, that is the signal to stop renting the meter and run the namespaces yourself.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Check your move before you migrate

Free browser tools: check a render.yaml or your Render scripts against bex, or turn a Heroku app or docker-compose.yml into a draft render.yaml. Nothing you paste leaves your browser.

Open the migration tools