all posts

The best Node.js hosting platforms in 2026

Ajay Kumar··9 min read

Node hosting looks like a solved problem until you try to host something that isn't a request-in, response-out API. Then you find out that half the platforms in the category are not really hosting a Node process at all — they are hosting a function that happens to be written in JavaScript, and the difference shows up the first time you open a WebSocket, start a queue worker, or write a response that takes ninety seconds to finish.

I'm Ajay, I build PandaStack, which is one of the options below. This is the comparison I wish I'd had: sorted by what your app actually needs to do, with the failure modes named.

Ask one question first

Does your process need to stay alive between requests? Everything else follows from the answer.

  • No — every request is independent, finishes in a few seconds, and holds nothing in memory. Serverless platforms are excellent for this and you should probably use one.
  • Yes — you have WebSockets, server-sent events, an in-process job queue, a long-lived database pool, a cache you actually rely on, a cron loop, or a request that can legitimately run for minutes. You want a machine, not a function.

People pick a serverless platform for a category-two app all the time, because the deploy story is so good, and then spend a quarter working around it — an external queue for the jobs, a hosted pub/sub for the sockets, a separate scheduler for the cron. That's a real architecture, but you should choose it deliberately rather than inherit it from a hosting decision.

The platforms

Vercel

Unbeatable if the Node in question is a Next.js app. The integration is genuinely deep — routing, caching, image handling, preview deployments — and nothing else in the list matches it for that specific case. For a plain Express or Fastify server it's a worse fit: you're deploying into a function runtime, with the execution-duration ceiling and the no-persistent-connection constraint that implies. Fluid compute has softened the cold-start story considerably, but it hasn't turned the platform into a long-running-process host.

Render and Railway

The default recommendation for a plain Node server, and deservedly so. You get a real long-running process, a managed Postgres next to it, background workers as a first-class object, and a deploy flow that's a git push. Railway's pricing is usage-based and Render's is instance-based, which matters more than the sticker rate: pick based on whether your traffic is spiky or steady. The main complaint from both camps at scale is cost creep once you're running several always-on services that are mostly idle.

Fly.io

The right answer when geography is part of the problem — you want the process near the user, or near a database replica, and you're willing to think about regions. Machines are real VMs, so anything a Node process can do works. The trade is that you're now operating something: Fly gives you more control than a PaaS and expects more from you in return.

Google Cloud Run

A container that scales to zero, with generous request timeouts and no artificial limits on what the process may do. Excellent, boring infrastructure. The friction is that you're writing a Dockerfile and living in GCP's IAM model, which is a real tax if you're a small team who just wanted to deploy an API.

AWS (Lambda, App Runner, ECS Fargate)

Lambda for genuinely event-driven work, App Runner if you want a container without operating a cluster, Fargate when you've outgrown both. All three are fine. All three cost you more setup than anything else on this list, and the reason to choose them is usually that the rest of your infrastructure is already there.

PandaStack (mine)

Your app runs as a normal Node process inside its own Firecracker microVM, built straight from the repo — no Dockerfile. Because it's a VM and not a function, WebSockets, workers, in-process schedulers and long requests all just work. Two things are specific to this design: the app can sleep when idle and wake on the next request, so an app nobody is using bills almost nothing; and each deploy is blue-green, with the old VM kept until the new one passes its health check. Runtime version comes from your repo — a `.nvmrc` or `.tool-versions` file is honoured rather than a dropdown in a dashboard.

# Deploy a plain Node/Express repo — no Dockerfile, no build config
pandastack app create \
  --name api \
  --git-url https://github.com/acme/api \
  --git-branch main \
  --port 3000

# Subsequent deploys are a git push, or an explicit one:
pandastack app deploy <app-id> --follow

Where it's the wrong answer: if you're a Next.js shop who wants ISR and edge middleware behaving exactly as documented, use Vercel. If you need a global anycast footprint, use something built for that. And a VM boots in about 179ms from snapshot but a cold app wake is measured in seconds, not milliseconds, because the app process itself has to start — if you need single-digit-millisecond wake on an idle app, this is not it.

