GioJSdocs

Deployment

GioJS ships as two processes: the giojs-server Rust binary (HTTP, routing, caching) and a Node.js worker (React SSR). Both start automatically.

The simplest deploy is a standalone folder: gio build standalone packages the server binary and a bundled worker into one directory that runs with node run.mjs on any server that has only Node installed - see Standalone Deploys. The methods below run the app from source instead, which keeps npm update as your upgrade path.

Before deploying

  1. Typecheck your app with tsc --noEmit - there is no separate build step; the server compiles and scans routes at startup
  2. Ensure Node.js 20+ is installed on the target host
  3. Place the giojs-server binary and your app directory on the host
  4. Set NODE_ENV=production

Choose a deployment method

MethodWhen to use
Linux systemdLinux VPS or bare metal, long-running service
DockerContainerized, single instance or scaling
KubernetesKubernetes, multi-instance behind a load balancer
Windows NSSMWindows Server host

Linux systemd

Run GioJS as a systemd service on any Linux VPS or bare metal server. Survives reboots, logs to journald, supports nginx as a TLS reverse proxy.

Full guide: docs/deployment/linux-systemd.md in the repository.

Docker

Multi-stage Dockerfile keeps the final image small (~80MB) by building Rust and Node separately.

Full guide: docs/deployment/docker.md in the repository.

Kubernetes

Deployment, Service, Ingress, and HPA YAMLs. Uses a readinessProbe on /_gio/health and scales on CPU utilization.

Full guide: docs/deployment/kubernetes.md in the repository.

Windows NSSM

Run GioJS as a Windows Service using NSSM. Survives reboots, writes to Event Viewer, and can be managed with PowerShell cmdlets.

Full guide: docs/deployment/windows-nssm.md in the repository.

Health check

/_gio/health returns JSON and always answers 200 - cached and static content keeps serving even while the Node worker is respawning, during which nodeReady is false. Readiness probes should read that field. Use it for readiness probes, load balancer health checks, and uptime monitors:

{
  "status": "ok",
  "http2": true,
  "tls": false,
  "deploymentId": "abc12345",
  "nodeReady": true,
  "cacheEntries": 42,
  "uptimeSecs": 3600
}

Multi-instance deployments

The page cache is per-instance (in-memory LRU plus a local disk tier) - there is no shared cache backend yet. When running multiple instances (Kubernetes, multiple VMs), set GIO_DEPLOYMENT_ID to the same value on every instance so they agree on the deployment ID. By default the ID is derived from the app's content, so identical builds already agree - pinning it explicitly protects you when pods roll out at different times:

GIO_DEPLOYMENT_ID=release-2026-09-06