Skip to content

feat: Flexible HTTPS outcalls and pay-as-you-go pricing - #714

Merged
lwshang merged 5 commits into
mainfrom
eichhorl/flexible-outcalls-pricing
Sep 15, 2026
Merged

lwshang merged 5 commits into
mainfrom
eichhorl/flexible-outcalls-pricing

Conversation

@eichhorl

@eichhorl eichhorl commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Description

Implement support for flexible HTTPS outcalls (flexible_http_request), which allow a canister to specify how many nodes on the subnet should perform the requests, and out of those, how many responses are required/accepted to be received.

Additionally, implement support for the new "pay-as-you-go" pricing for all HTTPS outcalls. Previously, HTTPS outcalls were charged in advance based on the request_bytes and (user predicted) max_response_bytes. This was problematic, because setting max_response_bytes to small meant failing the call, whereas setting it too large meant wasting cycles.

Pay-as-you-go pricing only charges a base fee in advance, and reserves the remaining cycles that were attached as a budget against which the outcalls are performed by each replica. In the end, unspent cycles of this budget are refunded to the user.

Flexible outcalls always use the new pricing version 2. "Normal" outcalls made via http_request technically continue to support (and default to) the old pricing version 1. However, this PR switches the CDK's wrappers to always use version 2.

The recommended cycles budget to attach to a call is calculated via a new system API cost_http_request_v2. The CDK does so automatically using the maximum sensible values. The maxima may be overwritten by functions of the new HttpRequest builder. This allows developers to tighten the cycles reservation which will be locked up throughout the call, by supplying the estimated resource consumption of their call.

Added

  • HttpRequest, a builder for http_request. It always selects pricing version 2 ("pay-as-you-go"), which charges for the resources the outcall consumes rather than for max_response_bytes.
  • FlexibleHttpRequest, a builder for the new flexible_http_request method, in which a committee of nodes return their individual HTTP responses instead of the subnet reaching consensus on one.
  • with_expected_roundtrip_time_ms, with_expected_raw_response_bytes, with_expected_transformed_response_bytes and with_expected_transform_instructions on both builders. Under pricing version 2 the attached cycles are also the budget each node may spend, so these narrow the reservation from "the most the outcall could consume" to what the caller expects. Anything left unset falls back to the maximum, which yields a reservation the outcall cannot exhaust but which holds far more cycles for the duration of the call.
  • with_transform_closure on both builders, replacing the free function http_request_with_closure and extending closure transforms to flexible outcalls.
  • cost_http_request_v2 and its argument types CostHttpRequestV2Args and HttpOutcallType.
  • Re-exports of SnapshotVisibility and StatusVisibility, the types of the CanisterSettings and DefiniteCanisterSettings fields of the same name, and of RenameCanisterRecord and RenameToRecord, the payload of ChangeDetails::RenameCanister. All four were reachable only by depending on ic-management-canister-types directly, which left those fields impossible to construct or match on.
  • Re-exports of the new ic-management-canister-types items: FlexibleHttpRequestArgs, FlexibleHttpRequestResult, FlexibleHttpRequestErr, FlexibleHttpGlobalError, FlexibleHttpNodeDetail, FlexibleHttpNodeError, HttpRequestResourceReport, ReplicationCounts and ResourceUsage.
  • api::subnet_self_node_count, returning the number of nodes on the subnet. Useful for computing valid replication bounds for flexible_http_request.
  • api::cost_http_request_v2, pricing a canister HTTPS outcall under pricing version 2. It takes the Candid-encoded parameter record; prefer the typed wrappers in ic-cdk-management-canister.

Removed

  • The free functions http_request, cost_http_request and http_request_with_closure. Use HttpRequest instead, which prices the outcall with version 2. Migrating deliberately rather than switching the pricing version underneath an unchanged call is the reason this is a breaking change rather than a silent one.
    • HttpRequest::from_args accepts an existing HttpRequestArgs, so an existing call site can be migrated without rewriting how it builds its arguments.
    • ic_cdk::api::cost_http_request still exposes version 1 pricing for callers that need it.

Changed

  • ic-management-canister-types bumped from 0.7.1 to 0.10, which adds the pricing_version field to HttpRequestArgs, the flexible_http_request types, and three fields to CanisterSettings.

How Has This Been Tested?

  • New tests were added

Checklist:

  • The title of this PR complies with Conventional Commits.
  • I have edited the CHANGELOG accordingly.
  • I have made corresponding changes to the documentation.

@eichhorl
eichhorl marked this pull request as ready for review September 14, 2026 08:28
@eichhorl
eichhorl requested a review from a team as a code owner September 14, 2026 08:28
@zeropath-ai

zeropath-ai Bot commented Sep 14, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to fc0b3c4.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► e2e-tests/src/bin/management_canister.rs
    Update to include minimum_incoming_canister_call_cycles, snapshot_visibility, and status_visibility in basic management canister settings
Enhancement ► e2e-tests/src/bin/timers.rs
    Replace http_request_with_closure usage with HttpRequest builder and transform closure
Enhancement ► e2e-tests/tests/http_request.rs
    Update tests to use new HttpRequest and FlexibleHttpRequest APIs, add expected headers helper, adjust transform tests, and support for flexible requests
Enhancement ► ic-cdk-management-canister/src/lib.rs
    Introduce HttpOutcallType, CostHttpRequestV2Args, cost_http_request_v2, and related pricing/reservation logic; update imports and re-exports to include new flexible HTTP types and visibility enums; expand HttpRequest-related types
Enhancement ► ic-cdk-management-canister/CHANGELOG.md
    Add entries for new HttpRequest, FlexibleHttpRequest, and related pricing/types; note breaking changes and new re-exports
Enhancement ► ic-cdk-management-canister/README.md
    Docs update to mention HttpRequest and FlexibleHttpRequest pricing and HTTPS outcalls path
Enhancement ► ic-cdk-management-canister/src/lib.rs
    Extensive type and API surface additions: FlexibleHttp*, HttpRequest*, ReplicationCounts, Visibility enums, and associated imports/exports; updated cost/pricing logic scaffolding; integration of new data structures and constants
Bug Fix ► e2e-tests/tests/api.rs
    Test to verify call_subnet_self_node_count returns a valid result (subnet node count)
Bug Fix ► e2e-tests/src/bin/api.rs
    Add test canister update call for call_subnet_self_node_count to ensure presence and no panic
Refactor ► e2e-tests/src/bin/http_request.rs
    Refactor HTTP request tests to use new HttpRequest builder patterns and expected headers helper function
Other ► ic-cdk-management-canister/CHANGELOG.md
    Add new sections under unreleased with Added, Removed, and Changed entries related to HttpRequest and pricing model

@eichhorl
eichhorl requested a balanced review from Copilot September 14, 2026 09:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

- Document the cap that the flexible builder applies to the default expected
  transformed response size, which the previous doc contradicted.
- Price every `outcall_type` variant through `cost_http_request_v2` on a
  replica, including `fully_replicated`, whose `reserved` payload was the one
  encoding no test exercised.
- Cover a flexible outcall over a committee of three nodes with differing
  responses, so that each node transforming its own response via a closure is
  pinned down rather than only the single node case.
- Mark the breaking CHANGELOG entries and note that pricing version 2 requires
  a replica providing `ic0.cost_http_request_v2`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lwshang
lwshang merged commit 045daf7 into main Sep 15, 2026
17 checks passed
@lwshang
lwshang deleted the eichhorl/flexible-outcalls-pricing branch September 15, 2026 12:14
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.

3 participants