Infra Stack Review

Heroku Alternatives for Production Node.js Apps

Assess your app's actual needs before picking a platform to replace Heroku.

· 11 min read · Updated
Cover illustration for “Heroku Alternatives for Production Node.js Apps”
PaaS Alternatives · August 7, 2026 · 11 min read · 2,433 words

Migrating off a legacy PaaS, most teams start by looking for the closest match to what they already have. That instinct is the wrong starting point: feature parity with the old platform tells you almost nothing about whether a platform fits the workload you're actually running. The right question isn't "what looks like the old platform," it's "what does this app need to stay up, scale, and pass an audit. Get that question right first, and the platform shortlist narrows itself.

A production Node.js app is rarely one process. Even a lean SaaS product might run an API server, a PostgreSQL database, Redis for queues, one or more background workers, cron jobs, a WebSocket server, and a webhook consumer, each with different requirements for memory, uptime, and network behavior. Picking a platform based on how well it mimics another vendor's git-push workflow ignores all of that. The decision that actually holds up over time starts with workload shape, not surface-level familiarity.

The workload checklist that determines which platform tier to evaluate

Before you open a single pricing page, you should be able to answer a short set of questions about your own app. The answers eliminate most of the platform market before any comparison starts.

WORKLOAD CHECKLIST

[ ] Always-on processes?            (API servers holding connections, not just handling requests)
[ ] Background workers?             (queue processors, not just scheduled scripts)
[ ] Cron jobs?                      (scheduled billing runs, cleanup tasks, reports)
[ ] WebSockets / persistent conns?  (chat, live dashboards, collaborative editing)
[ ] Managed database proximity? (you need same-region Postgres, not a remote managed add-on)
[ ] Multi-region / low-latency? (you have global users, not just a single geographic market)
[ ] Preview environments?           (PR-based review workflows)
[ ] Compliance requirements?        (SOC 2, HIPAA)
[ ] Fixed monthly budget?           (predictable billing vs. usage-based metering)

Each line maps to a real constraint on the hosting side. If a function spins down between requests, it can't hold an API connection open, so always-on processes rule out pure serverless platforms. Background workers need a runtime with explicit worker service support. Worker-heavy SaaS products need background process support, queue primitives, and predictable memory for each service, and that's a different ask than just running a script on a timer.

WebSockets and other persistent connections rule out function-based platforms. They require a VM or container runtime that survives beyond a single request-response cycle, which is a structural requirement, not a configuration option. When an app and its database sit far apart, latency compounds under load, so proximity matters. Some platforms treat the database as a separate managed service pinned to a fixed region, which can quietly become a bottleneck if the app later needs to expand elsewhere.

Multi-region or low-latency global serving narrows the field further, to platforms with real distributed compute rather than a CDN that only caches static assets at the edge. Preview environments matter if a team runs a PR-based review workflow, where every branch needs its own disposable environment before merging. Compliance requirements change the entire conversation: once SOC 2 or HIPAA enters the picture, the question moves beyond which PaaS tier fits and toward whether the infrastructure runs in a customer-owned cloud account.

Bill predictability closes the list. Pure usage-based metering, billed per second of CPU and memory, works well for workloads that spike and idle unpredictably. But if a steady-state API holds connections around the clock, that same model turns risky, because the meter never really stops.

Treating this as a typed checklist, the way production-grade frameworks already do, forces specificity before comparison. It also exposes a trap specific to Node.js: a Next.js app built mostly on serverless API routes has genuinely different infrastructure needs than an Express API holding open WebSocket connections. Both get called "a Node.js app." Evaluating them against the same shortlist produces the wrong answer for at least one of them.

Diagram: Workload Checklist: What Each Requirement Rules Out. Visualizes: Show how nine workload requirements each eliminate specific platform types, creating a filtering effect that narrows the shortlist before any pricing comparison begins.

What each platform in the shortlist actually does, and what it cannot do

No platform in this tier does everything well. The honest version of this comparison is knowing what each one was built for, and where it runs out of road.

