WebSocket API

Real-time dashboard updates via Socket.IO WebSocket gateways.

Deployment Note

WebSocket gateways are NOT available on AWS Lambda deployments. They require the analytics-svc to be deployed on ECS Fargate or run locally via pnpm dev. The Lambda deployment provides REST and GraphQL endpoints only.

Gateways

GatewayNamespacePurpose
DashboardGateway/dashboardReal-time dashboard metric updates
DashboardUpdatesGateway/analytics/dashboardDashboard configuration change notifications

Connection

Connect with socket.io-clienttypescript
import { io } from 'socket.io-client';

const socket = io('http://localhost:4004/dashboard', {
  auth: {
    token: '<JWT-access-token>',
  },
  transports: ['websocket'],
});

socket.on('connect', () => {
  console.log('Connected to analytics dashboard');
});

socket.on('connect_error', (err) => {
  console.error('Connection failed:', err.message);
});

Authentication

Authentication is performed via the auth.token field in the Socket.IO handshake. The JWT token is validated on connection and the tenantId is extracted from claims to scope all data.

Authentication handshaketypescript
const socket = io('http://localhost:4004/dashboard', {
  auth: {
    token: 'eyJhbGciOiJSUzI1NiIs...',
  },
});

Client Events (Emit)

EventPayloadDescription
subscribe{ entityId, entityType }Subscribe to real-time updates for an entity
unsubscribe{ entityId }Unsubscribe from entity updates
Subscribe to entity updatestypescript
// Subscribe to real-time metrics for an event
socket.emit('subscribe', {
  entityId: 'event-uuid-123',
  entityType: 'event',
});

// Unsubscribe when leaving dashboard
socket.emit('unsubscribe', {
  entityId: 'event-uuid-123',
});

Server Events (Listen)

EventDescription
dashboard:initialInitial dashboard state sent after subscribing
dashboard:updateDashboard configuration changed (tiles added/removed/reordered)
metric:updateReal-time metric value update for a subscribed entity
errorError notification (invalid entity, permission denied, etc.)
Listen for server eventstypescript
// Receive initial dashboard state
socket.on('dashboard:initial', (data) => {
  console.log('Dashboard loaded:', data);
  // data: { entityId, entityType, metrics: { ... }, tiles: [...] }
});

// Receive real-time metric updates
socket.on('metric:update', (data) => {
  console.log('Metric updated:', data);
  // data: { entityId, metricName, value, timestamp }
});

// Receive dashboard config changes
socket.on('dashboard:update', (data) => {
  console.log('Dashboard changed:', data);
  // data: { dashboardId, action, tile: { ... } }
});

// Handle errors
socket.on('error', (err) => {
  console.error('WebSocket error:', err);
  // err: { code: 'ANALYTICS_1100', message: '...' }
});

Full Example

Complete WebSocket integrationtypescript
import { io } from 'socket.io-client';

const token = '<your-jwt-token>';

const socket = io('http://localhost:4004/dashboard', {
  auth: { token },
  transports: ['websocket'],
  reconnection: true,
  reconnectionAttempts: 5,
  reconnectionDelay: 1000,
});

socket.on('connect', () => {
  // Subscribe to event metrics
  socket.emit('subscribe', {
    entityId: 'event-uuid-123',
    entityType: 'event',
  });
});

socket.on('dashboard:initial', (data) => {
  // Render initial dashboard
  renderDashboard(data);
});

socket.on('metric:update', (data) => {
  // Update specific metric in real-time
  updateMetricTile(data.metricName, data.value);
});

socket.on('disconnect', (reason) => {
  console.log('Disconnected:', reason);
});

// Cleanup on component unmount
function cleanup() {
  socket.emit('unsubscribe', { entityId: 'event-uuid-123' });
  socket.disconnect();
}