How CloudBroker Picks the Cheapest VM: Constraints, Scoring, and the Recommendation API #
The interface: from "I need 2 vCPUs in Europe" to a ranked list.
Send a JSON body with constraints; get a list of recommendations, best first. In between: filter (drop what doesn't qualify), then score (price + fit, or multi-criteria). Cheaper and better-fit rank higher. Every recommendation can include an explain block so you see why it ranked where it did.
The request
Parameters you send to POST /api/recommendations:
- min_vcpu, min_ram_gb — minimum specs. Only instance types that meet or exceed these are considered.
- arch (required) —
x86_64orarm64. - region_constraint — e.g.
"EU"to restrict to EU regions (uses theis_euflag on regions). - max_price_eur_per_hour — ceiling in EUR. No candidate above this is returned.
- allowed_providers — list of provider slugs (e.g.
["gcp", "hetzner", "scaleway"]). Only these providers are considered.
Optional TCO: data_source_provider, data_source_region, estimated_egress_gb_per_hour, min_storage_gb, include_public_ip, os_type, max_tco_eur_per_hour.
Optional GPU: min_gpu_count, gpu_type — filter for instances with GPUs.
Optional: preferred_providers (score boost), purchase_model (on_demand, spot), limit (how many results).
Example:
{
"min_vcpu": 2,
"min_ram_gb": 4,
"arch": "x86_64",
"region_constraint": "EU",
"max_price_eur_per_hour": 0.50,
"allowed_providers": ["gcp", "hetzner", "scaleway"]
}
The pipeline: filter, then score
Filter: Drop candidates that don't match specs (vcpu >= min, ram_gb >= min, arch match), GPU (when min_gpu_count or gpu_type are set), price (<= max_price_eur_per_hour), region (e.g. is_eu when region_constraint is EU), and allowed providers. Only the latest price per (instance_type, region) is used.
Score: Two modes. Legacy mode (default): weighted blend of normalized price (cheaper = higher) and resource fit (closer to what you asked = higher). Multi-criteria mode: adds performance and reliability dimensions; hyperscalers get a higher reliability score than regional providers. After the base score, adjustments: preferred providers get a boost; USD-only prices can get a small penalty; spot gets bonus and interruption-risk penalty.
Results are sorted by score descending. Top of the list = recommendation.
The response
Each item includes provider_slug, region_slug, instance_type_name, price_eur_per_hour, score, and optionally explain (resource_fit, normalized_price, weights, region_is_eu, price_eur_per_hour, tco_eur_per_hour, egress_cost_eur_per_hour, storage_cost_eur_per_hour, etc.). When TCO params are provided, explain includes the full cost breakdown.
{
"instance_type_name": "cx23",
"provider_slug": "hetzner",
"region_slug": "fsn1",
"vcpu": 2,
"ram_gb": 4.0,
"price_eur_per_hour": 0.0048,
"score": 0.9898,
"explain": {
"resource_fit": 1.0,
"normalized_price": 0.9797,
"price_weight": 0.5,
"fit_weight": 0.5,
"region_is_eu": true,
"tco_eur_per_hour": null,
"egress_cost_eur_per_hour": null
}
}
See a working response → /examples#recommendations
What CloudBroker doesn't do
No Kubernetes. No VM lifecycle. No notion of "who's calling" — it's a generic API. You (or another service) take the recommendation and provision elsewhere. CloudBroker is the price brain; something like Cloudburst Autoscaler is the provisioner.
So we have an API that, given constraints, returns the best option. The next piece is scope, limits, and how to run it.