T 200
uid: T-200 title: August GCP bill investigation β "24/7 container" claim refuted; spike = Gemini agent burst status: done area: infra created: 2026-08-06 updated: 2026-08-06 owner: girafeev1 assignee: EOP Local Assistance (Jefito) related: T-015, T-171, T-148
β Read AGENTS.md Β· EOP Local Assistance (Jefito) Β· local session 8ab2d4ce-6acc-4a26-ad72-c5bf1964cad2 Β· checked the board by scope (no dup β T-015 was the June cropper fix, T-171 the July Cloud Run retirement; neither covers the AUGUST spike or the fresh always-on-container claim) Β· tracking T-200. Source: EOP Local Assistance (Jefito) Β· local session 8ab2d4ce-6acc-4a26-ad72-c5bf1964cad2
Why this exists¶
The owner's Google Cloud bill looked oddly expensive again in early August 2026. A separate agent the owner consulted claimed "there's a container running 24/7 on Google Cloud" and the owner asked for verification + downscaling. This task records the verification so the next cost hunt doesn't restart from zero β and so the refuted claim doesn't get re-actioned by a future agent.
Findings (verified live 2026-08-06, read-only: Cloud Run Admin API + Compute API + BigQuery billing export)¶
1. The "24/7 container" claim is FALSE for the web-app project (aote-pms), today.
- Both surviving Cloud Run services β workspace-billing-service and bank-login-service (asia-east1)
β have minInstances=0 + CPU throttling on (request-based billing, scale to zero). Configs last
modified Jun 8 / Jun 13 by the owner; unchanged since.
- Zero Compute Engine instances, zero GKE clusters in aote-pms.
- The historical 24/7 container (receipt-cropper, min-instances=1, ~HK$770/mo) was scaled to zero
2026-07-09 (T-015) and deleted outright 2026-07-21 (T-171). The consulted agent was reading
stale state.
2. The only literal always-on machine is NOT the web app and costs ~nothing.
An e2 VM fortune-teller in the owner's separate project hotbes (us-west1-b) runs 24/7 β but it
sits in the Always Free tier: net HK$0.01β0.06/month (gross ~HK$49/mo fully offset by free-tier
credit lines; verified across AprβAug in the billing export). Not worth touching; the aote-pms
service account has no access to that project anyway (403).
3. The ACTUAL August spike is Vertex AI Gemini agent usage, not any container.
Whole-bill by month (net, HKD, all projects on the billing account): Apr ~21 Β· May ~843 (incl. a
one-off HK$99.95 project-less charge) Β· Jun ~880 (peak β the cropper) Β· Jul ~313 Β· Aug ~567 in
the first 5 days. August's HK$563 of that is Vertex AI "Gemini 3.6 Flash Global" SKUs concentrated
in Aug 2β3 (HK$459 on Aug 3 alone; burst hours 09:00β18:00 HKT), with billing labels
trajectory_id / last_execution_id / last_step_index (up to ~2280 steps) / used_claude: false
β the signature of an agentic coding tool (Gemini CLI / Gemini-based agent) authenticated against
aote-pms's Vertex AI. The web app itself pins gemini-2.5-flash (+-image) for receipt extraction
(lib/telegram/receiptProcessor.ts) β its Vertex usage is the small Jun/Jul baseline (HK$25β32/mo)
and it never calls Gemini 3.6. No charges Aug 4β5: the burst has stopped. Plausibly the burst IS
the consulted agent's own investigation sessions.
4. Remaining steady-state aote-pms baseline is reasonable: Secret Manager ~HK$13/mo + Artifact
Registry ~HK$8/mo + Firestore ops (billed under "App Engine") ~HK$3β7/mo + near-zero Cloud Run β
~HK$25β30/mo absent agent bursts.
Verdict / what was (not) done¶
Nothing was downscaled β there is nothing left to downscale. The infra is already in its cheapest sane configuration; the owner's "proceed to downscale" instruction was premised on a 24/7 container that no longer exists. Config changes were deliberately NOT invented to look busy. Read-only verification only; no code, no Firestore documents touched (reads only), no deploys.
Open levers for the owner (each needs an owner decision, none executed):
1. Identify the Gemini agent tool that billed HK$563 on Aug 2β3 and decide whether it should keep
using aote-pms as its Vertex billing project (vs. a personal API key/project, vs. accepting the
cost per use). It is dormant now but will bill again next time it runs.
2. Optional: a GCP budget alert on the billing account (e.g. HK$300/mo threshold) so the next
spike emails the owner within a day instead of surfacing at invoice time.
3. Optional micro-cleanup: Artifact Registry (~HK$8/mo) still stores images incl. those of the
deleted Cloud Run services; pruning needs care not to touch the two live services' images.
Blast radius: none β no state changed anywhere. Related SHAs: this docs commit only.
2026-08-06 β lever 2 (budget alert) attempted; blocked on billing-account IAM β owner action needed¶
- β
Read AGENTS.md Β· owner asked (verbatim): "Can I limit Google Cloud budget to HK$200/month?" β
clarified in chat that GCP budgets alert, not block (a true hard cap = auto-disabling billing,
rejected as too dangerous for a production app), then attempted to create a HK$200/month alert
budget (thresholds 50% / 90% / 100% actual + 100% forecasted) on billing account
0102F7-3FFF33-823945via the Billing Budgets API. - State changed: enabled
billingbudgets.googleapis.comonaote-pms(harmless, free, reversible; needed for API-based budget management). - Blocked: budgets are billing-account-level objects; billing-account IAM is separate from
project IAM, and
service@aote-pmsholds no role there βPERMISSION_DENIED. By design no agent credential can self-grant this. - Owner's two paths (either works):
(a) Console, no new grants (~2 min): console.cloud.google.com β Billing β Budgets & alerts β
Create budget β scope: all projects Β· amount HK$200 Β· thresholds 50/90/100 + forecasted 100.
(b) Delegate: grant
service@aote-pms.iam.gserviceaccount.comthe Billing Account Costs Manager role (roles/billing.costsManager) on billing account0102F7-3FFF33-823945(Billing β Account management β Permissions), then tell the agent to re-run creation β script already staged. The grant can be removed right after if preferred. - Source: EOP Local Assistance (Jefito) Β· local session 8ab2d4ce-6acc-4a26-ad72-c5bf1964cad2
2026-08-06 β budget alert LIVE β (owner delegated the billing role; lever 2 closed)¶
- β
Read AGENTS.md Β· owner granted
service@aote-pmsthe billing-account role and said (verbatim): "SA delegated" β budget created via the Billing Budgets API. - Live config (verified from the API's create response): budget
billingAccounts/0102F7-3FFF33-823945/budgets/2a154fea-21a1-43d8-aba9-023a4e35472b, display name "Monthly spend watch - HKD200 (T-200)", HK$200 per calendar month, all projects on the account, credits included (net spend); alerts at 50% / 90% / 100% of actual spend + 100% forecasted. No custom notification channel set β Google's default applies: threshold emails go to the billing account's admins/users (the owner). - What this does / doesn't do (recorded so nobody assumes a hard cap): it emails the owner as spend crosses HK$100 / HK$180 / HK$200 (or is forecast to) β it does not stop charges. The auto-disable-billing kill-switch was considered and rejected (would take Firestore + the app down mid-month automatically).
- Follow-up for the owner (least-privilege, optional): the delegated billing-account role on
service@aote-pmscan now be revoked β the budget persists without it; re-grant only if a future budget edit should go through an agent. Fits the T-148-era scoped-access model. - Source: EOP Local Assistance (Jefito) Β· local session 8ab2d4ce-6acc-4a26-ad72-c5bf1964cad2