Presence

Same API as the core createPresence plugin, but backed by Redis hashes. Presence state is shared across instances with cross-instance join/leave notifications via Redis pub/sub.

When to use over the built-in plugin: The core presence plugin only knows about connections on the local process. If a user connects to instance A, instance B has no idea they are online. The Redis presence extension gives you a single, consistent view of who is online across all instances, with per-entry TTLs so stale entries from crashed instances expire automatically.

Setup

// src/lib/server/presence.js
import { redis } from './redis.js';
import { createPresence } from 'svelte-adapter-uws-extensions/redis/presence';

export const presence = createPresence(redis, {
  key: 'id',
  select: (userData) => ({ id: userData.id, name: userData.name }),
  heartbeat: 30000,
  ttl: 90
});

Usage

// src/hooks.ws.js
import { presence } from '$lib/server/presence';

export async function subscribe(ws, topic, { platform }) {
  await presence.join(ws, topic, platform);
}

export async function close(ws, { platform }) {
  await presence.leave(ws, platform);
}

Options

OptionDefaultDescription
key'id'Field for user dedup (multi-tab)
selectstrips __-prefixed keysExtract public fields from userData
heartbeat30000TTL refresh interval in ms
ttl90Per-entry expiry in seconds. Entries from crashed instances expire individually after this period, even if other instances are still active on the same topic.

API

MethodDescription
join(ws, topic, platform)Add connection to presence
leave(ws, platform, topic?)Remove from a specific topic, or all topics if omitted
sync(ws, topic, platform)Send list without joining
list(topic)Get current users
count(topic)Count unique users
clear()Reset all presence state
destroy()Stop heartbeat and subscriber
hooks{ subscribe, close } - ready-made WebSocket hooks

Zero-config hooks

Instead of writing subscribe and close handlers manually, destructure presence.hooks:

// src/hooks.ws.js
import { presence } from '$lib/server/presence';
export const { subscribe, close } = presence.hooks;

subscribe handles both regular topics (calls join) and __presence:* topics (calls sync so the client gets the current list). close calls leave.

If you need custom logic (auth gating, logging), wrap the hooks:

import { presence } from '$lib/server/presence';

export async function subscribe(ws, topic, ctx) {
  if (!ctx.platform.getUserData(ws).authenticated) return;
  await presence.hooks.subscribe(ws, topic, ctx);
}

export const { close } = presence.hooks;

Was this page helpful?