An interactive business intelligence dashboard built with Plotly Dash — real-time KPI tracking, multi-source data pipeline, and drill-down analytics across 10+ chart types.
Raw data in spreadsheets and databases is invisible to anyone without SQL knowledge — which means the people most affected by trends (product managers, operations leads, executives) are the last to see them. The typical workaround is a data analyst producing weekly exports, creating a lag between reality and decision-making that compounds into bad outcomes.
The goal was to build a live BI dashboard that any stakeholder could use independently — exploring KPIs, drilling into specific date ranges, and comparing metrics across different data sources — without writing a single query. It also had to unify heterogeneous inputs: a SQL database, CSV exports, and a live API feed, all updated on configurable intervals.
The data flows from three distinct sources through a Pandas-based ETL layer that normalises schemas, fills missing values, and caches the resulting DataFrames in memory. Plotly Dash's callback system then binds filter controls directly to chart updates without a page reload, and dcc.Interval triggers re-fetch cycles at configurable intervals for the live data feed.
Flask-caching sits between the ETL layer and the callbacks, storing computed DataFrames with configurable TTLs. This means a slow PostgreSQL query runs once per interval — not once per callback fire — keeping the UI snappy even when underlying data sources are slow to respond.
Dash callbacks can become spaghetti fast when every filter control fires its own chain of updates. Mapping the full callback graph on paper before writing a single @app.callback decorator prevents circular dependencies and ghost updates.
Without flask-caching, every callback that reads from a slow SQL source adds hundreds of milliseconds of latency per interaction. Caching computed DataFrames at the ETL layer — not at the chart layer — is the correct granularity.
Dash Bootstrap Components help, but responsive layout in Dash is harder than vanilla CSS. Column width breakpoints, chart height on small screens, and overflow scroll on tables all need careful tuning that is much costlier to retrofit than to plan for initially.
The most impactful feature — a date-range brush on the main line chart — was not in the original spec. A stakeholder demo revealed it immediately when someone pointed at the chart and said "can I zoom into just Q3?" Ship demos early; they surface real requirements faster than any planning session.
Browse the source code on GitHub or reach out to discuss a custom data engineering project.