Skip to content

feat(webapp): Free usage charts as progress toward the cap#6790

Open
macko911 wants to merge 8 commits into
masterfrom
matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap
Open

feat(webapp): Free usage charts as progress toward the cap#6790
macko911 wants to merge 8 commits into
masterfrom
matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap

Conversation

@macko911

@macko911 macko911 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Problem

On the Free usage drill-in, the charts didn't frame usage against the cap: a daily bar chart under a monthly cap makes the limit effectively invisible, and level metrics (connections, sync records) had no cap reference to read against.

Solution

  • Draw the metric's cap as a dashed reference line, with the Y-axis pinned to round ticks ending at the cap plus ~10% headroom.
  • Render counter metrics (proxy, functions, webhooks) as a cumulative month-to-date curve, with a daily/cumulative toggle; no cap line on the daily view.
  • Draw connections/records from the point-in-time daily series (the endpoint option lands in feat(webapp): show Free-plan usage against plan limits #6789) so the plotted value is the one the cap limits, and hide the cap line when a series is filtered or isolated (a slice can't be read against the whole-metric cap).
  • Make the local ClickHouse seed realistic for this view (--mirror-db-counts): mirror the DB connection/record counts the gauge reads, scale counters to a fraction of the caps, and plateau them at the monthly cap.

Fixes NAN-6280

Stacked on #6789 (Free caps table, NAN-6237).

Testing

  • Verified locally on a Free account: the cap line and cumulative/daily toggle on counter metrics, connections/records whose chart end matches the caps gauge, and the cap line hiding when filtering/isolating a slice.
  • npm run ts-build and npm run lint clean.
Screen.Recording.2026-07-17.at.16.15.04.mov

@linear-code

linear-code Bot commented Jul 15, 2026

Copy link
Copy Markdown

NAN-6280

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Preview Deploy

Status URL Deploy Logs Last Updated
✅ Ready Preview URL Deploy Logs 17 Jul 2026, 15:50 UTC

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 15 files

Confidence score: 4/5

  • In scripts/seed-clickhouse.ts, buffering an entire account before flushing raises peak memory and could cause seed-clickhouse to OOM on larger multi-env/multi-day seeds, which would make seeding unreliable in CI or local setup—switch back to per-environment/chunked flushing or validate memory headroom on representative data before merging.
  • In packages/webapp/src/utils/usage.ts, the JSDoc still documents the warning threshold as 80% while NEAR_LIMIT_RATIO now triggers near at 70%, which can mislead future changes and debugging—update both doc blocks to match the current behavior.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/webapp/src/utils/usage.ts">

<violation number="1" location="packages/webapp/src/utils/usage.ts:47">
P3: Stale JSDoc still says the warning band starts at 80%. The `NEAR_LIMIT_RATIO` was lowered to 0.7 so `near` state now triggers at ≥70%. Update both docs to match.</violation>
</file>

<file name="scripts/seed-clickhouse.ts">

<violation number="1" location="scripts/seed-clickhouse.ts:628">
P2: Buffering the whole account before flushing increases peak memory use substantially compared with the previous per-environment flush path. For the seeded multi-env, multi-day dataset this can make `seed-clickhouse` much heavier or fail on larger `--days` runs.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/webapp/src/pages/Team/Billing/components/UsageChartCard.tsx Outdated
Comment thread packages/usage/lib/usage.ts
Comment thread packages/webapp/src/pages/Team/Billing/components/UsageChartCard.tsx Outdated
Comment thread scripts/seed-clickhouse.ts
Comment thread packages/webapp/src/components/patterns/chart/BreakdownChart.tsx
Comment thread packages/webapp/src/hooks/usePlan.tsx Outdated
Comment thread scripts/seed-clickhouse.ts Outdated
Comment thread packages/webapp/src/utils/usage.ts
@macko911
macko911 force-pushed the matej/nan-6237-free-plan-usage-caps-table branch from 4fec4b9 to 2d0c171 Compare July 15, 2026 15:55
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 1a824d7 to cbcf834 Compare July 15, 2026 15:56
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from cbcf834 to 0ab045b Compare July 15, 2026 19:13
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 0ab045b to 33acee2 Compare July 16, 2026 08:58
@macko911
macko911 force-pushed the matej/nan-6237-free-plan-usage-caps-table branch from 8ae80d6 to a7a06b5 Compare July 16, 2026 12:24
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from dcab46e to 885186e Compare July 16, 2026 12:24
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 93d8f0a to 0e06ef7 Compare July 16, 2026 12:53
@macko911
macko911 force-pushed the matej/nan-6237-free-plan-usage-caps-table branch from a7a06b5 to 1d68550 Compare July 16, 2026 12:57
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 0e06ef7 to a1d1ea9 Compare July 16, 2026 12:59
@macko911
macko911 force-pushed the matej/nan-6237-free-plan-usage-caps-table branch from 1d68550 to 5379170 Compare July 16, 2026 17:31
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from a1d1ea9 to ef0f0ca Compare July 17, 2026 07:07
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from d03f8ca to cba0889 Compare July 17, 2026 07:59
@macko911
macko911 force-pushed the matej/nan-6237-free-plan-usage-caps-table branch from fda6686 to acc6f41 Compare July 17, 2026 09:48
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from cba0889 to 23048c9 Compare July 17, 2026 10:01
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 23048c9 to 1d5cdfd Compare July 17, 2026 10:54
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from 1d5cdfd to 92b8965 Compare July 17, 2026 11:16
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from a28ec2b to e653760 Compare July 17, 2026 14:15
Base automatically changed from matej/nan-6237-free-plan-usage-caps-table to master July 17, 2026 15:11
sahilnyk pushed a commit to sahilnyk/nango that referenced this pull request Jul 17, 2026
## Problem

Free accounts (\~97% of accounts) had no view of their usage against
plan caps — the usage page showed charts with no limit framing, so users
couldn't see how close they were to a cap or which metric was near/over.

## Solution

* Free accounts get a per-metric caps table: used / limit, a progress
bar, and % of limit / "Limit reached", driven by the live `plans/usage`
gauge (warning at 70%, over at 100%).
* A single month selector sits above the table and drives the whole
table: rows show the live gauge for the current month and that month's
usage for past months, and each row expands into the existing trend +
dimension-breakdown drill-in for the selected month.
* Add a point-in-time daily series to the billing usage endpoint so
level metrics (connections, sync records) read as the concurrent daily
count rather than the running monthly average — meaningful against a
fixed cap.
* Reuse one `MonthSelector` (backed by a shared `useSelectedMonth` hook)
for both the paid usage header and the Free caps header.
* Extract the sidebar's `formatUsage` / `formatLimit` /
`getStylesForUsage` into a shared `utils/usage.ts`, plus `getUsageState`
and the usage-bar / text-colour helpers used by the caps table.
* Gated to `plan.name === 'free'`; paid/legacy keep the current view.

Follow-up work is stacked on top of this PR:
[NangoHQ#6790](<NangoHQ#6790>) renders the
drill-in as progress toward the cap (cumulative area + cap line), and
[NangoHQ#6791](<NangoHQ#6791>) adds the sidebar
alert for accounts nearing or hitting their caps.

Fixes [NAN-6237](https://linear.app/nango/issue/NAN-6237)

## Testing

* Verified locally on a Free account with seeded ClickHouse usage: caps
states (green / amber near-limit / red "Limit reached"), the month
selector driving both the row gauges and the drill-in across current and
past months, and the collapsible trend + breakdown.
* Confirmed the sidebar `UsageCard` still renders after the helper
extraction, and paid/legacy accounts are unaffected.
* `npm run ts-build` and `npm run lint` clean.

## Demo


https://github.com/user-attachments/assets/69f37518-8730-4102-8e92-cf594e9b7c7e
macko911 added 8 commits July 17, 2026 17:42
The Free-plan drill-in now shows usage against the plan cap: a dashed cap
reference line, counter metrics as a cumulative month-to-date curve with a
daily/cumulative toggle (icons + app focus ring), and connections/records
as their point-in-time daily count. Rounds the y-axis to nice ticks with
the cap as the top labelled tick and ~10% headroom, keeps the cap line
only on the area (not daily) view, and lowers the near-limit warning
threshold to 70%.
Add --mirror-db-counts to the clickhouse seed so the Free caps view has
believable data: mirror the account's real Postgres connection/record
counts into ClickHouse (ramping to the live count) so those AVG metrics
match the DB-backed gauge, scale counter volume to a realistic fraction
of the caps, and plateau counters at their monthly cap so usage stops
instead of running arbitrarily over.
- Default the drill-in chart mode to daily; Free explicitly opts into
  cumulative, so paid charts no longer render as cumulative curves.
- Show the daily/cumulative toggle whenever a chartMode is supplied
  (Free), independent of the breakdown rollout flag.
- Add group / aria-pressed roles to the chart-mode toggle.
- Scale the cap-line axis to the visible series so isolating/hiding a
  breakdown slice isn't flattened against the full stacked total.
- Keep the compact month stepper's focus ring after the MonthStepper
  extraction.
The cap applies to the whole metric, so drawing it against a filtered
slice or an isolated breakdown series is misleading — and the full cap
dwarfs the slice, squishing its data flat. Hide the cap line whenever
the chart is scoped to a slice.
getDbCounts summed every record_counts row, but the caps gauge only counts
records for connections that still exist (paginateConnections filters
deleted=false). Rows left behind by deleted connections pushed the mirrored
records above the gauge, breaking the --mirror-db-counts chart/gauge match.
Filter to live connections the same way the gauge does.
Follow the API rename in #6789: the drill-in chart's prop and its
useApiGetBillingUsageDetail option are now avgPerDay.
Readability only (no behaviour change): hoist a shared monthOf, add a bump()
accumulator and an FnAttrs/fnBag() helper to drop the repeated inline casts,
and collapse the identical proxy/webhook cap branches into one capCounter().
@macko911
macko911 force-pushed the matej/nan-6280-show-free-plan-drill-in-usage-as-progress-toward-the-cap branch from b6be2c8 to c1a3242 Compare July 17, 2026 15:47
@macko911
macko911 marked this pull request as ready for review July 17, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant