The Six-Week Fantasy
Your CTO sketches a dashboard on a napkin. “Chart.js and a few React components,” she says. “Six weeks. Two engineers.” You nod. The logic checks out. Chart.js handles bar charts and line charts. Your data sits in PostgreSQL. A few API endpoints pipe the data to the frontend. What could go wrong?
Six months later you ship something. It draws a bar chart. It breaks when a user selects two filters at once. It cannot export a PDF.
This story repeats every time a product team decides to build analytics in-house. The engineers who estimate the work have never built a BI platform. They count the visible pieces and miss the 80 percent that lives below the surface.
What You Need to Build
A dashboard that displays three charts on a screen is not a platform. Here is the full list of components a production analytics system requires.
Chart library. A library that renders bar charts, line charts, area charts, pie charts, scatter plots, heatmaps, funnels, tables, pivot tables, and gauges. Each chart type needs a configuration interface that non-engineers can use.
Query builder. A layer that translates user-facing filter selections into parameterized SQL. It must handle joins, aggregations, date ranges, nulls, and query timeout. It must not let users run DROP TABLE.
Filter system. Cross-filtering between charts. Date range pickers. Multi-select dropdowns with search. Cascading filters where selecting a country narrows the city list.
Export. CSV export with all rows, not just the visible page. PDF export with pagination, headers, footers, and company branding. Email scheduled reports.
RBAC. Role-based access control at the dashboard level, the question level, and the row level. Admin sees all regions. Regional manager sees their territory. Individual contributor sees their own metrics.
Tenant isolation. If your product serves multiple customers, each customer sees only their data. One misconfigured query exposes data across tenants. You need test coverage that catches this before production does.
Embedding SDK. Signed iframe embedding, JWT-based authentication. White-label theming that matches your product’s design system. Responsive layout that works on mobile.
Caching layer. Store query results so 200 users viewing the same dashboard do not all hit the database at once. Cache invalidation when underlying data changes.
Audit logging. Track who viewed which dashboard, who exported data, and who changed which filter. Compliance teams demand this.
Performance monitoring. Slow query detection. Dashboard load time tracking. Alerts when a query takes longer than five seconds.
Engineering Time: The Line Items
Here is what each component costs, in hours, using estimates from a team that has built this.
| Component | Hours |
|---|---|
| Chart library (8 chart types, configurable) | 280 |
| Query builder (parameterized, safe, join-aware) | 240 |
| Filter system (cross-filtering, cascading) | 200 |
| CSV export (streaming, large datasets) | 80 |
| PDF export (pagination, branding, scheduling) | 160 |
| RBAC (dashboard, question, row-level) | 240 |
| Tenant isolation (multi-tenant data layer) | 200 |
| Embedding SDK (signed iframe, JWT, theming) | 280 |
| White-labeling (CSS variables, brand config) | 120 |
| Caching layer (query cache, invalidation) | 160 |
| Audit logging (view, export, change tracking) | 120 |
| Performance monitoring (slow query, load time) | 100 |
| Integration testing (cross-component) | 200 |
| Documentation (internal, API docs, user guides) | 160 |
| Total | 2,540 |
Two thousand five hundred and forty hours. At a South African senior engineering rate of R550 per hour (about $30 USD), that is R1,397,000, or about $76,000. This assumes one senior engineer who knows what they are doing. If you assign two mid-level engineers who learn on the job, multiply the hours by 1.8 and the cost by 1.3.
Two thousand five hundred hours is 63 weeks of a single engineer’s time, or 32 weeks with two engineers. Your “six weeks, two engineers” estimate covers the chart library and a hardcoded filter. You built 14 percent of the system.
Year Two: The Maintenance Cliff
Ship the platform and the real costs begin.
Security patches for every dependency in your stack. Chart.js releases a breaking change. Your PDF library has a CVE. Your auth library deprecates the API you built on. Budget eight hours per month. That is 96 hours per year.
Feature requests arrive. Marketing wants a Sankey diagram. Operations wants a Gantt chart. The CEO wants a KPI card with a sparkline. Each new chart type costs 40 to 60 hours to build, configure, test, and document. Plan on two new chart types per quarter. That is 400 hours per year.
Onboarding new engineers to your custom analytics codebase takes 60 to 80 hours before they ship anything useful. If you lose one engineer per year, add 80 hours.
Documentation debt. The API docs you wrote at launch are seven months stale. The onboarding guide references a filtering pattern you replaced in March. A new hire spends three days debugging a caching bug that a one-line update to the README would have prevented. Budget four hours per month. That is 48 hours per year.
Database migrations. Your schema evolves as you add features. Each migration needs a rollback plan and a test against production data volumes. Budget 12 hours per month. That is 144 hours per year.
Bug fixes. Users discover edge cases your test suite missed. A dashboard breaks when a column name contains a space. The PDF export truncates long table headers. The date picker fails on December 31. Budget 16 hours per month. That is 192 hours per year.
Annual maintenance total: 960 hours. At R550 per hour, that is R528,000, or about $29,000 per year. Every year.
What Metabase and Grafana Give You
Metabase ships with 17 chart types, a visual query builder, a SQL editor, dashboard subscriptions, embedding, and SSO out of the box. Grafana ships with 30-plus visualization types, alerting, annotations, and a plugin ecosystem with hundreds of data sources. We compared the two in depth: Metabase vs Grafana vs Superset.
Both tools cost $0 to self-host. The open-source editions handle 95 percent of what teams need. The paid tiers unlock audit logging, advanced permissions, and priority support.
What you do not get: custom chart types that match your domain. A telecom needs a network topology view. A logistics company needs a route optimization map. Neither Metabase nor Grafana ships those. You build that layer on top.
The open-source tools demand infrastructure. Self-hosted Metabase needs a server, a database, regular backups, and someone who upgrades the JAR file when a new version drops. Budget eight hours per month for operations. That is R52,800 per year, not zero. Read our guide for the full setup: How to Embed a Metabase Dashboard.
The Hidden Line Items
Hiring. “We will hire someone who knows D3.js.” D3 developers who understand analytics UX, query optimization, and multi-tenant security cost 30 percent more than general frontend engineers. South African market: R75,000 to R110,000 per month for someone who ships production BI. There are maybe 40 such engineers in the country.
Onboarding time. An experienced analytics engineer joining your team spends the first month understanding your data model, your query patterns, and your existing dashboard code. They ship nothing in January. Budget R80,000 for zero output.
Documentation debt compounds. Every feature you ship without documenting creates three hours of future debugging for someone who was not in the room when you built it. Ten undocumented features equals one lost week per year, forever.
The rebuild. Eighteen months in, a new frontend engineer joins and declares the chart library “legacy.” They rewrite it in the framework they prefer. The rewrite takes six weeks and introduces 15 subtle regressions that surface over the following quarter. This happens. Budget for it.
When Building Makes Sense
A 300-person company with 50 engineers and a dedicated platform team can build an analytics platform. They have the headcount to maintain it. They have the onboarding budget to absorb departures. Their product requirements diverge so far from off-the-shelf tools that no open-source BI platform fits.
A five-person startup cannot. Every hour you spend building chart configuration is an hour you do not spend on your core product. Your users do not care that you built the dashboard library yourself. They care that the dashboard answers their question in under two seconds.
The middle ground: embed an open-source BI tool and build custom visualizations only where the tool falls short. Read our overview of the approach: What Is Embedded Analytics?. Metabase handles 90 percent of dashboard use cases. Grafana handles time-series monitoring. Your team builds the 10 percent that differentiates your product.
Cloud Intelligence’s Approach
We have built custom analytics dashboards from scratch. We have embedded Metabase into customer-facing products. We have configured Grafana for SaaS monitoring. Here is when we choose each path.
We build custom when the visualization is the product. A financial model that computes portfolio risk in real time. A network operations center that visualizes fiber infrastructure across a continent. A logistics dashboard that optimizes delivery routes. The chart is not decoration. It is the value.
We embed Metabase when the customer needs to ask their own questions. A SaaS platform where each client explores their usage data. An internal analytics portal where department heads build their own reports. The value lies in self-service, not in the visualizations we ship.
We embed Grafana when the problem is time-series. Server monitoring. IoT sensor data. Application performance metrics. Anything where the X-axis is time and the Y-axis is a metric.
We skip BI when the customer needs answers, not dashboards. A natural-language query interface that returns a single number beats a dashboard with twelve charts. We built a Slack bot that answers “What was our MRR last month?” in three seconds. No dashboard required.

The Decision in a Table
| Scenario | Build | Embed | Skip |
|---|---|---|---|
| 5-person startup, general analytics | Never | Metabase | — |
| 50-engineer company, unique viz domain | Custom on top of BI | Grafana/Metabase for commons | — |
| SaaS with 200 tenants needing dashboards | Never | Metabase with embedding | — |
| Internal ops monitoring | Never | Grafana | — |
| “A few charts for the admin panel” | Never | Never | Hardcoded React + Chart.js |
| Financial modeling that is the product | Custom | — | — |
The “a few charts” scenario deserves an extra word. If you need three bar charts and a table on an admin page, do not build a platform. Hardcode three React components. Call Chart.js. No query builder. No RBAC. No embedding SDK. Ship it in two days. Resist the platform instinct. Not every chart needs a dashboard.
The One Question
Before you open your editor and type npm install recharts, ask yourself: “Do we sell dashboards, or do we sell data served through dashboards?”
If you sell dashboards, build them. If you sell data, embed something that already works.