Skip to content

Runner right-sizing

Avrea measures the CPU, memory and disk every job uses on its runner, and suggests a smaller runner when a job leaves most of its capacity idle, or a larger one when it runs out of headroom. Suggestions cover jobs that run on Avrea runner labels.

Each job's recent successful runs are grouped by the runner size they ran on. A group needs at least 3 runs before it gets a verdict. Avrea compares the group's mean CPU use and its peak memory and disk use with the runner's capacity:

VerdictWhen
Size upPeak memory reaches 75%, peak disk 90%, or mean CPU 75% of capacity
Size downPeak memory stays under 25%, peak disk under 35% and mean CPU under 35%, and the same usage also fits a smaller runner (or the job already runs on the smallest size)
Sized rightAnything in between
Not enough usage data yetFewer than 3 runs

The gap between the two thresholds keeps a job near a boundary from switching back and forth between suggestions.

  • Size down suggests the smallest runner the job still fits, which can be several sizes down (8 vCPU to 2, for example). It is only suggested when that runner would not itself need to size up. A job already on the smallest size gets Size down without a suggested label.
  • Size up suggests the next larger size with more of each resource that ran out, which can skip sizes that add only CPU or only memory. When only the disk is full, it suggests the smallest size with enough disk; if no size has more disk, there is no suggestion.
  • Persistent disk. A full persistent disk is not fixed by a larger runner, so it is flagged without a suggested label.
  • Available sizes follow the operating system: macOS offers 8 and 16 vCPU, ARM Linux goes up to 16, and Windows offers 2 to 16.
  • Labels are suggested only for the size each job runs on now. Groups for sizes a job has already moved off keep their verdict but no suggestion.
  • Job and run pages. When a finished job should change size, its row shows a Size up or Size down badge, and the job shows a one-line explanation with the runner label to switch to. The badge opens the workflow's right-sizing view.
  • Workflows tab. In a repository's Workflows tab, choose Right-size on a workflow to open a per-job breakdown over the last day, 7 days or 30 days. Filter by verdict, follow a job to its recent runs, and copy the Prompt for an AI assistant: paste it into your coding assistant to apply the suggested labels to the workflow file.

Suggestions are refreshed at most hourly, so runs from the last hour may not be counted yet. Changing a workflow's runs-on labels starts fresh suggestions.

Fetch the same suggestions from https://api.avrea.com. Authenticate with an API key: avr auth login, then avr auth status --show-token prints it. The caller must be a member of the organization and have read access to the workflow's repository. Look up IDs with avr org list --json organization_id, avr repo list --json full_name,repository_id and avr workflow list --json name,workflow_id.

Terminal window
curl -H "Authorization: Bearer avk_your_api_key" \
"https://api.avrea.com/orgs/{org_id}/workflows/{workflow_id}/right-sizing?window_days=7"
ParameterDescription
window_daysRuns from the last 1 to 30 days. Default 30.
created_afterRuns created at or after this ISO 8601 time, at most 30 days ago. Use instead of window_days, not with it.

At most the 1,000 most recent runs are considered. When the window held more, the response sets execution_limit to that cap, and the runs used may cover less than the window.

Terminal window
curl -H "Authorization: Bearer avk_your_api_key" \
"https://api.avrea.com/orgs/{org_id}/repos/{repo_id}/workflows/right-sizing?workflow_ids=wfl-...&workflow_ids=wfl-...&window_days=7"

Pass up to 50 workflow_ids and an optional window_days (default 30). data holds one response per workflow, in the shape below. IDs that are unknown or belong to another repository are skipped. Workflows that could not be computed within 20 seconds are listed in unavailable; fetch those individually later, or repeat the request.

{
"workflow_id": "wfl-…",
"created_after": "2026-10-12T09:00:00Z",
"jobs": [
{
"job_name": "build",
"shape": {"cpu_count": 8, "memory_mb": 30720, "disk_gb": 300},
"execution_count": 42,
"summary": {"cpu_avg_ratio": 0.18, "memory_max_ratio": 0.12, "disk_max_ratio": 0.02, "truncated": false},
"verdict": "decrease",
"reasons": [],
"current": true,
"persistent_disk_full": false,
"root_disk_full": false,
"current_label": "avrea-ubuntu-24.04-8-vcpu",
"suggested_label": "avrea-ubuntu-24.04-2-vcpu",
"suggested_shape": {"cpu_count": 2, "memory_mb": 7680, "disk_gb": 14}
}
],
"workflow": []
}

jobs has one group per job name and runner size. workflow has one group per runner size across all of the workflow's jobs. In each group:

FieldMeaning
shapeRunner size the counted runs used
execution_countSuccessful runs with complete usage data
summarycpu_avg_ratio (mean), memory_max_ratio and disk_max_ratio (peaks), each between 0 and 1. truncated is true when some run's data covers only part of the run
verdictincrease, decrease, keep or insufficient_data
reasonsResources over their size-up threshold: cpu, memory, disk
currentfalse for a size the job has moved off; such groups get no suggestion
current_labelThe runs-on label of the latest run; omitted when unknown, when the latest run's label is for a different size, or for a workflow group whose jobs use different labels
suggested_label, suggested_shapeThe label to switch to and its size; omitted when there is no suggestion
root_disk_full, persistent_disk_fullThe root or persistent disk is over the size-up threshold
StatusWhen
404Workflow not found, or no access to its repository
422window_days out of range, created_after in the future or more than 30 days ago, both given, or more than 50 workflow_ids
429Rate limit exceeded
503One-workflow endpoint only: the workflow could not be computed in time. Retry after the Retry-After header, or ask for a shorter window. The repository endpoint lists such workflows in unavailable instead

Results for window_days (or the default) are cached for up to an hour. A request with created_after is always computed fresh.