Skip to content

draft: feat: Pricing Implementation, Editable Slots in Status Page by admin, dynamic pricing#9040

Closed
royendo wants to merge 48 commits intomainfrom
status-page-slots-modal
Closed

draft: feat: Pricing Implementation, Editable Slots in Status Page by admin, dynamic pricing#9040
royendo wants to merge 48 commits intomainfrom
status-page-slots-modal

Conversation

@royendo
Copy link
Contributor

@royendo royendo commented Mar 12, 2026

Pricing implementation: editable slots in Status Page, CHC auto-scaling on hibernation.

  • Admins can manage slots directly from the project Status page
  • CHC auto-scaling: slots auto-reduce to 1 when ClickHouse Cloud hibernates, restore to rill_min_slots on wake-up
  • "Sync Now" button in CHC Service Details modal for instant status detection
  • Default deploy slots changed from 4 to 1 (all plans start at 1 slot)
  • Slot rate corrected to $0.06/slot/hr (1 slot = 1 vCPU / 4 GB)
  • Popular and "Show all sizes" tier views for both Rill-managed and Live Connect
  • "Unhealthy" status with tooltip when CHC is hibernated/stopping
  • "Preparing project" status while slots are being restored after CHC wake-up
  • Runtime fallback: detects CHC Cloud and fetches live status even when connector is down

Free Plan: 1 slot (upgrade to Growth to customize)
Growth: Variable, managed by admins via Status page
Enterprise: Managed or hidden

docs in #9056

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Developed in collaboration with Claude Code

royendo added 8 commits March 12, 2026 16:31
when on Free plan, view only Cluster size costs, CTA Upgrade to Grwoth Plan
Once upgraded, CHC cannot rquset a tier less than detected. but free to change at any time. SCH can change to any tier at any time RMDuck likewise can change to any tier at any time. DATA OVERAGES ALSO CHARGED

- add rill_min_slots and chc_cluster_size to postgres export for telemetry
- add API endpoint to hit CHC cluster for Cluster info
- oka
…Metrics

CHC Tiers, in admin/clickhouse.go. need confirmation if this was implemented correctly
@royendo royendo changed the title draft: feat: Status page Slots modal draft: feat: Pricing Implementation, Editable Slots in Status Page by admin, dynamic pricing Mar 14, 2026
royendo added 3 commits March 14, 2026 12:18
User cannot manage slots when CHC is hibernated, auto downgrades to 1 slot as 0 slot is not usable ie free. when user restarts CHC, we start Rill,

Full tier list, add sync now button to get current CHC settings.
@royendo
Copy link
Contributor Author

royendo commented Mar 16, 2026

v0 feedback:

  • hide CHC Slots,
  • Adjust $/hr values to match 1/4 not 1/2 ratio
  • Need Org level slot tracking and billing info
  • when upgrading keep all slost at 1, need to manually change each project. 1=free

@royendo
Copy link
Contributor Author

royendo commented Mar 16, 2026

once confrimed on behavior, will split into smaller PRs

@royendo
Copy link
Contributor Author

royendo commented Mar 16, 2026

PR 1: Growth plan support
  - admin/billing/biller.go — Add GrowthPlanType
  - admin/billing/orb.go — getPlanType + getPlanDisplayName for "growth"
  - web-admin/.../billing/plans/utils.ts — isGrowthPlan()
  - web-admin/.../billing/plans/Plan.svelte — Route Growth to TeamPlan component

  PR 2: Slot pricing & tiers fix
  - admin/clickhouse_cloud.go + test — Halve CHC tier slots (1 slot = 4GB)
  - web-admin/.../slots-utils.ts + test — Fix tier calculation, $0.06/hr rate, popular + all sizes
  - web-admin/.../ManageSlotsModal.svelte — Show all sizes toggle, scrollable list, both Rill-managed and Live Connect
  - cli/pkg/local/slots.go — Default to 1 slot

  PR 3: MotherDuck detection
  - runtime/drivers/duckdb/duckdb.go — Inject is_motherduck in Config()
  - runtime/server/instances.go — Pass through is_motherduck in enrichment
  - web-admin/.../DeploymentSection.svelte — MotherDuck display (just the detection + OLAP label part)

  PR 4: CHC Cloud detection & status UI
  - runtime/server/instances.go — enrichConnectorFromResolvedConfig fallback
  - runtime/connections.go — Map CHC API keys to connector config
  - runtime/drivers/clickhouse/clickhouse.go — Immediate CHC poll on startup
  - web-admin/.../DeploymentSection.svelte — Unhealthy/Preparing status, hibernation tooltip, View Details always shown
  - web-admin/.../ClickHouseCloudDetailsModal.svelte — Sync Now button, local state overrides

  PR 5: CHC auto-scaling slots on hibernation
  - admin/jobs/river/billing_reporter.go — defer syncCHCCloudInfo, direct CHC API call, auto-scale logic, fetchCHCInfoDirectly
  - admin/server/projects.go — Clear auto-scale annotation on manual slot change
  - admin/server/clickhouse_cloud.go — /v1/clickhouse-cloud/sync endpoint
  - web-admin/.../DeploymentSection.svelte — Auto-scale message, isChcAutoScaled, isChcRestoring

  PR 6: Emit prod_slots metric for Orb billing
  - runtime/registry.go — Emit prod_slots in heartbeat

