Skip to content

Labels and sizes

Every cloud gets the same four sizes, at 4 GiB of memory per vCPU, on that cloud’s spot pool of 16-vCPU, 64 GiB VMs:

Label vCPU Memory Jobs per VM
backmesh-2 2 8 GiB 8
backmesh-4 (default) 4 16 GiB 4
backmesh-8 8 32 GiB 2
backmesh-16 16 64 GiB 1

A job gets a fixed share of its VM, a little under the nominal size: about 3% less memory, for the VM’s own system. Its CPU limit equals its request, so a job can’t take a neighbour’s CPU. Sizes aren’t configurable.

With one cloud the labels are backmesh-2 to backmesh-16. With more than one, each label names its cloud:

runs-on: backmesh-aws-4 # or backmesh-gcp-4, backmesh-azure-4

Each label runs in exactly one cloud. backmesh never moves a job to another cloud, so a matrix over clouds is how you spread work:

strategy:
matrix:
cloud: [aws, gcp, azure]
runs-on: backmesh-${{ matrix.cloud }}-4

Each pool launches the first type in its list that has spot capacity:

Cloud Types, in order
AWS m6a.4xlarge, m7a.4xlarge, m6i.4xlarge, m7i.4xlarge
GCP n2d-standard-16, n2-standard-16
Azure Standard_D16as_v5, Standard_D16s_v5

When no type has capacity, jobs wait at GitHub and backmesh status shows the pool’s last error. There are no on-demand labels yet; a job that can’t wait can switch its runs-on to another runner by hand.

Workflows that run large Node.js tools on backmesh-4, such as ESLint over a big repository, set a larger heap:

env:
NODE_OPTIONS: --max-old-space-size=6144

Every label runs one image with the GitHub Actions runner and Docker. A job that needs other tools uses GitHub’s per-job container:. Each job starts with an empty Docker data directory, so no image layers carry over between jobs. Caching is GitHub’s actions/cache, plus the images already pulled on a reused VM.