Porter deploys production environments directly into a team's own AWS, GCP, or Azure account. The infrastructure runs inside the customer's cloud, not on shared-tenant servers owned by the platform. That single architectural choice covers the full Node.js production stack: always-on API servers, background workers, cron jobs, WebSockets, managed databases, autoscaling, and GPU workloads, without requiring a dedicated DevOps hire to wire it all together. For compliance-bound teams, Porter also answers the question that disqualifies shared-tenant PaaS platforms outright: SOC 2 and HIPAA compliance are one-click on AWS (support for GCP and Azure compliance tooling isn't available yet), turning what is normally a multi-month engineering project into a configuration choice. Pricing runs against the team's own cloud credits, whether that's AWS Activate, Azure credits, or GCP credits, so infrastructure cost tracks actual compute rather than a markup layered on top of shared resources. Porter fits teams that have cleared the workload checklist above and landed on always-on processes, background workers, or compliance controls, or teams who find shared PaaS economics starting to work against them rather than for them.

Render takes a more conventional managed-PaaS approach, but structures it cleanly. Its model separates service types explicitly: web services, private services, background workers, cron jobs, managed PostgreSQL, and Redis-compatible key-value storage. That structure maps directly onto a conventional Node.js SaaS architecture, so teams don't have to bend their app's shape to fit the platform. Pricing follows the same logic: a web service is billed by instance tier, Postgres and Redis and workers each carry their own line item, which makes Render considerably easier to model against a fixed budget than pure usage-based platforms. Render also gives you native preview environments generated from PR branches, built-in secret management, health checks wired into zero-downtime deploys, and render.yaml so you can define infrastructure as code. It fits an Express, Fastify, NestJS, or Hono API server running alongside a PostgreSQL primary database, a Redis cache or queue, and one or more background workers, for a small team that wants fewer infrastructure decisions to make on a given day.

Railway runs on usage-based pricing, metered per second of CPU, memory, and storage, plus per-GB egress. Its Hobby plan includes a monthly resource credit equal to the plan fee itself, so the entry point is cheap if your workload is small or irregular. Railway fits teams still validating a product, teams that want fast deployment and several preview or staging environments running at once, and teams that are prioritizing velocity over tight infrastructure control.

Fly.io takes a different architectural approach entirely, running code in Firecracker micro-VMs placed near users across many regions. That's a meaningfully different setup than shared-tenant PaaS, and it suits latency-sensitive or globally distributed workloads in a way the other platforms in this list generally don't. Fly.io charges per-Machine, per-volume, per dedicated IPv4 address, and per-GB of egress. Two billing lines were added in early 2026: inter-region private networking, billed at private-network data-transfer rates starting in February 2026, and volume snapshots, billed starting in January 2026. You pay monthly for each dedicated IPv4 address and for outbound bandwidth per GB across North America and Europe, and persistent volumes keep billing even when the underlying Machine is stopped. Fly.io fits latency-sensitive apps, multi-region Node.js services, and teams that have outgrown a single-region deployment, though it's not the right fit for a team that wants flat, predictable billing above all else. Postgres on Fly.io is treated as an app rather than a managed service, which hands over more control but also demands more operational attention than Render's managed Postgres offering.

Vercel is built around HTTP serverless functions and static frontend hosting, and the framework (Next.js) and the deployment platform are made by the same company. If you build frontend-heavy Next.js apps, that pairing is a genuine feature, but for everyone else it's a coupling risk. Vercel fits a frontend-heavy Next.js SaaS product with a light API surface. It does not suit heavy worker fleets, long-running background workers, or persistent WebSocket connections, because its execution model was never built to hold a connection open indefinitely. Lock-in risk runs highest here: Vercel-specific primitives like ISR and Edge Config are the hardest pieces to migrate away from once a team has built around them. The Vercel AI SDK is a notable exception, because it's open-source and platform-agnostic, so it doesn't carry that same lock-in risk.

Cloudways Velocity rounds out the shortlist as a managed convenience option. It supports popular frameworks out of the box, including Next.js, Nuxt, Remix, and Express, with pricing starting at a moderate monthly rate for 2 GB of RAM and 2 vCPUs, a sizable CDN bandwidth allowance, and a fast network uplink, spread across six plans at increasing price points. Every plan includes enterprise CDN, DDoS protection, and malware protection, along with vertical scaling. It fits agencies, startups, and teams with limited infrastructure management experience who want flat monthly billing and still get managed convenience.

How Pricing Models Behave at Different Traffic Levels

The pricing model that looks cheapest at zero traffic is often the one that costs the most once an app hits real production load. Each model has a specific point where it tends to break, and that point becomes visible only after a team has already committed to it.

Bandwidth is the most common line item that turns a predictable bill into a surprise one. Vercel gives you 100 GB of bandwidth on its Hobby plan and 1 TB on Pro, then charges per GB past that allowance. A single viral traffic event, or even a sustained bot-traffic spike, can push a project well past its allowance in days. Fly.io carries a quieter version of the same risk: persistent volumes keep billing even while the Machine attached to them is stopped, which catches teams that spin services up and down frequently and assume a stopped Machine means a paused meter.

A documented case makes the pattern concrete. A side-project SaaS running on Vercel's Pro plan expected a modest monthly bill, but it reached a much larger sum in a single month, after a bot-traffic spike pushed serverless invocations past the platform's 100K-per-month cap. Nothing about the app's real traffic changed; the billing model just wasn't built to absorb that kind of spike gracefully.

The deeper pattern is that workload shape determines which pricing model is actually cheaper, not which one looks cheaper on a landing page. For a steady-state, always-on API, fixed instance-tier pricing, the kind Render uses, is easier to model and carries less risk than pure usage-based metering, because the bill doesn't move much even as traffic fluctuates within a normal range. For a workload that's genuinely variable or bursty, usage-based pricing, the kind Railway uses, is more efficient, because the team isn't paying for idle capacity during the quiet periods.

Put a typical indie SaaS stack side by side across these platforms: one web service, one worker, one Postgres database, modest traffic. On Render or Railway, that stack costs modestly. On Fly.io, it costs somewhat more once dedicated IPv4 addresses and volume snapshots get added to the bill. On Vercel, it can range anywhere from moderate to well over a hundred dollars a month, depending almost entirely on actual invocation counts and bandwidth use rather than on the size of the app itself.

Running infrastructure inside a customer-owned cloud account, which is how Porter's model works, changes the shape of that cost curve rather than just the numbers on it. Cloud spend runs against a team's existing AWS, GCP, or Azure credits, and the team pays for the compute it actually consumes rather than absorbing a markup built into a shared-tenant platform's pricing. The practical effect is that the economics get better as a team scales, rather than worse, which is the opposite of what usage-based PaaS metering tends to do once traffic moves past the free or low-usage tier.

How Vendor Lock-In Risk Differs Between Platforms

A team that picks carefully still has to ask what happens if the choice turns out wrong six months later. The useful answer here cuts against intuition: migrations between commodity container platforms are rarely the painful ones.

Moving a containerized app between platforms like Render, Railway, and Fly.io follows roughly the same sequence, because all three support standard Dockerfiles as a common foundation. That shared foundation is what makes the migration tractable. The practitioner sequence starts with an audit: checking the current app for platform-specific environment variables, add-ons, or config files, things like a Procfile, railway.json, render.yaml, or fly.toml, that won't carry over automatically, and confirming the app builds from a standard Dockerfile rather than a platform-proprietary buildpack. From there, you export the database using pg_dump with the --format=custom flag, which preserves indexes and constraints through the restore. DNS TTL gets lowered to 300 seconds or less at least 24 hours before cutover, then DNS records get pointed at the new platform's endpoint. Both deployments run in parallel for at least 48 hours, with the old platform's app paused but not deleted, as a rollback option.

That process works because none of those three platforms ask you to build your application logic around a proprietary primitive. The pain occurs in platforms that encourage teams to build directly on top of vendor-specific infrastructure: Vercel's ISR and Edge Config, or similar primitives like Cloudflare Durable Objects and Workers KV on other platforms. Code that depends on those primitives doesn't export cleanly, because the primitive itself has no equivalent on the destination platform. A team that adopted ISR for incremental static regeneration, or built caching logic around Edge Config, has to rewrite that part of the application before it can move anywhere else. That's a different category of migration than swapping a Dockerfile target.

The practical implication for anyone picking a platform today: understand which parts of a platform's feature set are convenience layers over standard infrastructure, and which parts are proprietary primitives with no equivalent elsewhere. A background worker, a Postgres database, a standard container runtime: these look similar enough across Render, Railway, and Fly.io that moving between them is mostly mechanical. A platform-specific caching layer or edge primitive is a one-way door unless a team is prepared to rebuild that piece of the app from scratch. Porter's approach sidesteps a version of this problem by running standard workloads, API servers, workers, cron jobs, databases, inside a customer's own cloud account rather than behind a proprietary abstraction layer, which keeps the infrastructure portable even as the platform managing it changes.

Sources

  1. PaaS Comparison 2026: Railway, Render, Fly.io vs Vercel for Indie Backends
  2. Render vs Railway vs Fly.io for Node.js SaaS Apps in 2026

More in PaaS Alternatives