royendo added 6 commits March 16, 2026 19:30
…AN_TYPE_GROWTH = 6 - Added BILLING_ISSUE_TYPE_CREDIT_LOW = 8, CREDIT_CRITICAL = 9, CREDIT_EXHAUSTED = 10 - Added BillingCreditInfo message with total/used/remaining credit, expiry, and burn rate - Added credit_info field to GetBillingSubscriptionResponse - Added credit metadata messages (BillingIssueMetadataCreditLow, CreditCritical, CreditExhausted) with oneof entries Backend (biller.go, orb.go, noop.go): - Added FreePlanType and GrowthPlanType constants - Added CreditBalance struct - Added GetCreditBalance() to Biller interface - Orb implementation queries credit grants via Customers.Credits.ListByExternalID, aggregates active grants, calculates burn rate - Noop biller returns nil (no credits) - Updated getPlanType() and getPlanDisplayName() for new plan names (free, growth + mode variants) Database (database.go, postgres.go): - Added BillingIssueTypeCreditLow/Critical/Exhausted constants - Added metadata structs for credit issues - Updated postgres DTO deserialization to handle new issue types - CreditLow is warning level; CreditCritical and CreditExhausted are error level Server (billing.go): - GetBillingSubscription now returns credit_info for free-tier orgs - All DTO conversion functions updated for new plan types and issue types Generated clients: Proto regenerated, TS clients updated via Orval.
…ts): - Added MANAGED_SLOT_RATE_PER_HR = 0.15, CLUSTER_SLOT_RATE_PER_HR = 0.06, RILL_SLOT_RATE_PER_HR = 0.15 - Added STORAGE_RATE_PER_GB_PER_MONTH = 1.0, INCLUDED_STORAGE_GB = 1 - Added MANAGED_SLOT_TIERS, CLUSTER_SLOT_TIERS, RILL_SLOT_TIERS arrays - Legacy SLOT_RATE_PER_HR = 0.06 preserved for Team plan customers ManageSlotsModal (ManageSlotsModal.svelte): - New props: useNewPricing, clusterSlots, currentRillSlots - Managed mode: dynamically uses $0.15/hr (new pricing) or $0.06/hr (legacy) based on plan - New pricing Live Connect: two-section UI — Cluster Slots (read-only info box) + Rill Slots (selectable table starting at 0) - Shows estimated total cost (cluster + rill combined) - Legacy Live Connect path preserved for Team plan customers DeploymentSection (DeploymentSection.svelte): - Detects Free/Growth plans → useNewPricing = true - Derives clusterSlots from rillMinSlots (set by backend CHC sync) - New pricing Live Connect: shows separate "Cluster Slots" (auto-calculated, read-only) and "Rill Slots" (with Manage button) rows - Free plan: shows "Upgrade to Growth" instead of "Upgrade to Team Plan" - Passes new props to ManageSlotsModal That wraps up Phase 4. Phases 1, 2, and 4 are done. Remaining: Phase 3 (flesh out plan components + upgrade flow), Phase 5 (credit banners + hibernation), Phase 6 (migration). Want to continue with one of those, or commit what we have?
royendo and others added 23 commits March 17, 2026 18:17
…itExhausted, returning "free credit exhausted". StartTrial — when the default plan is FreePlanType: - Skips incrementing trial org count - Skips raising the OnTrial billing issue - Logs "started free plan" instead of "started trial" - Falls through to the existing quota/cleanup logic (subscription + billing issues still cleaned up correctly) UpdateBillingSubscription — when upgrading to Growth: - Checks for CreditExhausted issue before cleanup - After quota update + issue cleanup, wakes all hibernated projects (PrimaryDeploymentID == nil) by calling RedeployProject - Logs the un-hibernate event
…b.F("USD") to the ListByExternalID call — without this, Orb returns credits in all currencies and the result can be ambiguous - Fixed MaximumInitialBalance = 0 case: when Orb doesn't track the original cap (plan-granted credits), falls back to using Balance as the total so the balance still shows correctly instead of being skipped VoidCredits (new): - Lists all active USD credit blocks for the customer - Voids each one via Ledger.NewEntryByExternalID with entry_type: "void" - Called in UpdateBillingSubscription when upgrading to Growth — credits don't carry over per the spec Free plan onboarding email: - RepairOrganizationBilling no longer sends SendTrialStarted when the default plan is FreePlanType — that email references a trial end date which doesn't exist for free plans
- proto/gen: take ours (HEAD) — contains new billing credit/growth types
- BillingCTAHandler.ts: merge GrowthPlanDialogTypes (ours) + fetchOrganizationBillingIssues (main)
- Payment.svelte: adopt main's pendingSetup pattern, add onFreePlan to hide payment for free-plan orgs
- DeploymentSection.svelte: keep ours (CHC Cloud management buttons)
- billing.go: remove req.Setup reference removed from proto by main

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MD confirmed working, CHC confirmed working,  SMCH.   working,
@royendo
Copy link
Contributor Author

royendo commented Mar 19, 2026

closing for rill-slots view

@royendo royendo closed this Mar 19, 2026
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