Whatever you pick, check the platform's idle and request-duration limits before you migrate, not after. The two most common migration surprises are a request timeout shorter than your slowest endpoint, and a platform that recycles the process more aggressively than your in-memory cache assumes.

The five things worth checking before you commit

  1. Maximum request duration. Find your slowest real endpoint — the report export, the PDF render — and check it fits with room to spare.
  2. WebSocket and SSE support, stated explicitly. 'Supports HTTP/2' is not an answer to this question.
  3. How Node version is chosen. A platform that reads `.nvmrc` or `package.json` engines from the repo will not drift from local. A dropdown in a dashboard will.
  4. What happens to a build that runs out of memory. Next.js and TypeScript builds are memory-hungry, and a build box smaller than your laptop is the single most common cause of 'it builds locally'.
  5. Zero-downtime deploys, by name. Blue-green or rolling — either is fine. 'We restart the process' is not.

Short version

Next.js: Vercel. A conventional API with a database and a couple of workers: Render or Railway. Geography matters: Fly. Already deep in a cloud: Cloud Run or App Runner. Long-lived connections, background work in-process, and an idle bill you don't want to pay: a microVM platform like PandaStack. Nothing here is a trick answer — the mistake is picking a function runtime for an app that needed a process.

Frequently asked questions

Can I host a Node.js WebSocket server on a serverless platform?

Generally not directly. A serverless function is invoked for a request and torn down after it, which is fundamentally at odds with a connection that stays open for minutes or hours. Most platforms in that category either reject upgrade requests outright or terminate the connection at their execution-duration ceiling. The usual workaround is to move the socket layer to a managed realtime service and keep your functions for the request/response paths, which works well but adds a dependency and a second billing relationship. If WebSockets are core to the product rather than an accessory, hosting the app as a long-running process — on a container platform, a VM, or a microVM — is the simpler architecture and usually the cheaper one.

Do I need a Dockerfile to deploy a Node.js app in 2026?

No, and for a straightforward Node app you probably shouldn't write one. Most modern platforms detect a Node repo from `package.json`, install dependencies, run your build script, and start your app with the start command — the same three steps you would have written in the Dockerfile, minus the chance of getting the base image or the layer caching wrong. Keep a Dockerfile for genuinely unusual needs: a system library that isn't in the platform's base image, a multi-stage build with a compilation step in another language, or an artifact you need to run identically in three different environments.

Why does my Node build fail on the host but work on my laptop?

Almost always memory, sometimes environment variables. Node's default heap is smaller than most build boxes' RAM, and TypeScript, Next.js, and webpack builds routinely exceed it on real codebases — the symptom is a build killed without a useful error, or an explicit JavaScript heap out of memory. Check your platform's build-time memory allocation against what your laptop actually uses during a build. The second cause is env vars: variables your framework inlines at build time must exist during the build, not just at runtime, and platforms differ on which set they expose to which phase.

What is the cheapest way to host a Node.js app that gets little traffic?

A platform that bills for what the app consumes rather than for a reserved instance, ideally one that can sleep the app when nothing is hitting it. A small always-on instance on a fixed-price PaaS is predictable but you pay for the twenty-three hours a day it does nothing. Serverless is cheap at low traffic but constrains what the app may do. Scale-to-zero on a container or microVM platform gets you both — a real process while traffic exists, near-zero cost while it doesn't — at the price of a wake delay on the first request after an idle period. For a side project or an internal tool, that delay is almost always an acceptable trade.

How do I run background jobs alongside a Node web server?

Three shapes, in increasing order of robustness. In-process — a worker loop or an interval in the same Node process — is the simplest and only safe if the platform genuinely keeps the process alive and runs exactly one instance. A separate worker service consuming from a queue is the standard answer, decoupled and independently scalable, and most PaaS platforms support it as a first-class object. A scheduled function or cron job suits periodic work that does not need to be always-on. What breaks people is choosing the first shape on a platform that scales instances horizontally, so every replica runs the same job, or on one that suspends idle processes, so the job silently stops firing.

Keep reading

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.