Updated Nov 5, 20265 min read

Render vs Fly.io: Which Should You Deploy Your Backend On

Render's service types and managed Postgres against Fly.io's Machines and regions, compared on deploys, background work, databases and scaling.

Render and Fly.io both took over a share of the developers who left Heroku, and they took different paths. Render kept the managed service model: you pick a service type, such as a web service, background worker, cron job or Postgres database, and Render runs it. Fly.io went lower level: your Docker image runs as Machines, small VMs you place in regions you choose.

Both deploy a single API quickly. The differences show up when the app grows a worker, a scheduled job, a queue or users on another continent. This comparison covers those, and where Encore (infrastructure from code) fits when you want the same workflow in your own AWS or GCP account.

Render vs Fly.io at a glance

EncoreRenderFly.io
Where it runsYour own AWS or GCP accountRender's infrastructureFly.io's infrastructure
Deploygit pushGit push, Docker image, Blueprint filefly deploy from a Dockerfile or buildpack
PostgresRDS or Cloud SQL, from codeRender PostgresFly Managed Postgres
Background workPub/Sub subscriptionsBackground worker serviceExtra process group or Machines
Scheduled jobsCronJob calling an endpointCron job serviceScheduled Machines or an in-app scheduler
QueuesSNS/SQS or GCP Pub/SubWorker plus Key ValueRun your own
RegionsAny AWS or GCP regionA handful of regionsMany regions, multi-region by design

Each option is covered below, starting with Encore.

Services, queues and cron in your own cloud with Encore

Encore is infrastructure from code for TypeScript and Go, with a platform that provisions and deploys into your own AWS or GCP account. Where Render gives you service types and Fly.io gives you Machines, Encore reads the infrastructure from your code: a topic becomes SNS and SQS on AWS or Pub/Sub on GCP, a database becomes RDS or Cloud SQL.

Application code passes through Encore and infrastructure guardrails to resources provisioned in your own AWS or GCP account.
Encore provisions the infrastructure your application needs in your own AWS or GCP account.

The background worker you would run as a separate service on Render is a subscription in the same codebase:

// orders/orders.ts import { api } from "encore.dev/api"; import { Topic, Subscription } from "encore.dev/pubsub"; import { SQLDatabase } from "encore.dev/storage/sqldb"; import log from "encore.dev/log"; const db = new SQLDatabase("orders", { migrations: "./migrations" }); export interface OrderPlaced { orderId: string; email: string; totalCents: number; } export const orderPlaced = new Topic<OrderPlaced>("order-placed", { deliveryGuarantee: "at-least-once", }); export const place = api( { expose: true, method: "POST", path: "/orders" }, async (req: OrderPlaced): Promise<{ messageId: string }> => { const messageId = await orderPlaced.publish(req); return { messageId }; }, ); const _ = new Subscription(orderPlaced, "send-receipt", { handler: async (event) => { // Idempotent: a redelivered event finds the row and does nothing. const inserted = await db.queryRow` INSERT INTO receipts (order_id, email) VALUES (${event.orderId}, ${event.email}) ON CONFLICT (order_id) DO NOTHING RETURNING order_id`; if (!inserted) return; log.info("receipt sent", { orderId: event.orderId }); }, retryPolicy: { maxRetries: 5, minBackoff: "10s" }, });

The migration in orders/migrations creates the receipts table the queries use:

-- orders/migrations/1_create_receipts.up.sql CREATE TABLE receipts ( order_id TEXT PRIMARY KEY, email TEXT NOT NULL );

encore run starts Postgres and a local Pub/Sub, applies migrations and shows each message in a local trace. In production, failed deliveries are retried and then moved to a dead-letter queue. The Render migration guide and Fly.io migration guide map each platform's concepts to Encore.

With the queue and the database declared in code, a coding agent can add them and run the result locally. Cloud access sits with Encore's IAM role, not the agent.

The cron jobs docs cover scheduled work, which runs without a separate worker service.

Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

Render: a managed service for every part of the app

Render's model is easy to reason about. Each part of the app is a service with a type: web services for HTTP, background workers for long-running consumers, cron jobs that start on a schedule and exit, plus Render Postgres and Render Key Value. A Blueprint file describes the whole set so a new environment can be created from the repository, and preview environments spin up per pull request.

The trade-off is that every piece is its own service with its own instance size and bill. There is no built-in Pub/Sub, so a queue means a worker service plus a library backed by Key Value. Free web services spin down after 15 minutes without traffic, and the first request after that waits for a cold start.

Fly.io: Machines in the regions you choose

Fly.io runs your image as Machines and routes traffic through Fly Proxy to the nearest one. fly launch enables autostop and autostart by default, so idle Machines stop and wake on the next request, usually within about two seconds. Running the same app in several regions is a configuration change, which is what Fly.io does best.

In exchange for that control, you decide how many Machines exist, volumes attach to one Machine at a time, and process groups in fly.toml are how you run a worker next to the web process. Fly Managed Postgres adds high availability, backups and pgvector, though moving to a new major Postgres version means creating a new cluster and copying data.

Cost, briefly

Render bills per service instance, so the number of services drives the bill. Fly.io bills Machines by usage, so stopped Machines cost little, while databases and volumes are billed whether busy or not. Check each provider's current pricing page before deciding, since both change plans regularly. For a closer look at one pairing, see Render vs Railway.

How to choose

Pick Encore when you want git push deploys, with queues, cron jobs and databases declared in code and running in your own AWS or GCP account, and a full local environment from encore run. See Encore vs Render and Encore vs Fly.io.

Pick Render when you want each part of the app as a managed service with a clear dashboard, in one region. Pick Fly.io when the app should run close to users in several regions and you are comfortable managing Machines and fly.toml.

Frequently asked questions

Is Render or Fly.io better for a backend API?

Render is the simpler choice for an API with a database and a worker in one region, since each piece is a managed service type with a dashboard. Fly.io suits APIs that should run in several regions close to users, at the cost of managing Machines and fly.toml yourself.

Does Render or Fly.io have a message queue?

Neither has a built-in Pub/Sub service. On Render you typically run a background worker with a queue library backed by Render Key Value. On Fly.io you run the broker yourself or use an external queue.

How do I get queues and a database in my own cloud with a Render-style workflow?

Encore deploys with git push into your own AWS or GCP account. You declare new Topic<OrderPlaced>("order-placed", { deliveryGuarantee: "at-least-once" }) and a Subscription in TypeScript, and Encore creates SNS and SQS on AWS or Pub/Sub on GCP, with retries and dead-letter queues.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders