Skip to main content
Data Visualization
CHAPTER 22 Beginner

Real-Time Data Visualization

Updated: May 18, 2026
5 min read

# CHAPTER 22

Real-Time Data Visualization

1. Chapter Introduction

Real-time dashboards monitor live systems — server metrics, IoT sensors, stock feeds, website traffic. This chapter builds live-updating Dash dashboards using Intervals and simulated streaming data patterns.

2. Live Dashboard with dcc.Interval

python
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
from dash import Dash, html, dcc, Input, Output, callback
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from collections import deque
from datetime import datetime

# Data store (ring buffer — keeps last N points)
MAX_POINTS = 60
data_store = {
    'time':    deque(maxlen=MAX_POINTS),
    'revenue': deque(maxlen=MAX_POINTS),
    'orders':  deque(maxlen=MAX_POINTS),
    'cpu':     deque(maxlen=MAX_POINTS),
}

app = Dash(__name__)
app.layout = html.Div([
    html.Div([
        html.H2("🟢 Live Analytics Monitor", style={'color': '#1565C0', 'margin': '0'}),
        html.P(id='last-update', style={'color': '#666', 'fontSize': '12px'})
    ], style={'background': '#F5F5F5', 'padding': '15px 25px', 'borderBottom': '2px solid #1565C0'}),

    # KPI Row (live)
    html.Div([
        html.Div(id='live-revenue', style={'width': '30%', 'display': 'inline-block', 'padding': '10px'}),
        html.Div(id='live-orders',  style={'width': '30%', 'display': 'inline-block', 'padding': '10px'}),
        html.Div(id='live-cpu',     style={'width': '30%', 'display': 'inline-block', 'padding': '10px'}),
    ], style={'textAlign': 'center'}),

    # Live charts
    html.Div([
        dcc.Graph(id='live-revenue-chart', style={'width': '65%', 'display': 'inline-block'}),
        dcc.Graph(id='live-gauge',          style={'width': '33%', 'display': 'inline-block'}),
    ]),

    # Interval: fires every 1 second
    dcc.Interval(id='interval', interval=1000, n_intervals=0),  # 1000ms = 1s

], style={'fontFamily': 'Inter, sans-serif'})


@callback(
    [Output('live-revenue-chart', 'figure'),
     Output('live-gauge',         'figure'),
     Output('live-revenue',       'children'),
     Output('live-orders',        'children'),
     Output('live-cpu',           'children'),
     Output('last-update',        'children')],
    Input('interval', 'n_intervals')
)
def update_live(n):
    # Simulate streaming data
    now = datetime.now().strftime('%H:%M:%S')
    new_revenue = np.random.normal(8500, 1500)
    new_orders  = np.random.randint(15, 45)
    new_cpu     = max(10, min(95, (data_store['cpu'][-1] if data_store['cpu'] else 45) + np.random.normal(0, 8)))

    data_store['time'].append(now)
    data_store['revenue'].append(new_revenue)
    data_store['orders'].append(new_orders)
    data_store['cpu'].append(new_cpu)

    times   = list(data_store['time'])
    revenue = list(data_store['revenue'])
    cpu     = list(data_store['cpu'])

    # Revenue chart
    fig_line = go.Figure()
    fig_line.add_trace(go.Scatter(x=times, y=revenue, mode='lines+markers',
                                    line_color='#1565C0', line_width=2,
                                    fill='tozeroy', fillcolor='rgba(21,101,192,0.1)',
                                    name='Revenue ($)'))
    fig_line.update_layout(title='Live Revenue Stream', template='plotly_white',
                            height=300, margin=dict(l=50,r=20,t=40,b=40),
                            xaxis=dict(tickangle=-30),
                            yaxis=dict(tickprefix='$', tickformat=',.0f'))

    # Gauge chart for CPU
    fig_gauge = go.Figure(go.Indicator(
        mode='gauge+number+delta',
        value=new_cpu,
        domain={'x': [0, 1], 'y': [0, 1]},
        title={'text': 'CPU Usage (%)'},
        delta={'reference': cpu[-2] if len(cpu) > 1 else new_cpu},
        gauge={
            'axis': {'range': [0, 100]},
            'bar': {'color': '#1565C0'},
            'steps': [
                {'range': [0, 60],  'color': '#E8F5E9'},
                {'range': [60, 80], 'color': '#FFF9C4'},
                {'range': [80, 100],'color': '#FFEBEE'}
            ],
            'threshold': {'line': {'color': 'red', 'width': 3}, 'value': 80}
        }
    ))
    fig_gauge.update_layout(height=300, margin=dict(l=20,r=20,t=40,b=20))

    # KPI cards
    def mini_kpi(label, value):
        return html.Div([
            html.P(label, style={'margin': '0', 'color': '#666', 'fontSize': '11px'}),
            html.H4(value, style={'margin': '0', 'color': '#1565C0', 'fontSize': '20px'})
        ], style={'background': 'white', 'padding': '12px', 'borderRadius': '6px',
                   'boxShadow': '0 2px 6px rgba(0,0,0,0.08)'})

    return (fig_line, fig_gauge,
            mini_kpi('Revenue/s', f'${new_revenue:,.0f}'),
            mini_kpi('Orders/s', str(new_orders)),
            mini_kpi('CPU%', f'{new_cpu:.1f}%'),
            f'Last updated: {now}')


if __name__ == '__main__':
    app.run(debug=True, port=8051)

3. Common Mistakes

  • Too-fast intervals: interval=100ms for heavy computations causes callback queue buildup. Use preventinitialcall=True and set interval ≥ computation time.
  • Growing data arrays: Without a ring buffer (deque(maxlen=N)), data arrays grow indefinitely → memory leak. Always limit stored points.

4. MCQs

Question 1

dcc.Interval(interval=1000) fires callback every?

Question 2

deque(maxlen=60) is used to?

Question 3

Gauge chart (go.Indicator) is best for?

Question 4

fill='tozeroy' in scatter trace?

Question 5

Real-time dashboards require data to be?

Question 6

Gauge threshold value creates?

Question 7

nintervals counter in dcc.Interval?

Question 8

mode='gauge+number+delta' in Indicator?

Question 9

Memory leak in real-time dashboard caused by?

Question 10

preventinitial_call=True in callback?

5. Interview Questions

  • Q: How do you build a live-updating chart in Plotly Dash?
  • Q: What is a deque and why use it for real-time data?

6. Summary

Real-time Dash dashboards: dcc.Interval fires callbacks on schedule, deque(maxlen=N) limits memory. Gauge charts for KPI threshold monitoring. Simulated streaming: generate random data per interval tick. Production: replace simulation with WebSocket/REST API calls. Set interval ≥ computation time to prevent queue buildup.

7. Next Chapter Recommendation

In Chapter 23: Data Visualization for Business Intelligence, we build executive BI dashboards with KPI hierarchies, drill-down, and cross-filter capabilities.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·