Deployment guide

Deploying a SvelteKit application on a VPS

Deploy on a VPS Cloud →

Development7 min read

Deploying a SvelteKit application on a VPS

SvelteKit produces high-performance full-stack applications, but most tutorials assume a serverless deployment. On a VPS, the Node adapter gives you a real long-running server, with no cold start or execution limit. Here is how to deploy it cleanly with Docker and a reverse proxy.

Why self-host SvelteKit on a VPS

SvelteKit adapts to many targets via its adapters (Vercel, Netlify, Cloudflare…), but the official @sveltejs/adapter-node adapter produces a standalone Node server, perfect for a VPS. Instead of splitting your application into serverless functions subject to cold starts and execution-time limits, you get a persistent process that keeps its database connections open and responds without startup latency. Form actions, server-side load functions and +server.ts endpoints run in a single runtime that you control. On a VPS, you also avoid per-invocation billing, common on front-end platforms, which becomes unpredictable as soon as traffic rises.

Concrete benefits

  • Persistent Node server via adapter-node: no cold start on server routes
  • Database connections kept open in a pool, without reconnecting on each request
  • No per-invocation billing: stable cost even with high and irregular traffic
  • Form actions and +server.ts endpoints executed without an imposed duration limit
  • WebSockets and SSE possible, where serverless forbids or complicates them
  • Environment variables and secrets managed directly, without a third-party platform dashboard

Hardware and software prerequisites

A SvelteKit application in Node mode consumes moderately: a VPS with 1 vCPU and 2 GB of RAM suits a medium-traffic site; scale up to 2 vCPU / 4 GB if you co-locate a PostgreSQL database and have heavy server load functions. Install Node.js 20 LTS, and either Docker or PM2 to manage the process as a daemon. Nginx will serve as a reverse proxy. Point your domain at the VPS IP. The build (build/ generated by adapter-node) stays light; 5 to 10 GB of disk is enough with the node_modules.

Step-by-step deployment

01

Install and configure the Node adapter

Add @sveltejs/adapter-node and declare it in svelte.config.js (adapter: adapter()). It is what transforms your app into a standalone Node server rather than a serverless bundle.

02

Build the application

Run npm run build. SvelteKit generates a build/ folder containing index.js, the server's entry point. You test it locally with node build; it listens by default on port 3000.

03

Containerize or daemonize the process

With Docker: a node:20-alpine Dockerfile that copies build/ and package.json, installs the production dependencies (npm ci --omit=dev) and runs node build. Without Docker: use PM2 with pm2 start build/index.js --name svelte-app for automatic restart.

04

Inject the runtime configuration

Pass PORT, ORIGIN (indispensable for SvelteKit to validate form actions) and your secrets via the environment: ORIGIN=https://mydomain.com. Without a correct ORIGIN, form actions will fail in production with a CSRF error.

05

Configure Nginx as a front end

Create a vhost with proxy_pass http://127.0.0.1:3000; and the proxy_set_header Host and X-Forwarded-Proto $scheme headers. Enable proxy_http_version 1.1 and the Upgrade headers if you use WebSockets.

06

Secure with Let's Encrypt

Run certbot --nginx -d mydomain.com. Once the certificate is installed, check that ORIGIN matches the final HTTPS URL, otherwise form submissions will be rejected.

Cache the output of static routes with the Cache-Control header in your load functions, and enable precompression: adapter-node automatically serves .gz and .br files if they exist. Build with precompression by setting precompress: true in the adapter options. On the process management side, prefer PM2's cluster mode (pm2 start build/index.js -i max) to make use of all the VPS cores under a high CPU load.

Deploy your SvelteKit app without cold starts

The ServOrbit Cloud VPS gives you a persistent Node environment with dedicated resources: ideal for running adapter-node continuously and serving your SvelteKit routes without startup latency.

Need help?

Browse our help center and FAQ, or write to our team — support in French, English and Arabic.