New to Kestra?
Use blueprints to kickstart your first workflows.
Project end-of-month GCP spend from the BigQuery billing export, compare the forecast against your budget, and alert Slack before the invoice lands.
A budget alert that fires at 90% of the budget has already lost the argument: by then the money is mostly spent. This blueprint moves the decision earlier by forecasting instead of measuring. It queries the BigQuery billing export for month-to-date cost and the trailing 7-day cost, extends that recent pace across the remaining days of the month, and compares the projection against a budget input — over it, Slack gets the forecast, the headroom, and the service driving the spend while the month is still young enough to do something about it.
fetch_spend_summary (io.kestra.plugin.gcp.bigquery.Query, FETCH_ONE) reads the standard daily billing export in a single pass: month-to-date cost, cost over the trailing 7 days, how many of those days actually have data, and the calendar facts (days_elapsed, days_in_month) the projection needs.fetch_top_service (io.kestra.plugin.gcp.bigquery.Query) ranks services by month-to-date cost and returns the leader, so the alert names where to cut rather than only how much is at stake.assess_forecast (io.kestra.plugin.scripts.python.Script on the io.kestra.plugin.core.runner.Process runner) extends the trailing 7-day daily pace across the remaining days of the month — a recent-pace forecast that reacts to a spike the same week it starts. When the recent window has no rows (a brand-new export), it falls back to a linear month-to-date projection, and it computes percent-of-budget and headroom either way.check_forecast (io.kestra.plugin.core.flow.If) compares projected_cost with the monthly_budget_usd input. Over it, alert_overspend posts the projection, budget, month-to-date numbers, forecast basis, and top service to Slack; under it, log_on_track keeps a quiet record so the execution history shows the month's runway.errors block alerts Slack when the guard itself fails, and a daily Schedule trigger (shipped disabled) drives the cadence once enabled.forecast_summary JSON output (month-to-date, projection, budget, percentages, basis, top service) for dashboards or downstream flows.The billing export already stores every cost row; what it cannot do is turn those rows into a scheduled decision. Kestra adds the loop: a daily schedule timed after the export lands, two BigQuery queries with retries, a Python projection step that needs no infrastructure of its own thanks to the Process runner, a branch that separates alerting from quiet record-keeping, and an execution history that doubles as a daily audit of the forecast. A cron script would run, but it would not retry, alert on its own failure, or leave a queryable trail.
billing_export_table.roles/bigquery.jobUser plus a viewer role on the dataset).GCP_PROJECT_ID: project in which the BigQuery queries run.GCP_SERVICE_ACCOUNT: service account key JSON with BigQuery job permissions.SLACK_WEBHOOK_URL: Slack incoming webhook URL for overspend and failure alerts.billing_export_table to your export table's fully qualified name and monthly_budget_usd to your real budget.forecast_summary (and the logs) to see your projection.disabled: false on the daily_forecast_check trigger.If that alerts on pct_used alone (for example 80% consumed) so slow and steady creep trips the guard even when the projection is still calm.project.id instead of service.description to attribute spend to the team whose project is growing.then branch.