Tutorial 06
Harden realtime for production
Treat socket connections like long-lived sessions with explicit auth, controlled errors, and a Node runtime.
Outcome
You will read the session in src/hooks.socket.ts, return only the user data handlers need, and deploy on a long-running Node process.
Socket hook
Create socket locals in hooks.socket.ts
The socket hook runs when a browser opens or refreshes the realtime connection. Read the session there and return only the values your .socket.ts files need.
Protected rooms start in the socket hook
Private tenant rooms need user data that came from the server. src/hooks.socket.ts is where the session cookie becomes locals.user for the rest of the connection.
Previously: The Rooms page added a tenant room that reads locals.user.tenantId. This step shows the hook that creates locals.user before that room code runs.
Code focus: This example keeps only the values .socket.ts files need. Do not pass raw session blobs into every handler.
Lives in
src/hooks.socket.ts
creates per-connection values for .socket.ts files · Room contracts read locals.user, but they should not duplicate session-cookie lookup code. Keep that lookup in the socket hook.
Route map
src/hooks.socket.ts <- resolve locals.user
src/routes/rooms/[roomId]/chat.socket.ts <- read locals.user
import { handleSocket } from 'liverpc/server';
export const handle = handleSocket(async ({ cookies }) => {
const sessionId = cookies.get('session');
const session = sessionId ? await getSession(sessionId) : undefined;
return {
locals: {
// Socket handlers read locals.user, never browser-supplied identity.
user: session?.user
}
};
});Result: Every connection now gets user data from one server-side hook before protected rooms or handlers run.
Checkpoint
Connect without a session cookie and confirm protected rooms reject access on the server.
Runtime
Deploy as a long-running Node server
Deploy this package version as adapter-node output or a custom Node server. Static, edge, and short-lived serverless output cannot keep Socket.IO connections open.
Socket.IO needs a process that keeps connections open
The adapter wrapper attaches Socket.IO to the SvelteKit Node server. Run that server as a long-lived process so browser connections stay attached after the first request.
Code focus: Use this shape in your process manager, container command, or platform start command.
Lives in
build output from adapter-node
production command for the built app · This is deployment setup, not route code. The process owns both SvelteKit HTTP requests and Socket.IO connections.
Route map
svelte.config.js <- adapter wrapper
build/ <- Node server output
node build <- long-lived process
# Build the SvelteKit Node app.
pnpm build
# Run the long-lived process that owns Socket.IO.
HOST=0.0.0.0 PORT=3000 node buildResult: The app now runs in the runtime mode LiveRPC expects for this version.
Checkpoint
Open the production URL and keep a browser tab connected through a deploy restart test.