4.10 Costs
We aim to spend on use, not on things left running. Every service, consumer, relay and sweeper scales to zero (see Running on Demand), notebooks are stopped and no model endpoint is kept on. What remains fixed is the Cloud SQL instance of stage and prod, the public edge of prod and stage (load balancer and fixed addresses, plus Cloud Armor in prod only) and the HSM keys of prod. This page shows what each environment is expected to cost at the start, and how budgets warn us before a bill surprises us.
4.10.1 Expected Monthly Spend¶
Expected spend at the start of production: about 20 dairy farms, each sending about 10,000 observations a day (a million a day at 100 farms), November 2026 list prices, updated on 2026-11-11. Bars split the database (Cloud SQL) from everything else.
| Environment | Includes | € per month | Likely range | € per year |
|---|---|---|---|---|
| Shared | Cloud Build, Cloud Deploy, registry, log archive, seed, the docs site | 80 | 46–146 | 960 |
| Sandbox | Three personal sandboxes | 10 | 0–150 | 120 |
| Stage | A shared-core Cloud SQL instance, the load balancer (no Cloud Armor since 2026-11-11), software keys, services while used | 44 | 38–60 | 528 |
| Prod | A highly available 1 vCPU Cloud SQL instance, edge and the download CDN, NAT, the HSM keys of access and releases, the platform, farm, grant and ML projects | 248 | 176–576 | 2,976 |
| Total | 382 | 260–932 | 4,584 |
The figures come from the cost diagram, with November 2026 list prices at 1 USD = 0.92 EUR, for about twenty farms. Cloud Build is the largest shared line, about €55 a month for Rust builds on 8 vCPU machines, which the free build minutes do not cover; Cloud Deploy adds €5 a month for each pipeline after the first. The diagram also shows the design this replaced, with an always-on worker for every relay and consumer: about €777 a month without development, most of it workers that waited for work (replaced on 2026-11-05). Cloud SQL is the Enterprise edition in Milan: about €110 a month in prod for a 1 vCPU, 3.75 GB instance with its standby in a second zone (high availability doubles instance and storage) and about €9 for a shared-core instance in development and stage, plus storage and backups. They leave out what is billed outside Google Cloud (below) and Google Workspace, GitHub, domains and VAT.
Cloud Armor runs in prod only (decided 2026-11-11): stage relies on IAP and the URL map. Cloud Armor Standard costs about 5 USD a month per policy, 1 USD a month per rule and 0.75 USD per million requests; we use no hierarchical policy. The stage estimate above still counts one policy, so stage costs a few euros less until the cost diagram is updated.
Development runs only on each developer's computer, with Docker (decided 2026-11-11), so it costs nothing in Google Cloud. Identity Platform costs nothing up to 50,000 monthly active users with e-mail, password and Google sign-in, and IAP costs nothing; the signing keys of releases and the download CDN are already in the lines of stage and prod.
Outside Google Cloud¶
| Service | Used for | € per month |
|---|---|---|
| Brevo | The e-mails of access and releases |
0 up to 300 e-mails a day, then about 9–25 |
| Sentry (EU) | Errors and crashes of every system | 0 on the free plan; about 25 on the Team plan when the volume needs it |
| Cloudflare | The landing, News and status pages, the status feed and its watchdog | 0–5 |
Billed by Use¶
Vertex AI is billed per call, through ai_gateway, and is not in the table: what MooChat and the models cost depends on how much they are used and which models the profiles choose. Model Armor is billed per call in the same way.
The chart is drawn by uv run --group charts docs-charts in this repository; change the numbers in src/moonitoring_docs/charts.py together with the table.
As We Grow¶
Past a few hundred farms the bill is mostly the database, and in the database it is storage: about 1.1 GB per farm per year. With a highly available Cloud SQL instance, the cost diagram estimates about €570 a month at 300 farms, €1,360 at 1,000 and €7,260 at 10,000. Keeping 6 to 12 months of data in the database and moving older partitions to Parquet files in Cloud Storage divides that line by 5 to 10.
4.10.2 Budgets and Alerts¶
Every folder has a budget, set in Terraform in the org root. A budget does not stop spending by itself; it sends alerts to the platform engineers:
| Alert | When |
|---|---|
| Early warning | 50% of the month's budget spent |
| Act now | 90% of the month's budget spent |
| Forecast | The month is forecast to exceed 100% |
- The organization budget for Google Cloud is €400 a month.
- Sandbox stops itself: at 100% a function disables billing on the sandbox project. Its resources stop and may be deleted, which is acceptable for a sandbox.
- Prod never stops itself. An alert in prod is a task for a person, not an automatic shutdown.
4.10.3 What to Watch¶
- Data Access logs are billed by volume. Enable them only where they are needed.
- A new public edge (load balancer and Cloud Armor) adds about €20 to €25 a month per environment.
- An always-on worker (a Cloud Run worker pool, or a job started every few minutes) costs about €10 to €30 a month each. None is used; a new one needs a reason written in the pull request.
- HSM keys cost about €2.30 a month per key version, including rotated versions kept for verification; only prod uses them.
- The total is close to the €400 budget. Cloud Build is the line to watch: compiled dependencies are cached and pull requests build no images.
- The Cloud SQL instance of prod is the largest single line. Its size is reviewed when its CPU or memory stays above 70% or below 20% for a month.
- The stage instance can be stopped outside working hours; a stopped instance bills only its storage.
- A recovery clone is a full instance billed while it exists: delete it as soon as the recovery is done.
- A Cloud NAT with fixed addresses adds about €10 to €15 a month; only prod has one.
- Anything with a minimum instance (Cloud Run minimum instances, a model endpoint, a running notebook) costs every hour of the month. It needs a reason written in the pull request.

