Portal Community

Decision Matrix

ScenarioRecommended TransportReason
Browser app on ASP.NET Core backendsignalrNative integration, automatic protocol fallback, managed auth
Browser app on non-Microsoft backendwebsocketProtocol-agnostic, bidirectional, low overhead
Mobile app (React Native, Capacitor)websocketNo SignalR dependency needed, binary support
Server-to-server integrationwebsocketNo browser APIs needed, efficient binary framing
Read-only event feed (no replies)sseLowest overhead, HTTP/1.1 compatible, firewall-friendly
Corporate firewall blocks WebSocketsignalr or http-pollingSignalR negotiates; polling works everywhere over HTTP
Strict legacy proxy (no persistent connections)http-pollingStandard HTTP GET/POST only

Feature Comparison

FeatureSignalRWebSocketSSEHTTP Polling
BidirectionalYesYesNo (receive only)Yes (GET + POST)
Binary framesYesYes (ArrayBuffer)No (text only)No
Auto reconnectYes (built-in)Yes (manual impl)Yes (manual impl)Yes (polling loop)
Protocol fallbackYes (WS → SSE → polling)NoNoN/A
Firewall friendlyYes (falls back to HTTP)DependsYes (HTTP)Yes (HTTP)
Auth via headersYes (accessTokenFactory)No (query params only)No (query params)Yes (headers)
ASP.NET Core requiredNo (but designed for it)NoNoNo
LatencyLowVery lowLowHigh (polling interval)

BizFirstGO Standard Setup

// Standard BizFirstGO app — two servers, optimal transports for each
const stream = createEdgeStream({ logLevel: 'info' });

// BAS server: workflow events, forms, HIL — SignalR for reliable ASP.NET integration
stream.registerServer({
  id: 'bas',
  type: 'bas',
  url: '/hubs/edge-stream',
  transportConfig: {
    type: 'signalr',
    url: '/hubs/edge-stream',
    accessToken: authStore.getToken(),
  }
});

// Chat server: Octopus agent streaming — WebSocket for minimal latency
stream.registerServer({
  id: 'chat',
  type: 'chat',
  url: 'wss://chat.bizfirst.com/ws',
  transportConfig: {
    type: 'websocket',
    url: 'wss://chat.bizfirst.com/ws',
    queryParams: { token: authStore.getChatToken() },
  }
});

Environment Detection

import { detectBestTransport } from 'edge-stream-js';

// Detect what's available in the current environment
const best = detectBestTransport();
console.log('Best transport:', best);
// 'websocket' — modern browser or Node.js
// 'sse'        — browser without WebSocket (rare)
// 'http-polling' — fully restricted environment

// Note: detectBestTransport() does NOT consider SignalR
// because SignalR requires @microsoft/signalr and a compatible hub.
// Use SignalR explicitly when you know the backend supports it.
When in Doubt, Use SignalR For BizFirstGO deployments, SignalR is always safe. If the environment supports WebSocket, SignalR uses it. If not, it automatically falls back. You never need to handle fallback logic yourself.