Real-Time Dashboard Implementation (Live Data Updates)
Real-Time Dashboard displays current data without manual page refresh — metrics, order statuses, analytics, KPIs. Updates happen via WebSocket or SSE when data changes.
Technology Choice
WebSocket — bidirectional, suitable for interactive dashboards with filters. Server-Sent Events (SSE) — unidirectional server → client, simpler, works over HTTP/2. Polling — request every N seconds. Simple but less efficient.
For dashboard without user actions SSE is sufficient and cheaper to implement.
SSE Endpoint
// GET /api/dashboard/stream
app.get('/api/dashboard/stream', authenticate, async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no'); // for nginx
const sendEvent = (event: string, data: unknown) => {
res.write(`event: ${event}\n`);
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// Send initial data
const initial = await dashboardService.getMetrics(req.user.id);
sendEvent('init', initial);
// Subscribe to Redis pub/sub for updates
const subscriber = redis.duplicate();
await subscriber.subscribe(`dashboard:${req.user.id}`);
subscriber.on('message', (channel, message) => {
const update = JSON.parse(message);
sendEvent(update.type, update.data);
});
// Heartbeat every 30 sec to keep connection alive
const heartbeat = setInterval(() => {
res.write(':heartbeat\n\n');
}, 30000);
req.on('close', () => {
clearInterval(heartbeat);
subscriber.unsubscribe();
subscriber.quit();
});
});
React Hook for SSE
function useDashboardStream(userId: string) {
const [metrics, setMetrics] = useState<DashboardMetrics | null>(null);
const [isConnected, setIsConnected] = useState(false);
useEffect(() => {
const eventSource = new EventSource('/api/dashboard/stream', {
withCredentials: true
});
eventSource.addEventListener('init', (e) => {
setMetrics(JSON.parse(e.data));
setIsConnected(true);
});
eventSource.addEventListener('metrics:updated', (e) => {
const update = JSON.parse(e.data);
setMetrics(prev => prev ? { ...prev, ...update } : update);
});
eventSource.addEventListener('order:new', (e) => {
const order = JSON.parse(e.data);
setMetrics(prev => prev ? {
...prev,
todayOrders: prev.todayOrders + 1,
todayRevenue: prev.todayRevenue + order.total
} : null);
});
eventSource.onerror = () => {
setIsConnected(false);
// EventSource automatically reconnects
};
return () => eventSource.close();
}, [userId]);
return { metrics, isConnected };
}
Publishing Updates from Backend
// When order created — notify active dashboards
async function onOrderCreated(order: Order) {
// Publish to manager
await redis.publish(`dashboard:${order.managerId}`, JSON.stringify({
type: 'order:new',
data: { id: order.id, total: order.total, status: order.status }
}));
// Publish to general channel for admin dashboard
await redis.publish('dashboard:admin', JSON.stringify({
type: 'metrics:updated',
data: { todayOrders: await countTodayOrders(), todayRevenue: await sumTodayRevenue() }
}));
}
Dashboard with Socket.IO and Widgets
function DashboardPage() {
const { metrics, isConnected } = useDashboardStream(user.id);
return (
<div className="dashboard-grid">
<ConnectionIndicator isConnected={isConnected} />
<MetricCard
title="Orders Today"
value={metrics?.todayOrders ?? 0}
delta={metrics?.ordersVsYesterday}
/>
<MetricCard
title="Revenue"
value={formatCurrency(metrics?.todayRevenue ?? 0)}
delta={metrics?.revenueVsYesterday}
/>
<LiveOrderFeed orders={metrics?.recentOrders ?? []} />
<RealtimeChart
data={metrics?.hourlyRevenue ?? []}
title="Revenue by Hour"
/>
</div>
);
}
Timeline
SSE endpoint + Redis pub/sub + React hook + basic widgets: 1–2 weeks. Full dashboard with filters, export and multiple metric types: 3–4 weeks.







