Core Concepts

View Active Connections

Last updated by
Harlan Wilton
in feat: view active connections (#6).

Track how many users are connected to your application and which versions they're running. This is useful for admin dashboards, deployment monitoring, and understanding rollout progress.

Connection tracking only works with sse or ws update strategies. It does not support polling or external adapters (Pusher/Ably).

Setup

Enable connection tracking in your Nuxt config:

nuxt.config.ts
export default defineNuxtConfig({
  skewProtection: {
    connectionTracking: true
  }
})

Limitations

This feature is only for certain compatible environments currently:

  • Single instance only: Stats are per-server process. With horizontal scaling, each instance only sees its own connections.
  • SSE/WS only: Does not work with polling strategy or external adapters (Pusher/Ably).

Using the Composable

The useActiveConnections() composable provides reactive access to connection statistics:

<script setup lang="ts">
import { useActiveConnections } from '#imports'

const { total, versions } = useActiveConnections()
</script>

<template>
  <div>
    <p>Active users: {{ total }}</p>
    <ul>
      <li v-for="(count, version) in versions" :key="version">
        {{ version.slice(0, 8) }}: {{ count }} users
      </li>
    </ul>
  </div>
</template>

Return Values

PropertyTypeDescription
totalComputedRef<number>Total active connections
versionsComputedRef<Record<string, number>>Map of buildId → connection count

Example: Admin Dashboard

<script setup>
const { total, versions } = useActiveConnections()
const currentBuildId = useRuntimeConfig().app.buildId

const stats = computed(() => {
  const current = versions.value[currentBuildId] || 0
  const outdated = total.value - current
  return {
    total: total.value,
    current,
    outdated,
    percentUpToDate: total.value ? Math.round((current / total.value) * 100) : 100
  }
})
</script>

<template>
  <div class="grid grid-cols-4 gap-4">
    <div class="stat">
      <span class="label">Total Users</span>
      <span class="value">{{ stats.total }}</span>
    </div>
    <div class="stat">
      <span class="label">On Latest</span>
      <span class="value text-green">{{ stats.current }}</span>
    </div>
    <div class="stat">
      <span class="label">On Old Version</span>
      <span class="value text-orange">{{ stats.outdated }}</span>
    </div>
    <div class="stat">
      <span class="label">Rollout Progress</span>
      <span class="value">{{ stats.percentUpToDate }}%</span>
    </div>
  </div>
</template>

Custom Behavior with Hooks

For advanced use cases, you can use hooks directly instead of the composable.

Client-Side: skew:message

Listen to all messages from the SSE/WebSocket connection:

plugins/custom-stats.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hooks.hook('skew:message', (message) => {
    if (message.type === 'stats') {
      // Custom handling
      console.log('Connections:', message.total)
      console.log('Versions:', message.versions)
    }
  })
})

Server-Side: Connection Lifecycle

Build custom tracking logic with Nitro hooks:

server/plugins/custom-tracking.ts
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('skew:connection:open', ({ id, version, send }) => {
    console.log(`Client ${id} connected on ${version}`)

    // Send custom welcome message
    send({ type: 'welcome', serverTime: Date.now() })
  })

  nitroApp.hooks.hook('skew:connection:close', ({ id }) => {
    console.log(`Client ${id} disconnected`)
  })
})

See Nuxt Hooks and Nitro Hooks for full documentation.

Did this page help you?