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
- Typecheck your app with
tsc --noEmit- there is no separate build step; the server compiles and scans routes at startup - Ensure Node.js 20+ is installed on the target host
- Place the
giojs-serverbinary and your app directory on the host - Set
NODE_ENV=production
Choose a deployment method
| Method | When to use |
|---|---|
| Linux systemd | Linux VPS or bare metal, long-running service |
| Docker | Containerized, single instance or scaling |
| Kubernetes | Kubernetes, multi-instance behind a load balancer |
| Windows NSSM | Windows 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