Skip to content

Add Bencher Bare Metal Stripe product#715

Merged
epompeii merged 7 commits intodevelfrom
u/ep/prod-bare-metal
Mar 20, 2026
Merged

Add Bencher Bare Metal Stripe product#715
epompeii merged 7 commits intodevelfrom
u/ep/prod-bare-metal

Conversation

@epompeii
Copy link
Member

This changeset adds the Bencher Bare Metal Stripe product. Further, the Bencher Cloud annual license has been removed. All licenses are now for Bencher Self-Hosted only.

@github-actions
Copy link

github-actions bot commented Mar 19, 2026

🤖 Claude Code Review

PR: #715
Base: devel
Head: u/ep/prod-bare-metal
Commit: 6b721d94d3148db11097ec172cc0d3189cf3ada2


Here's my review:


PR Review: Billing Bare Metal + Licensed Plan Cleanup

Commits: 7 commits covering bare metal billing, licensed plan simplification, OCI timeout, and test improvements.

Overall Assessment

This is a well-structured set of changes that: (1) adds a bare_metal Stripe product as a mandatory line item on every subscription, (2) removes the CloudLicensed usage kind since licensed plans on Bencher Cloud are now exclusively self-hosted, and (3) simplifies the Licensor::into_json API by removing the self_hosted field.

Issues

1. bare_metal_price called before into_plus_price consumes self (biller.rs:217-218)

let bare_metal_price = plus_plan.bare_metal_price(&self.products)?;
let (plus_price, entitlements) = plus_plan.into_plus_price(&self.products)?;

bare_metal_price takes &self while into_plus_price takes self — this works because PlusPlan is Clone (derived), but the code relies on the borrow ending before the move. This is fine today, but worth noting that bare_metal_price re-extracts the usage variant and price_name that into_plus_price also extracts. Consider a single method that returns both prices to avoid the redundant pattern matching.

2. Bare metal line item added unconditionally for metered (non-licensed) plans

In new_checkout_session and create_subscription, the bare metal line item is always added regardless of whether the plan is metered or licensed. For metered-only cloud users who don't use bare metal, they'll see an extra line item in their Stripe checkout. Verify this is the intended billing model — that every subscriber pays for bare metal access.

3. bare_metal_price falls back to "default" key inconsistently

into_plus_price does a direct get(&price_name) with no fallback to "default". But bare_metal_price also does a direct get(price_name.as_str()) with no fallback. Meanwhile, Product::preferred_price_ids uses .or_else(|| self.metered.get(DEFAULT_PRICE_NAME)). The fallback behavior is inconsistent — if a preferred/non-default key is used, bare_metal_price will fail even if a "default" price exists.

4. Breaking API change: JsonLicense.self_hosted and UsageKind::CloudLicensed removed

The self_hosted field is removed from JsonLicense and CloudLicensed is removed from UsageKind in the OpenAPI spec and TypeScript types. This is a breaking change for any API consumers. Make sure this is coordinated with a version bump or migration plan.

5. Validation duplication (checkout.rs:66 vs plan.rs:167)

The same guard — entitlements.is_some() && self_hosted.is_none() — appears in both checkouts_post_inner and post_inner (plan.rs), but with a subtle difference: plan.rs additionally checks context.is_bencher_cloud. The checkout endpoint doesn't check is_bencher_cloud, meaning it would reject licensed-without-self-hosted even on self-hosted instances. If the checkout endpoint is only reachable on Bencher Cloud this is fine, but worth confirming.

Minor Notes

  • Test data correctly updated: old "metrics" key removed, "default" now points to new price IDs, and bare_metal test product added.
  • The filter_subscription_items_excludes_bare_metal test is a good addition.
  • OCI timeout (timeout-minutes: 5) in deploy.yml is sensible — prevents a hung OCI conformance test from blocking the pipeline.
  • Adding sentry and otel to bencher_api_tests default features is appropriate for test coverage.
  • The #[expect(clippy::too_many_lines)] removal on get_inner (usage.rs) is valid since the function was shortened by removing the CloudLicensed branch.

Summary

The changes are clean and well-tested. The main concerns are: (1) confirming that bare metal billing on every subscription is intentional, (2) the missing is_bencher_cloud check in the checkout endpoint validation, and (3) awareness that this is a breaking API change.


Model: claude-opus-4-6

@github-actions
Copy link

github-actions bot commented Mar 19, 2026

🐰 Bencher Report

Branchu/ep/prod-bare-metal
Testbedubuntu-22.04
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
Adapter::Json📈 view plot
🚷 view threshold
3.74 µs
(+6.49%)Baseline: 3.52 µs
4.66 µs
(80.43%)
Adapter::Magic (JSON)📈 view plot
🚷 view threshold
3.68 µs
(+5.43%)Baseline: 3.49 µs
4.57 µs
(80.58%)
Adapter::Magic (Rust)📈 view plot
🚷 view threshold
25.82 µs
(+1.12%)Baseline: 25.54 µs
31.38 µs
(82.29%)
Adapter::Rust📈 view plot
🚷 view threshold
2.79 µs
(-1.46%)Baseline: 2.83 µs
3.30 µs
(84.33%)
Adapter::RustBench📈 view plot
🚷 view threshold
2.77 µs
(-1.93%)Baseline: 2.82 µs
3.29 µs
(84.14%)
head_version_insert/batch/10📈 view plot
🚷 view threshold
105.56 µs
(+5.16%)Baseline: 100.38 µs
118.45 µs
(89.12%)
head_version_insert/batch/100📈 view plot
🚷 view threshold
236.99 µs
(-0.42%)Baseline: 237.99 µs
266.67 µs
(88.87%)
head_version_insert/batch/255📈 view plot
🚷 view threshold
463.83 µs
(+0.22%)Baseline: 462.81 µs
499.49 µs
(92.86%)
head_version_insert/batch/50📈 view plot
🚷 view threshold
161.87 µs
(+0.40%)Baseline: 161.22 µs
183.81 µs
(88.06%)
threshold_query/join/10📈 view plot
🚷 view threshold
143.71 µs
(-0.89%)Baseline: 145.00 µs
170.04 µs
(84.51%)
threshold_query/join/20📈 view plot
🚷 view threshold
156.55 µs
(-1.91%)Baseline: 159.59 µs
187.40 µs
(83.54%)
threshold_query/join/5📈 view plot
🚷 view threshold
137.67 µs
(+0.35%)Baseline: 137.19 µs
160.87 µs
(85.58%)
threshold_query/join/50📈 view plot
🚷 view threshold
200.76 µs
(-0.06%)Baseline: 200.89 µs
232.73 µs
(86.26%)
🐰 View full continuous benchmarking report in Bencher

@epompeii epompeii merged commit e040a0c into devel Mar 20, 2026
166 of 171 checks passed
@epompeii epompeii deleted the u/ep/prod-bare-metal branch March 20, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant