Skip to content

Commit

Every sandbox on g1t's runners has 20 GB of disk, the most Cloudflare Containers give one, as much or more than a GitHub-hosted ubuntu-latest's 14 GB: the standard machine (ubuntu-latest and every other hosted label, and all other work) becomes a custom instance type of 1 vCPU, 4 GiB and 20 GB, where standard-1 had half a vCPU and 8 GB, and g1t-2core a custom 2 vCPU, 8 GiB and 20 GB, where standard-3 had 16 GB; g1t-4core stays standard-4, which already had 20 GB. 1 vCPU is the smallest a custom type may have, and Cloudflare bills CPU only as it is used, so the doubled vCPU costs only what a job uses of it. The contracts' instance table, its TypeScript mirror and the billing keeper's standard sandbox say the same sizes; the price scales, worked out as before from Cloudflare's list prices with every vCPU busy and the Durable Object behind each, are now 1.9 for g1t-2core and 3.4 for g1t-4core, against the larger standard machine, and the fallbacks for a sandbox second (33 millionths of a dollar with its vCPU busy) and a build second (16) follow it. A test holds wrangler.jsonc's sizes to the contracts', and another the scales to the list prices. The docs' machine tables, the larger machines' prices and the Cloudflare deploy guide say so.

syntaqxcommitted Parent6f03f2cBrowse files
14 files+136−570/14 viewed
+1−0
319319 | Limit | Value |
320320 | --- | --- |
321321 | Largest machine | 4 vCPUs, 12 GiB of memory, 20 GB of disk (`g1t-4core`). No GPUs. |
322+| Disk | 20 GB on every machine, the most Cloudflare Containers give one. |
322323 | One job on g1t's machines | 60 minutes. On a self-hosted runner, 24 hours. |
323324 | One cache entry | 2 GiB, compressed. A larger one is not saved. |
324325 | A repository's caches | 10 GiB together. Past it, the entries restored longest ago are removed. |
+9−3
7373
7474 | `runs-on` | Class | Size |
7575 | --- | --- | --- |
76−| Any other hosted label, and every other kind of work | `AttemptSandbox` | Cloudflare's `standard-1` |
77−| `g1t-2core` | `Sandbox2Core` | 2 vCPU, 8 GiB memory, 16 GB disk |
78−| `g1t-4core` | `Sandbox4Core` | 4 vCPU, 12 GiB memory, 20 GB disk |
76+| Any other hosted label, and every other kind of work | `AttemptSandbox` | 1 vCPU, 4 GiB memory, 20 GB disk (a custom instance type) |
77+| `g1t-2core` | `Sandbox2Core` | 2 vCPU, 8 GiB memory, 20 GB disk (a custom instance type) |
78+| `g1t-4core` | `Sandbox4Core` | 4 vCPU, 12 GiB memory, 20 GB disk (Cloudflare's `standard-4`) |
79+
80+Each has the 20 GB of disk Containers allow at most. The named instance
81+types with 1 and 2 vCPU come with 8 and 16 GB, so those two are custom
82+instance types (`instance_type` with `vcpu`, `memory_mib` and `disk_mb` in
83+`services/runner/wrangler.jsonc`); 1 vCPU is the smallest a custom type may
84+have.
7985
8086 Every sandbox starts from one image: `services/runner/base/Dockerfile`,
8187 which has Node, Python, Go, Rust, Java, .NET, Ruby and Docker, with the
+2−2
542542
543543 | `runs-on` | vCPUs | Memory | Disk |
544544 | --- | --- | --- | --- |
545−| `ubuntu-latest`, or any other Linux label | 0.5 | 4 GiB | 8 GB |
546−| `g1t-2core` | 2 | 8 GiB | 16 GB |
545+| `ubuntu-latest`, or any other Linux label | 1 | 4 GiB | 20 GB |
546+| `g1t-2core` | 2 | 8 GiB | 20 GB |
547547 | `g1t-4core` | 4 | 12 GiB | 20 GB |
548548
549549 ```yaml
+5−2
305305 minutes, so a deploy never cuts one short; an agent run whose guardrails
306306 allow more than two hours can be.
307307
308−Jobs choose larger machines with `runs-on: g1t-2core` or `g1t-4core`. Your
309−account's Containers limits must allow `standard-4`.
308+Jobs choose larger machines with `runs-on: g1t-2core` or `g1t-4core`.
309+Every sandbox has 20 GB of disk: the standard one and `g1t-2core` are
310+custom instance types (1 vCPU and 4 GiB, and 2 vCPU and 8 GiB), and
311+`g1t-4core` is `standard-4`. Your account's Containers limits must allow
312+all three.
310313
311314 Set the runner Worker's `DOCKER` variable to `off` to give workflow jobs no
312315 Docker Engine.
+5−4
140140 | What | Unit | Costs g1t | You pay |
141141 | --- | --- | --- | --- |
142142 | Sandbox time (workflows, checks, the merge queue) | Second | About $0.001 a minute | About $0.0012 a minute |
143−| [Larger machines](#workflow-jobs-on-larger-machines) for workflow jobs (`g1t-2core`, `g1t-4core`) | Second | About 2.8 and 5.1 times a sandbox second | Cost + 20% |
143+| [Larger machines](#workflow-jobs-on-larger-machines) for workflow jobs (`g1t-2core`, `g1t-4core`) | Second | About 1.9 and 3.4 times a sandbox second | Cost + 20% |
144144 | Deploy builds | Second | About $0.001 a minute | About $0.0012 a minute |
145145 | App requests | Million | $0.30 | $0.36 |
146146 | App CPU time | Million CPU milliseconds | $0.02 | $0.024 |
356356
357357 A workflow job whose `runs-on` names a [larger machine](/guides/actions/#machine-sizes)
358358 runs on a larger Cloudflare Containers instance, and its seconds cost what
359−that instance costs g1t, plus 20%:
359+that instance costs g1t, plus 20%. The standard machine they are compared
360+with has 1 vCPU, 4 GiB and 20 GB:
360361
361362 | `runs-on` | Instance | Its memory and disk, against the standard machine's | A second with its vCPUs as busy as an average sandbox's |
362363 | --- | --- | --- | --- |
363−| `g1t-2core` | 2 vCPU, 8 GiB, 16 GB | 1.9 times | About 2.8 times a sandbox second |
364−| `g1t-4core` | 4 vCPU, 12 GiB, 20 GB | 2.7 times | About 5.1 times a sandbox second |
364+| `g1t-2core` | 2 vCPU, 8 GiB, 20 GB | 1.8 times | About 1.9 times a sandbox second |
365+| `g1t-4core` | 4 vCPU, 12 GiB, 20 GB | 2.5 times | About 3.4 times a sandbox second |
365366
366367 A job that reports its own CPU is priced on it: its memory and disk for
367368 every second, and the vCPU-seconds it used. One that does not is priced
+36−10
10381038 }
10391039
10401040 /// A size of machine g1t runs workflow jobs on, asked for by a label in
1041−/// `runs-on`. Each is a Cloudflare Containers instance type; it costs what
1042−/// that instance costs g1t, plus the margin, like any sandbox time.
1041+/// `runs-on`. Each is a Cloudflare Containers instance type (named, or a
1042+/// custom one: services/runner/wrangler.jsonc), every one with the 20 GB of
1043+/// disk Containers allow at most; it costs what that instance costs g1t,
1044+/// plus the margin, like any sandbox time.
10431045 #[derive(Clone, Copy, Debug, PartialEq)]
10441046 pub struct InstanceType {
10451047 /// The `runs-on` label, or `standard` for the default.
10461048 pub label: &'static str,
1047− /// The Containers instance type.
1049+ /// The Containers instance type: a named one, or `custom` for one
1050+ /// sized by its vCPU, memory and disk.
10481051 pub container: &'static str,
10491052 pub vcpu: f64,
10501053 pub memory_gib: f64,
10521055 /// What a second of it costs g1t as a multiple of the standard
10531056 /// machine's, with its vCPUs as busy (Cloudflare's list prices:
10541057 /// memory $0.0000025 a GiB-second, disk $0.00000007 a GB-second, vCPU
1055− /// $0.00002 a second). Used to reserve before a job starts, and to
1056− /// price a job that did not report its own CPU.
1058+ /// $0.00002 a second, and the Durable Object behind it at 128 MB,
1059+ /// $0.0000125 a GB-second), to one decimal. Used to reserve before a
1060+ /// job starts, and to price a job that did not report its own CPU.
10571061 pub price_scale: f64,
10581062 }
10591063
10601064 /// The default: what `ubuntu-latest` and every other hosted label get.
10611065 pub const STANDARD_INSTANCE: InstanceType =
1062− InstanceType { label: "standard", container: "standard-1", vcpu: 0.5, memory_gib: 4.0, disk_gb: 8.0, price_scale: 1.0 };
1066+ InstanceType { label: "standard", container: "custom", vcpu: 1.0, memory_gib: 4.0, disk_gb: 20.0, price_scale: 1.0 };
10631067
10641068 /// Every machine a workflow job can ask for, the default first.
10651069 pub const INSTANCE_TYPES: [InstanceType; 3] = [
10661070 STANDARD_INSTANCE,
1067− InstanceType { label: "g1t-2core", container: "standard-3", vcpu: 2.0, memory_gib: 8.0, disk_gb: 16.0, price_scale: 2.8 },
1068− InstanceType { label: "g1t-4core", container: "standard-4", vcpu: 4.0, memory_gib: 12.0, disk_gb: 20.0, price_scale: 5.1 },
1071+ InstanceType { label: "g1t-2core", container: "custom", vcpu: 2.0, memory_gib: 8.0, disk_gb: 20.0, price_scale: 1.9 },
1072+ InstanceType { label: "g1t-4core", container: "standard-4", vcpu: 4.0, memory_gib: 12.0, disk_gb: 20.0, price_scale: 3.4 },
10691073 ];
10701074
10711075 /// The machine a job's `runs-on` labels ask for: the largest named, or the
14951499
14961500 #[test]
14971501 fn runs_on_picks_the_machine() {
1498− assert_eq!(instance_for(&labels(&["ubuntu-latest"])).container, "standard-1");
1502+ assert_eq!(instance_for(&labels(&["ubuntu-latest"])), STANDARD_INSTANCE);
14991503 assert_eq!(instance_for(&labels(&[])).label, "standard");
15001504 assert_eq!(instance_for(&labels(&["g1t-4core"])).container, "standard-4");
1501− assert_eq!(instance_for(&labels(&["ubuntu-latest", "G1T-2Core"])).container, "standard-3");
1505+ assert_eq!(instance_for(&labels(&["ubuntu-latest", "G1T-2Core"])).label, "g1t-2core");
15021506 // Both named: the larger.
15031507 assert_eq!(instance_for(&labels(&["g1t-2core", "g1t-4core"])).label, "g1t-4core");
15041508 assert_eq!(instance_named("g1t-4core").map(|i| i.vcpu), Some(4.0));
15071511 }
15081512
15091513 #[test]
1514+ fn every_machine_has_the_most_disk_containers_allow_and_fits_a_custom_type() {
1515+ for instance in INSTANCE_TYPES {
1516+ assert_eq!(instance.disk_gb, 20.0, "{}", instance.label);
1517+ // Custom instance types: 1 to 4 vCPU, at most 12 GiB, at least
1518+ // 3 GiB a vCPU.
1519+ assert!((1.0..=4.0).contains(&instance.vcpu), "{}", instance.label);
1520+ assert!(instance.memory_gib <= 12.0 && instance.memory_gib >= 3.0 * instance.vcpu, "{}", instance.label);
1521+ }
1522+ }
1523+
1524+ #[test]
1525+ fn price_scales_follow_the_list_prices_with_every_vcpu_busy() {
1526+ // Memory, disk and vCPU at Cloudflare's list prices, and the
1527+ // Durable Object behind the container (128 MB), in micros a second.
1528+ let busy = |i: &InstanceType| i.memory_gib * 2.5 + i.disk_gb * 0.07 + i.vcpu * 20.0 + 0.125 * 12.5;
1529+ for instance in INSTANCE_TYPES {
1530+ let scale = busy(&instance) / busy(&STANDARD_INSTANCE);
1531+ assert!((instance.price_scale - (scale * 10.0).round() / 10.0).abs() < 1e-9, "{}: {scale}", instance.label);
1532+ }
1533+ }
1534+
1535+ #[test]
15101536 fn start_args_from_older_callers_read() {
15111537 let args: StartJobArgs = serde_json::from_value(serde_json::json!({
15121538 "job": "job_1", "token": "t", "repo": { "namespace": "acme", "name": "web" }, "timeoutMinutes": 30
+6−6
385385 pub const MICROS_PER_MILLION_REQUESTS: i64 = 300_000;
386386 /// $0.02 per million CPU milliseconds.
387387 pub const MICROS_PER_MILLION_CPU_MS: i64 = 20_000;
388− /// What one second of a build's sandbox costs g1t (Cloudflare
389− /// Containers, standard-1: half a vCPU, 4 GiB, 8 GB disk), rounded up,
390− /// as the price keeper measured it on 2026-10-05 (14.5). Only a
391− /// fallback: billing charges builds at the price book's `build_second`,
392− /// which the keeper keeps current.
393− pub const MICROS_PER_BUILD_SECOND: i64 = 15;
388+ /// What one second of a build's sandbox costs g1t (the standard
389+ /// sandbox, `actions::STANDARD_INSTANCE`), rounded up: the price keeper
390+ /// measured 14.5 on 2026-10-05, when it had 8 GB of disk, and its 20 GB
391+ /// now add 0.84. Only a fallback: billing charges builds at the price
392+ /// book's `build_second`, which the keeper keeps current.
393+ pub const MICROS_PER_BUILD_SECOND: i64 = 16;
394394 /// What one custom hostname costs g1t a month (Cloudflare for SaaS):
395395 /// $0.10.
396396 pub const MICROS_PER_DOMAIN_MONTH: i64 = 100_000;
+4−3
249249
250250 /**
251251 * What one second of a sandbox costs g1t, in millionths of a dollar, when
252− * the price book cannot be read: Containers standard-1 with its Durable
253− * Object, rounded up.
252+ * the price book cannot be read: the standard sandbox (1 vCPU, 4 GiB, 20 GB)
253+ * with its vCPU busy and its Durable Object, 32.96 at list prices, rounded
254+ * up.
254255 */
255−export const FALLBACK_SANDBOX_MICROS_PER_SECOND = 25;
256+export const FALLBACK_SANDBOX_MICROS_PER_SECOND = 33;
256257
257258 /** A sandbox for `minutes` at `microsPerSecond`. */
258259 export function sandboxEstimateMicros(minutes: number, microsPerSecond: number): number {
+12−9
11 /**
22 * Sizes of machine g1t runs workflow jobs on, asked for by a label in
33 * `runs-on`. Mirrors `g1t_contracts::actions::INSTANCE_TYPES`. Each is a
4− * Cloudflare Containers instance type, and costs what that instance costs
5− * g1t, plus the margin, like any sandbox time.
4+ * Cloudflare Containers instance type (named, or a custom one sized in
5+ * services/runner/wrangler.jsonc), every one with the 20 GB of disk
6+ * Containers allow at most, and costs what that instance costs g1t, plus
7+ * the margin, like any sandbox time.
68 */
79 export type InstanceType = {
810 /** The `runs-on` label, or `standard` for the default. */
911 label: string;
10− /** The Containers instance type. */
12+ /** The Containers instance type: a named one, or `custom`. */
1113 container: string;
1214 vcpu: number;
1315 memoryGib: number;
2426 /** The default: what `ubuntu-latest` and every other hosted label get. */
2527 export const STANDARD_INSTANCE: InstanceType = {
2628 label: "standard",
27− container: "standard-1",
28− vcpu: 0.5,
29+ container: "custom",
30+ vcpu: 1,
2931 memoryGib: 4,
30− diskGb: 8,
32+ diskGb: 20,
3133 estimateScale: 1,
3234 };
3335
3436 /**
3537 * Every machine a job can ask for, the default first. The scales follow
3638 * Cloudflare's list prices: memory $0.0000025 a GiB-second, disk
37− * $0.00000007 a GB-second, vCPU $0.00002 a second.
39+ * $0.00000007 a GB-second, vCPU $0.00002 a second, and the Durable Object
40+ * behind each at 128 MB, $0.0000125 a GB-second; to one decimal.
3841 */
3942 export const INSTANCE_TYPES: readonly InstanceType[] = [
4043 STANDARD_INSTANCE,
41− { label: "g1t-2core", container: "standard-3", vcpu: 2, memoryGib: 8, diskGb: 16, estimateScale: 2.8 },
42− { label: "g1t-4core", container: "standard-4", vcpu: 4, memoryGib: 12, diskGb: 20, estimateScale: 5.1 },
44+ { label: "g1t-2core", container: "custom", vcpu: 2, memoryGib: 8, diskGb: 20, estimateScale: 1.9 },
45+ { label: "g1t-4core", container: "standard-4", vcpu: 4, memoryGib: 12, diskGb: 20, estimateScale: 3.4 },
4346 ];
4447
4548 /** An instance type by its label; the standard one for anything else. */
+3−3
854854
855855 #[test]
856856 fn every_build_second_is_metered_at_cost_plus_the_margin() {
857− // A 5-minute build at 15 millionths a second costs g1t 4,500, and
857+ // A 5-minute build at 16 millionths a second costs g1t 4,800, and
858858 // is charged at cost plus 20%, from the first second: there are no
859859 // included build minutes, only the plan's included usage.
860860 let cost = 300 * costs::MICROS_PER_BUILD_SECOND;
861− assert_eq!(cost, 4_500);
862− assert_eq!(crate::credits::with_margin(cost, 20), 5_400);
861+ assert_eq!(cost, 4_800);
862+ assert_eq!(crate::credits::with_margin(cost, 20), 5_760);
863863 }
864864
865865 #[test]
+16−10
187187 memory_byte_seconds: f64,
188188 }
189189
190−/// g1t's sandboxes: Containers' standard-1, half a vCPU, 4 GiB, 8 GB disk.
190+/// g1t's standard sandbox (`STANDARD_INSTANCE` in the contracts): a custom
191+/// Containers instance type of 1 vCPU, 4 GiB and 20 GB of disk.
191192 const SANDBOX_GIB: f64 = 4.0;
192−const SANDBOX_DISK_GB: f64 = 8.0;
193+const SANDBOX_DISK_GB: f64 = 20.0;
193194 const GIB: f64 = 1024.0 * 1024.0 * 1024.0;
194195 /// The Durable Object behind each container is billed for as long as the
195196 /// container runs, at 128 MB.
565566 let usage = ContainerUsage { cpu_seconds: 720.0, memory_byte_seconds: 3600.0 * 4.0 * GIB };
566567 let micros =
567568 sandbox_second_micros(usage, LIST_MEMORY_GIB_SECOND, LIST_DISK_GB_SECOND, LIST_VCPU_SECOND, LIST_DO_GB_SECOND).unwrap();
568− // 4 x 2.5 + 8 x 0.07 + 0.125 x 12.5 + 0.2 x 20 = 16.1225
569− assert!((micros - 16.1225).abs() < 1e-9, "{micros}");
570− // The Durable Object adds about 11% to the second it left out.
571− assert!((sandbox_base_micros(LIST_MEMORY_GIB_SECOND, LIST_DISK_GB_SECOND, LIST_DO_GB_SECOND) - 12.1225).abs() < 1e-9);
569+ // 4 x 2.5 + 20 x 0.07 + 0.125 x 12.5 + 0.2 x 20 = 16.9625
570+ assert!((micros - 16.9625).abs() < 1e-9, "{micros}");
571+ // The Durable Object adds about 14% to the second it left out.
572+ assert!((sandbox_base_micros(LIST_MEMORY_GIB_SECOND, LIST_DISK_GB_SECOND, LIST_DO_GB_SECOND) - 12.9625).abs() < 1e-9);
572573 // Too little use to say anything.
573574 assert!(sandbox_second_micros(ContainerUsage { cpu_seconds: 1.0, memory_byte_seconds: GIB }, 1.0, 1.0, 1.0, 1.0).is_none());
574575 }
577578 fn a_run_that_reports_its_cpu_is_priced_on_it() {
578579 let base = sandbox_base_micros(LIST_MEMORY_GIB_SECOND, LIST_DISK_GB_SECOND, LIST_DO_GB_SECOND);
579580 let vcpu = LIST_VCPU_SECOND * MICROS_PER_DOLLAR as f64;
580− // A 10-minute cargo build that kept its half vCPU busy throughout.
581+ // A 10-minute cargo build that kept half its vCPU busy throughout.
581582 let heavy = run_cost(600, 300.0, base, vcpu);
582− assert!((heavy - (600.0 * 12.1225 + 300.0 * 20.0)).abs() < 1e-6);
583+ assert!((heavy - (600.0 * 12.9625 + 300.0 * 20.0)).abs() < 1e-6);
583584 // The same ten minutes, mostly idle, costs less.
584585 let light = run_cost(600, 30.0, base, vcpu);
585586 assert!(light < heavy);
589590 assert_eq!(run_cost(0, -1.0, base, vcpu), 0.0);
590591 // A larger machine's base: its memory and disk, not its CPU.
591592 assert!((base_scale(SANDBOX_GIB, SANDBOX_DISK_GB) - 1.0).abs() < 1e-12);
592− assert!((base_scale(12.0, 20.0) - 2.72).abs() < 0.01, "{}", base_scale(12.0, 20.0));
593− assert!((base_scale(8.0, 16.0) - 1.87).abs() < 0.01, "{}", base_scale(8.0, 16.0));
593+ assert!((base_scale(12.0, 20.0) - 2.54).abs() < 0.01, "{}", base_scale(12.0, 20.0));
594+ assert!((base_scale(8.0, 20.0) - 1.77).abs() < 0.01, "{}", base_scale(8.0, 20.0));
595+ // Each machine in the contracts, priced from its own memory and disk.
596+ for instance in g1t_contracts::actions::INSTANCE_TYPES {
597+ let scale = base_scale(instance.memory_gib, instance.disk_gb);
598+ assert!(scale >= 1.0 && scale < instance.price_scale.max(1.0) + 1e-9, "{}: {scale}", instance.label);
599+ }
594600 }
595601
596602 #[test]
+1−1
228228 const gate = new ComputeGate(billing({}).binding, memory(), quiet);
229229 assert.equal(await gate.microsPerSecond(), 20);
230230 const down = new ComputeGate(billing({ fail: new Set(["prices"]) }).binding, memory(), quiet);
231− assert.equal(await down.microsPerSecond(), 25);
231+ assert.equal(await down.microsPerSecond(), 33);
232232 });
233233
234234 // ---- Caps -------------------------------------------------------------------------------
+25−0
11 import assert from "node:assert/strict";
2+import { readFileSync } from "node:fs";
23 import { test } from "node:test";
34
45 import type { WorkflowDomain } from "@g1t/contracts";
56
7+import { INSTANCE_TYPES } from "../../../packages/contracts/src/instances.ts";
8+
69 import { SANDBOX_BINDINGS, jobHosts, sandboxNamespace } from "./egress.ts";
710
811 const domains: WorkflowDomain[] = [
4245 assert.equal(sandboxNamespace({ SANDBOX: "standard" }, "Sandbox4Core"), "standard");
4346 assert.deepEqual(Object.keys(SANDBOX_BINDINGS), ["AttemptSandbox", "Sandbox2Core", "Sandbox4Core"]);
4447 });
48+
49+test("each sandbox class is the size the contracts give its runs-on label", () => {
50+ type Size = { vcpu: number; memory_mib: number; disk_mb: number };
51+ // wrangler.jsonc's comments are whole lines.
52+ const text = readFileSync(new URL("../wrangler.jsonc", import.meta.url), "utf8").replace(/^\s*\/\/.*$/gm, "");
53+ const config = JSON.parse(text) as { containers: { class_name: string; instance_type: string | Size }[] };
54+ // The named Cloudflare instance types a machine may be.
55+ const named: Record<string, Size> = { "standard-4": { vcpu: 4, memory_mib: 12 * 1024, disk_mb: 20_000 } };
56+ const classes = Object.keys(SANDBOX_BINDINGS);
57+ assert.equal(INSTANCE_TYPES.length, classes.length);
58+ INSTANCE_TYPES.forEach((instance, i) => {
59+ const type = config.containers.find((c) => c.class_name === classes[i])?.instance_type;
60+ const size = typeof type === "string" ? named[type] : type;
61+ assert.ok(size, `${classes[i]}: ${JSON.stringify(type)}`);
62+ assert.equal(typeof type === "string" ? type : "custom", instance.container, instance.label);
63+ assert.deepEqual(
64+ { vcpu: size.vcpu, memoryGib: size.memory_mib / 1024, diskGb: size.disk_mb / 1000 },
65+ { vcpu: instance.vcpu, memoryGib: instance.memoryGib, diskGb: instance.diskGb },
66+ instance.label,
67+ );
68+ });
69+});
+11−4
55 "compatibility_date": "2026-09-26",
66 "main": "./src/index.ts",
77 "workers_dev": false,
8− // One image (the base plus the runner binary), on three machine sizes.
8+ // One image (the base plus the runner binary), on three machine sizes,
9+ // each with the 20 GB of disk Containers allow at most. The standard and
10+ // g1t-2core machines are custom instance types (1 vCPU is the smallest a
11+ // custom type may have, with at least 3 GiB of memory per vCPU), since
12+ // the named ones that size come with 8 and 16 GB. crates/contracts
13+ // (INSTANCE_TYPES) and services/billing (keeper.rs) say the same sizes.
914 // scripts/deploy.mjs deploys with each image set to the reference it
1015 // built and pushed ("The runner's images" in
1116 // docs.g1t.sh/guides/deploy-to-cloudflare/), so a deploy builds
1419 {
1520 "class_name": "AttemptSandbox",
1621 "image": "./Dockerfile",
17− "instance_type": "standard-1",
22+ // Workflow jobs with `runs-on: ubuntu-latest` (and every other
23+ // hosted label), and all other work: 1 vCPU, 4 GiB, 20 GB.
24+ "instance_type": { "vcpu": 1, "memory_mib": 4096, "disk_mb": 20000 },
1825 "max_instances": 20,
1926 // A deploy replaces sandboxes. Ones that are busy are given this
2027 // long, in seconds, to finish first, so shipping g1t does not
2229 "rollout_active_grace_period": 7200
2330 },
2431 {
25− // Workflow jobs with `runs-on: g1t-2core`: 2 vCPU, 8 GiB, 16 GB.
32+ // Workflow jobs with `runs-on: g1t-2core`: 2 vCPU, 8 GiB, 20 GB.
2633 "class_name": "Sandbox2Core",
2734 "image": "./Dockerfile",
28− "instance_type": "standard-3",
35+ "instance_type": { "vcpu": 2, "memory_mib": 8192, "disk_mb": 20000 },
2936 "max_instances": 10,
3037 "rollout_active_grace_period": 7200
3138 },