Svelte SSR Server

The SSR server runs as a child process of Puma.

It starts and stops together with Puma.

To provide zero-config, fully automated handling of background processes, this includes:

  • Stable behavior across different deployment setups without relying on Process.ppid.
  • Deduplicated startup leader selection when running multiple Puma workers.
  • Ensuring that only one elected startup leader starts the SSR server.
  • Ensuring that a restart occurs with every deployment to eliminate the risk of an old version being used.
  • Fully separate startup processes (e.g.: no shared flock file) to ensure that older processes cannot break new ones.
  • Cleanup of stale Node processes, socket files, and startup info/lock files (*.flock).
  • Self-healing behavior: if the SSR process dies, it is restarted automatically.
    • You can test this with:
    • Check the Node process ID with ps aux | grep node or rails svelte_on_rails:check.
    • rails svelte_on_rails:cache:clear + kill <PID>.
    • Reload the page. An SSR error may appear briefly until client-side hydration takes over.
    • => Reload the page again: The error should disappear
    • => The Node process should be running again
    • => rails svelte_on_rails:check should show the restarted SSR server.

Process description: how startup leader selection works during deployment

  • The startup election uses files matching tmp/sockets/sor-startup-leader-*.flock.
  • Existing startup lock files are considered valid only while they are newer than STARTUP_GENERATION_TTL (5 seconds).
  • If a recent startup leader file exists, the current Puma worker reuses that startup generation and does not start another SSR server.
  • If no recent startup leader file exists, the worker creates its own candidate lock file.
  • The worker writes startup information into that file, then waits briefly so other Puma workers can also become candidates.
  • After the wait, all candidates deterministically choose the same winner from the recent lock files.
  • If the current worker owns the winning lock file, it becomes the startup leader.
  • If another candidate wins, the current worker removes its own candidate lock file and follows the winning startup generation.
  • The startup leader resets log/svelte-ssr-server.log and writes SSR startup logs there.
  • The startup leader launches the Node SSR process or cluster.
  • After the SSR server has started successfully, stale Node processes, socket files, and old startup lock files for the same app/environment are cleaned up.

Requirements

A current Node.js installation is required.

The path to Node.js can be set via the SVELTE_ON_RAILS_NODE_BIN environment variable.

If it is not set, the gem checks whether nvm is installed by looking for the NVM_DIR environment variable or for ~/.nvm. It also checks for a .nvmrc file within Rails.root.

The @csedl/svelte-on-rails package must be installed, as it provides the bin/svelte-ssr-server and bin/svelte-ssr-cluster executables.

Both are validated and started when Rails boots.

Setting ssr to false in the configs (see next section) disables all of this.

Configuration

See: Configuration

Troubleshooting

Running rails svelte_on_rails:check prints a status overview page. See Rake Tasks.

It includes:

  • The status of the currently running Node instance or cluster processes.
  • A trace of how the gem tried to find — or successfully found — the Node binary.
  • Memory usage for the Node instances.
  • Disk usage for Redis.

You can also inspect the Node instance with a curl command:

curl --unix-socket <socket-file> http://localhost

Running node process you can find by

ps aux | grep svelte

Logfile

The SSR server writes an additional log file to <Rails.root>/log/svelte-ssr-server.log.

This log file is deleted every time Rails boots up and mainly contains logs for booting or restarting the SSR server.

This is because boot processes are not always written to the Rails log.