all posts

The best Angular hosting platforms in 2026

Ajay Kumar··9 min read

Angular deploys are simpler than most frameworks' once you answer one question: does your build produce a folder of files, or a folder of files plus a Node server? Everything downstream — which hosts work, what routing config you need, what breaks — follows from that.

The answer is in your build output. If `dist/<app>/` contains only `browser/`, you have a static app. If it also contains `server/` with a `server.mjs`, you have server-side rendering and you need somewhere to run Node. I build PandaStack, which is relevant to the second case; most of this post is about telling the two apart and picking accordingly.

Work out which build you have

ng build
ls dist/my-app/

# Static only:
#   browser/

# SSR / prerendering enabled:
#   browser/  server/  prerendered-routes.json

Angular's application builder handles both from one config. Adding SSR (`ng add @angular/ssr`) doesn't change how you develop — it changes what you have to deploy, and it means static hosting is no longer sufficient unless every route is prerendered.

Prerendering and SSR are not the same thing, and the distinction decides your hosting. Prerendered routes are HTML files you can serve from a CDN. SSR routes are rendered per request by a Node process. An app can use both — and if it does, you need the server.

Static Angular: any CDN, plus one rewrite rule

A client-rendered Angular app is a folder of static assets, and every static host serves it well: Cloudflare Pages, Netlify, Vercel, GitHub Pages, S3 with CloudFront, or the static side of a general app platform. Pricing at this size is close to free everywhere and shouldn't drive the decision.

There is exactly one configuration everyone forgets. The Angular router owns the URL, so a hard refresh on `/dashboard/settings` asks the host for a file that doesn't exist. The host must rewrite unknown paths to `index.html`:

# Netlify — _redirects
/*  /index.html  200

# Cloudflare Pages — _redirects (same file format)
/*  /index.html  200

# nginx
location / {
  try_files $uri $uri/ /index.html;
}

Symptom if you skip it: the app works when you click around and 404s when you reload or share a link. It's the single most common Angular deploy bug and it has nothing to do with Angular.

SSR Angular: you're hosting a Node server now

With `@angular/ssr`, the build emits a server bundle that you start like any Node application. The hosting requirement is unglamorous and specific: a long-running Node process, listening on a port, that stays up.

# Build both bundles
ng build

# Run the SSR server
node dist/my-app/server/server.mjs
# Listens on $PORT (defaults to 4000)

That rules out pure static hosts and puts you in the same category as any Node app. Platforms that fit: a container host (Cloud Run, Fly.io, Railway, Render), a serverless-function adapter if your host provides one, or an app platform that runs the process directly.

The serverless route deserves a caveat. Angular's SSR bundle is not tiny, and cold-starting it per request adds latency that a warm process doesn't have. For a low-traffic internal app that's fine. For a public-facing site where SSR exists to improve perceived performance, a warm process is the point.

The platforms, briefly

  • Cloudflare Pages — excellent for static Angular, generous limits, global by default. SSR needs the Workers path and some adaptation.
  • Netlify and Vercel — smooth for static, and both can run the SSR server as a function. Watch cold starts and the per-invocation model if traffic is spiky.
  • Firebase Hosting — natural if you're already using Firebase for auth and Firestore; SSR runs on Cloud Functions with the same cold-start caveat.
  • Google Cloud Run — a container running the SSR server, scales to zero, no framework opinions. More setup, fewer surprises.
  • Railway, Render, Fly.io — run the Node process directly, straightforward SSR story, always-on billing unless you configure otherwise.
  • Static object storage plus a CDN — cheapest possible static hosting if you're comfortable configuring the rewrite yourself.

PandaStack — the SSR process, asleep when nobody's looking

Mine, so concretely: you connect the repo and PandaStack builds it inside a Firecracker microVM and serves it on a stable URL. Angular SSR needs no adapter — it's a Node process on a port:

{
  "type": "node",
  "installCommand": "npm ci",
  "buildCommand": "npm run build",
  "startCommand": "node dist/my-app/server/server.mjs",
  "port": 4000
}

The reason this shape suits SSR: the process is long-lived, so you get warm rendering rather than a cold start per request — and when real traffic stops, the app sleeps and stops billing, restoring from a snapshot when the next visitor arrives. That's the combination SSR normally can't have: warm-process performance without paying for an idle server all night.

For a purely static Angular build, honestly, use a CDN. There's no advantage to running a VM to serve files that never change.

Deploy checklist

  1. Run ng build and look at dist/ — browser only, or browser plus server?
  2. Static: configure the SPA fallback rewrite to index.html, then verify by hard-refreshing a deep link.
  3. SSR: confirm the start command points at server/server.mjs and that the host passes a PORT the server reads.
  4. Set environment variables at build time for anything baked into the bundle, and at runtime for anything the SSR server reads.
  5. Check the Node version your host defaults to against the one Angular requires — a mismatch fails the build with an unhelpful message.

Frequently asked questions

Why does my Angular app 404 when I refresh a page?

Because the Angular router handles the URL in the browser, but a refresh asks the host for that path directly, and there's no file there. The fix is a rewrite rule sending unmatched paths to index.html — a _redirects file on Netlify or Cloudflare Pages, try_files in nginx, or the equivalent SPA-fallback setting on your host. It's a hosting configuration issue, not an Angular one, which is why it only shows up in production.

Do I need SSR for my Angular app?

Only if you need HTML in the initial response — usually for SEO on public content, for link previews on social platforms, or to improve first contentful paint on slow connections. An authenticated dashboard behind a login gets nothing from SSR and takes on a server to run. If you want faster first paint without a server, prerender the handful of public routes at build time and keep the rest client-rendered.

Can I deploy Angular SSR to a static host?

Only if every route is prerendered at build time, in which case you don't really have SSR — you have static HTML with hydration, and a static host serves it fine. The moment one route renders per request (because it depends on the URL, a cookie, or live data), you need a Node process. Check prerendered-routes.json in your build output against your actual route list before assuming static hosting will do.

How do I set environment variables in an Angular app?

Distinguish build-time from runtime. Anything the browser bundle needs — an API base URL, a public key — must be present when ng build runs, because it's compiled into the JavaScript; changing it later means rebuilding. Anything only the SSR server reads can come from the host's runtime environment via process.env. And nothing secret should ever be in the first category: values compiled into the browser bundle are public, whatever your host calls the setting.

Is Angular SSR slow to cold start on serverless?

It's noticeably slower than an edge function, yes — the server bundle plus your dependencies has to be loaded before the first render. On a warm invocation it's fine; on a cold one, users see the delay SSR was supposed to eliminate. If your traffic is steady, serverless is fine. If it's spiky, or if SSR exists specifically for perceived performance, a long-running process serves you better — ideally one that can sleep when traffic genuinely stops.

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.