# velikodniy/gcp-spending-guard architecture

> Architecture diagram of the GitHub repository velikodniy/gcp-spending-guard, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/velikodniy/gcp-spending-guard
- Repository: https://github.com/velikodniy/gcp-spending-guard

## Overview

1. **What this repo is**
   - This is not an application backend or UI; it is an **infrastructure module** that enforces a **hard spending limit on a GCP project**.
   - The module’s purpose is to automate a “kill switch” for billing once a budget threshold is exceeded.

2. **Top-level architecture**
   - The repo is split into two clear parts:
     - **Terraform/OpenTofu module** at the root: `main.tf`, `variables.tf`, `outputs.tf`, `versions.tf`
     - **Node.js Cloud Function** in `function/`
   - Terraform provisions the Google Cloud resources; the Node.js code runs the enforcement action when an alert arrives.

3. **Primary data flow**
   - GCP Budget Monitoring detects spend exceeding the configured threshold.
   - The budget system publishes an alert to a **Pub/Sub topic** created by this module.
   - A **Cloud Function** subscribed to that topic receives the alert.
   - The function calls Google Cloud billing/project APIs to **disable billing on the project**.

4. **Core GCP resources**
   - **Budget resource**: configured with a target amount, currency, and display name.
   - **Pub/Sub topic**: acts as the event transport for budget notifications.
   - **Cloud Function**: event-driven handler that performs the billing shutdown action.
   - **IAM/service account wiring**: grants the function permission to interact with billing and project resources.

5. **Runtime boundary**
   - The module has a strong split between:
     - **Provisioning time**: Terraform creates and wires resources together.
     - **Alert handling time**: the function runs only when a budget notification is published.
   - This means the enforcement logic is event-driven, not continuously running.

6. **Cloud Function deployment model**
   - The listed required APIs include `cloudfunctions`, `cloudbuild`, `eventarc`, and `run`, which strongly suggests the function is deployed as **Cloud Functions Gen 2**.
   - In that model, Cloud Build packages/deploys the function, and the runtime sits on Cloud Run with Eventarc/Pub/Sub integration underneath.

7. **External dependencies and required APIs**
   - The module depends on several GCP control-plane services being enabled:
     - Budgeting and billing APIs
     - Pub/Sub
     - Cloud Functions / Cloud Build / Eventarc / Cloud Run
     - Cloud Resource Manager
   - These are not incidental; they are required for both alert delivery and the enforcement action.

8. **Configuration surface**
   - The main inputs are:
     - `project_id`
     - `billing_account_id`
     - `budget_amount`
     - optional `region`
     - optional `currency_code`
     - optional naming inputs for the budget, topic, and function
   - The currency must align with the billing account’s currency.

9. **Operational behavior**
   - When triggered by an over-budget event, the function disables billing for the project.
   - The README notes that restoring service requires **manually reattaching billing**; the module is designed to be disruptive by intent.

10. **Repository layout significance**
   - `function/package.json` and `function/index.js` indicate the runtime logic is packaged independently from the Terraform code.
   - `main.tf` likely stitches together the topic, budget, function, and IAM.
   - `variables.tf` and `outputs.tf` define the module contract and expose the created infrastructure to callers.

11. **Diagram-worthy subsystems**
   - A useful architecture diagram should show:
     - the **GCP project and billing account** as external inputs,
     - the **budget/notification pipeline**,
     - the **Pub/Sub event channel**,
     - the **Cloud Function enforcement worker**,
     - and the **billing disablement action** back against the project.

12. **Key architectural takeaway**
   - This module is a **governance control**: it uses cloud-native eventing to convert a budget breach into an automated billing shutdown.
   - The important design pattern is “budget alert as event, function as enforcement, billing API as actuator.”

