Skip to content

Limits

What’s not in BI

Scope is intentionally narrow — BI is the canvas for analyst-built dashboards over your warehouse, not a Looker / Tableau replacement.

Hard contract — won’t change

  • Read-only. Inherited from DB Engine. No widget can write back to the source DB.
  • One connection per widget. No cross-connection joins inside a single widget.

Roadmap

These are documented intent — not committed scope. Surface them if they’re blocking you.

  • Per-tenant dashboard templates — clone a stock dashboard (“Clinic A/R overview”, “Coverage health”, “ABA panel productivity”) instead of building from scratch.
  • Scheduled refresh — auto-refresh on a cron (currently manual / lazy). Plumb through APScheduler or a CronJob worker.
  • Cross-filtering — clicking a bar in widget A filters every widget on the same connection. Needs a per-dashboard filter state and a SQL rewriter pass.
  • Drill-through — clicking a chart datum opens the underlying rows in a side panel.
  • Snapshot dashboards — capture data + spec + layout at a point in time so emails can link to a stable view.
  • Per-breakpoint layoutslg / md / sm / xs / xxs distinct positions. Current behaviour is single layout with auto-collapse.

Off the roadmap

  • Operational replacement. Use /admin/coverage, /admin/eligibility, /admin/denials, etc. for the practice’s own purpose-built queues. BI is not the place to rebuild those.
  • ML / forecasting widgets. Predictive charts are a separate roadmap; BI is descriptive.
  • Write-back from widgets. Read-only by contract.
  • Custom chart kinds. Recharts kinds are the locked list — line / area / bar / stacked-bar / donut / scatter / kpi / table. Adding a kind is a contract change; surface the request.

Performance caps

  • Per dashboard: ~20 widgets comfortable; beyond that, refresh-all parallelism hits warehouse rate limits.
  • Per widget result: 100k rows max (inherited from db.run_sql).
  • Per widget refresh: 30s statement timeout (inherited).