refactor(billing): retire the parity-phase getUsage source toggle#6764
Conversation
Post-cutover, the ClickHouse path is authoritative for /getUsage on
every account. The parity-phase machinery that let a dev-only flag
route individual requests to Orb instead is dead code:
- `billingUsageSource` field on GET /api/v1/meta (was hardcoded to
'clickhouse' anyway)
- `source=clickhouse|orb` query param on GET /api/v1/plans/billing-usage
- `source` field on `GetBillingUsageOpts`
- `FLAG_ALLOW_OVERRIDE_GETUSAGE_SERVICE` env var
- Orb-override branch in `UsageTracker.getBillingUsage` (with its Orb
cache-key sanitisation and cumulative-usage post-processing — all
unreachable now)
- `params.append('source', ...)` in the webapp's `useApiGetBillingUsage`
and `useApiGetBillingUsageDetail`
Webapp `useBreakdownEnabled` now returns `true` unconditionally. The
downstream `if (breakdownEnabled)` conditionals are still there but
always take the true branch; that inlining is left as follow-up cleanup
so this diff stays focused on the removal.
Companion cleanup needed in nango-environments: remove
`FLAG_ALLOW_OVERRIDE_GETUSAGE_SERVICE` from `apps/development/nango-values.yaml`.
Nothing to do for staging/prod (never set there).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
All reported issues were addressed across 10 files
Confidence score: 5/5
- Safe to merge after the addressed issues were fixed.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Addresses cubic's P3 on nango#6764: with useBreakdownEnabled returning true unconditionally, the Dev Tools "Usage breakdown" switch still wrote to localStorage but nothing read it — a persisted setting that looked like it worked but had no effect. Drops: - the switch itself + its "Feature Flags" section header in DevToolPanel (last item there, section is now empty) - the entire useFeatureFlagsStore (usageBreakdown was its only field) - the LocalStorageKeys.FeatureFlags entry + its KEY_CATEGORY row If any user still has the `nango_feature_flags` key persisted in localStorage from before, it just becomes orphaned data — no runtime effect, cleared naturally on next full logout. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
macko911
left a comment
There was a problem hiding this comment.
nitpick (non-blocking): UsageTracker.billingClient is now write-only — assigned in the constructor but no longer read anywhere, since the removed orbOverride branch was its only reader (the UsageBillingClient import now survives only for its type). Worth dropping, or folding into the same follow-up as the other no-op cleanups.
Otherwise LGTM — clean removal, verified no dangling references and that stray ?source= params are silently dropped (non-strict schema) rather than 400ing.
Second follow-up to cubic's review on nango#6764. With the orbOverride branch gone from UsageTracker.getBillingUsage, nothing calls UsageBillingClient — its only method (`getUsage`) is the Orb-side read path we retired at cutover. Metering's HTTP-event push path is a separate surface (`@nangohq/billing`'s OrbClient.ingest via `billing.add`) and stays untouched. Removes: - packages/usage/lib/billing.ts (the class) - packages/usage/lib/billing.unit.test.ts (its tests) - The `billingClient` field + constructor init on UsageTracker - Stale reference in clickhouse.ts:547's docstring Drops per-service-process allocation of a Redis rate limiter that no downstream consumer touches. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| * Whether the usage breakdown view is shown. Always true post-cutover — kept | ||
| * as a hook so call sites don't have to change while the always-true | ||
| * conditionals downstream get inlined in follow-up cleanup. | ||
| */ | ||
| export function useBreakdownEnabled(): boolean { | ||
| const { data: meta } = useMeta(); | ||
| return meta?.data.billingUsageSource === 'clickhouse'; | ||
| return true; |
There was a problem hiding this comment.
I think this could be cleaned up?
…-billingusagesource # Conflicts: # packages/server/lib/controllers/v1/plans/usage/getBillingUsage.ts # packages/usage/lib/usage.ts # packages/webapp/src/hooks/usePlan.tsx # packages/webapp/src/pages/Team/Billing/components/Usage.tsx # packages/webapp/src/pages/Team/Billing/useBreakdownEnabled.ts # packages/webapp/src/utils/local-storage.tsx
Preview Deploy
|
Follow-up to cubic's earlier P3 (macko911 approved) and kaposke's PR comment. The hook returned true unconditionally post-cutover, and its call sites gated conditionals that were always true. Inlines those: - useSelectedMonth: drops `breakdownEnabled` from the return shape and simplifies the day-clamp / canGoPrevious logic. External consumers don't destructure `breakdownEnabled` so the API contract is unaffected. - UsageChartCard: drops `showControls` alias. `parseFilterParam`, `inBreakdownMode`, `inFilterMode`, and the breakdown-control render gate now read as unconditional. - Deletes packages/webapp/src/pages/Team/Billing/useBreakdownEnabled.ts. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
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/pages/Team/Billing/useSelectedMonth.ts">
<violation number="1" location="packages/webapp/src/pages/Team/Billing/useSelectedMonth.ts:21">
P3: The ClickHouse floor is now applied to every usage view, but `EARLIEST_USAGE_MONTH_MS` is still documented as breakdown-only in `usageBreakdown.ts`. Updating that JSDoc to describe the floor as applying to all usage views would keep the source-of-truth documentation accurate.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| * the breakdown (ClickHouse) view is active — that's when the data starts; legacy Orb accounts keep | ||
| * full history. Any component reading this hook stays in sync via the shared param. | ||
| * Selected usage month, backed by the `?month` URL param. The June-2026 floor is where the | ||
| * ClickHouse data starts. Any component reading this hook stays in sync via the shared param. |
There was a problem hiding this comment.
P3: The ClickHouse floor is now applied to every usage view, but EARLIEST_USAGE_MONTH_MS is still documented as breakdown-only in usageBreakdown.ts. Updating that JSDoc to describe the floor as applying to all usage views would keep the source-of-truth documentation accurate.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/webapp/src/pages/Team/Billing/useSelectedMonth.ts, line 21:
<comment>The ClickHouse floor is now applied to every usage view, but `EARLIEST_USAGE_MONTH_MS` is still documented as breakdown-only in `usageBreakdown.ts`. Updating that JSDoc to describe the floor as applying to all usage views would keep the source-of-truth documentation accurate.</comment>
<file context>
@@ -13,19 +12,16 @@ interface UseSelectedMonth {
- * the breakdown (ClickHouse) view is active — that's when the data starts; legacy Orb accounts keep
- * full history. Any component reading this hook stays in sync via the shared param.
+ * Selected usage month, backed by the `?month` URL param. The June-2026 floor is where the
+ * ClickHouse data starts. Any component reading this hook stays in sync via the shared param.
*/
export function useSelectedMonth(): UseSelectedMonth {
</file context>
…-billingusagesource # Conflicts: # packages/webapp/src/pages/Team/Billing/components/UsageChartCard.tsx
Fixes CI: the "rejects an unknown source" integration test was still sending `?source=not-a-source` expecting a 400, but the source field was removed from the schema in this branch — the request is now a 200 (unknown params are silently dropped) so `isError` throws. Removes: - The "rejects an unknown source" test entirely. - The stale `(source=clickhouse)` qualifier from the "ClickHouse happy path" describe title. - Every `source: 'clickhouse'` query param scattered across the CH happy-path tests — the field no longer exists on the schema, so those were dead noise being silently ignored. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
/getUsageon every account. Removes the parity-phase machinery that let a dev-only flag route individual requests to Orb instead — dead code now./api/v1/metaresponse, one query param + its handling from/api/v1/plans/billing-usage, one env var, the Orb-fallback branch inUsageTracker.getBillingUsage(plus the cumulative-usage helper only that branch used), and the corresponding webapp plumbing.Removed
billingUsageSourceonGET /api/v1/meta(was hardcoded to'clickhouse'anyway).source=clickhouse|orbquery param onGET /api/v1/plans/billing-usage.source?field onGetBillingUsageOpts.FLAG_ALLOW_OVERRIDE_GETUSAGE_SERVICEenv var (packages/utils/lib/environment/parse.ts).orbOverridebranch inUsageTracker.getBillingUsage, including the Orb cache-key sanitisation and cumulative-usage post-processing that only that branch reached.params.append('source', ...)in the webapp'suseApiGetBillingUsageanduseApiGetBillingUsageDetail.Left as follow-up
useBreakdownEnablednow returnstrueunconditionally. Downstreamif (breakdownEnabled)conditionals still evaluate correctly (always take the true branch) but could be inlined. Kept out of scope to keep this diff focused on the removal.The webapp
usageBreakdowndev toggle inDevToolPanel+ its slot in the feature-flags store are no-ops now — same story, follow-up cleanup.Companion nango-environments change
Remove
FLAG_ALLOW_OVERRIDE_GETUSAGE_SERVICEfromapps/development/nango-values.yaml. Nothing to do for staging/prod (never set there).Test plan
npm run ts-buildclean.npm run lintclean.npm run format:checkclean.packages/server/lib/controllers/v1/meta/getMeta.integration.test.tsstill passes.GET /api/v1/plans/billing-usage?source=orbno longer routes to Orb (should silently ignore or 400 depending on strict-schema config).🤖 Generated with Claude Code