Main entry points: [`main.tf`](https://github.com/velikodniy/gcp-spending-guard/blob/main/main.tf) (Wiring), [`function/package.json`](https://github.com/velikodniy/gcp-spending-guard/blob/main/function/package.json) (Deploy function), [`function/index.js`](https://github.com/velikodniy/gcp-spending-guard/blob/main/function/index.js) (Handler), [`variables.tf`](https://github.com/velikodniy/gcp-spending-guard/blob/main/variables.tf) (Inputs)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_terraform["Terraform module"]
  node_variables_tf["Inputs<br/>terraform contract<br/>[variables.tf]"]
  node_main_tf["Wiring<br/>terraform orchestration<br/>[main.tf]"]
  node_outputs_tf["Outputs<br/>terraform contract<br/>[outputs.tf]"]
  node_versions_tf["Versions<br/>terraform constraints<br/>[versions.tf]"]
  node_budget_resource[("Budget")]
  node_pubsub_topic(("Alert topic<br/>gcp pubsub topic"))
  node_iam_wiring{{"IAM access<br/>gcp permissions"}}
  node_project[("Target project<br/>gcp project")]
  node_billing_account[("Billing account")]
  node_budget_alerts(("Budget alerts<br/>gcp budget monitoring"))
end

subgraph group_runtime["Function runtime"]
  node_function_deploy["Deploy function<br/>gcp gen2 function<br/>[package.json]"]
  node_handler_code["Handler<br/>node.js logic<br/>[index.js]"]
  node_gen2_platform{{"Gen2 platform<br/>cloud build/run/eventarc"}}
  node_billing_action["Disable billing<br/>gcp billing api"]
end

node_variables_tf -->|"configures"| node_main_tf
node_main_tf -->|"creates"| node_budget_resource
node_main_tf -->|"creates"| node_pubsub_topic
node_main_tf -->|"grants"| node_iam_wiring
node_main_tf -->|"deploys"| node_function_deploy
node_budget_resource -->|"feeds"| node_budget_alerts
node_budget_alerts -->|"publishes"| node_pubsub_topic
node_pubsub_topic -->|"triggers"| node_function_deploy
node_function_deploy -->|"runs on"| node_gen2_platform
node_function_deploy -->|"executes"| node_handler_code
node_handler_code -->|"calls"| node_billing_action
node_billing_action -->|"disables billing on"| node_project
node_billing_account -->|"sets currency and scope"| node_budget_resource
node_outputs_tf -->|"exposes"| node_main_tf
node_versions_tf -->|"constrains"| node_main_tf
node_iam_wiring -->|"authorizes"| node_handler_code
node_project -->|"is monitored by"| node_budget_resource

click node_variables_tf "https://github.com/velikodniy/gcp-spending-guard/blob/main/variables.tf"
click node_main_tf "https://github.com/velikodniy/gcp-spending-guard/blob/main/main.tf"
click node_outputs_tf "https://github.com/velikodniy/gcp-spending-guard/blob/main/outputs.tf"
click node_versions_tf "https://github.com/velikodniy/gcp-spending-guard/blob/main/versions.tf"
click node_function_deploy "https://github.com/velikodniy/gcp-spending-guard/blob/main/function/package.json"
click node_handler_code "https://github.com/velikodniy/gcp-spending-guard/blob/main/function/index.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_variables_tf,node_main_tf,node_outputs_tf,node_versions_tf,node_budget_resource,node_pubsub_topic,node_iam_wiring,node_project,node_billing_account,node_budget_alerts toneBlue
class node_function_deploy,node_handler_code,node_gen2_platform,node_billing_action toneAmber
```

## Components

### Terraform module

Provisioning layer that declares and wires the GCP resources.

- [Inputs](https://github.com/velikodniy/gcp-spending-guard/blob/main/variables.tf): terraform contract · Module parameters for project, billing, budget, region, and naming. · `variables.tf`
- [Wiring](https://github.com/velikodniy/gcp-spending-guard/blob/main/main.tf): terraform orchestration · Creates the budget, Pub/Sub topic, Cloud Function, and IAM connections. · `main.tf`
- [Outputs](https://github.com/velikodniy/gcp-spending-guard/blob/main/outputs.tf): terraform contract · Exposes created resource identifiers to module callers. · `outputs.tf`
- [Versions](https://github.com/velikodniy/gcp-spending-guard/blob/main/versions.tf): terraform constraints · Pins Terraform and provider/runtime compatibility. · `versions.tf`
- **Budget**: gcp billing budget · Configured spending threshold and notification target.
- **Alert topic**: gcp pubsub topic · Transport for budget breach notifications.
- **IAM access**: gcp permissions · Grants the function permission to manage billing-related actions.
- **Target project**: gcp project · Project whose billing is protected by the guard.
- **Billing account**: gcp billing account · Source of truth for the attached billing relationship and currency.
- **Budget alerts**: gcp budget monitoring · Detects threshold breaches and emits notifications.

### Function runtime

Event-driven enforcement code packaged and deployed separately from Terraform.

- [Deploy function](https://github.com/velikodniy/gcp-spending-guard/blob/main/function/package.json): gcp gen2 function · Cloud Function Gen 2 deployment entrypoint managed by Terraform. · `function/package.json`
- [Handler](https://github.com/velikodniy/gcp-spending-guard/blob/main/function/index.js): node.js logic · Processes budget alerts and invokes the shutdown action. · `function/index.js`
- **Gen2 platform**: cloud build/run/eventarc · Underlying deployment and eventing substrate used by the function.
- **Disable billing**: gcp billing api · Acts on the target project to stop further charges.

## Connections

- Inputs → Wiring: configures · Inputs feed the Terraform resource graph.
- Wiring → Budget: creates · Defines the spend limit and notification rules.
- Wiring → Alert topic: creates · Provisioned as the alert transport.
- Wiring → IAM access: grants · Wires permissions for the enforcement worker.
- Wiring → Deploy function: deploys · Packages and registers the Cloud Function.
- Budget → Budget alerts: feeds · Budget monitoring evaluates spend against the configured threshold.
- Budget alerts → Alert topic: publishes · Over-budget events are sent to the topic.
- Alert topic → Deploy function: triggers · Event delivery invokes the function.
- Deploy function → Gen2 platform: runs on · Cloud Functions Gen 2 uses Cloud Build, Eventarc, and Cloud Run underneath.
- Deploy function → Handler: executes · Runtime entrypoint is the Node.js handler.
- Handler → Disable billing: calls · Handler invokes billing/project control APIs.
- Disable billing → Target project: disables billing on · Kills further spending for the target project.
- Billing account → Budget: sets currency and scope · Budget is tied to the billing account and its currency.
- Outputs → Wiring: exposes · Surfaces resource identifiers created by the module.
- Versions → Wiring: constrains · Provider and runtime compatibility for the module.
- IAM access → Handler: authorizes · Allows the function to perform the shutdown action.
- Target project → Budget: is monitored by · The budget applies to the target project's spend.
