Skip to main content

Per-query cost guard for cloud databases. Set dollar or byte limits before any query runs.

Project description

query-cost-guard

query-cost-guard

Per-query cost guard for BigQuery. Set dollar or byte limits before any query runs.

Why

BigQuery charges per byte scanned. A single bad query can burn through your daily quota. The native maximum_bytes_billed only speaks in bytes — this package lets you think in dollars.

Install

pip install query-cost-guard

# With CLI
pip install query-cost-guard[cli]

Usage

Dollar-based guard

from google.cloud.bigquery import Client
from query_cost_guard import QueryCostGuard, QueryParams

guard = QueryCostGuard(client=Client())

result = guard.query(
    sql="SELECT * FROM `project.dataset.table` WHERE date > '2026-01-01'",
    params=QueryParams(max_cost_usd=0.50),
)

result.rows              # list[dict]
result.actual_cost_usd   # 0.03
result.bytes_billed      # 4_831_838_208
result.duration_seconds  # 2.41

Byte-based guard

result = guard.query(
    sql="SELECT * FROM `project.dataset.table`",
    params=QueryParams(max_bytes=5 * 1024**4),  # 5 TiB
)

max_cost_usd and max_bytes are mutually exclusive.

When cost exceeds the limit

BigQuery rejects the query before execution — no bytes are billed.

from query_cost_guard import QueryCostExceededError, QueryParams

try:
    result = guard.query(sql=huge_query, params=QueryParams(max_cost_usd=0.10))
except QueryCostExceededError as e:
    e.context.estimated_cost_usd  # 2.34
    e.context.max_cost_usd        # 0.10
    e.context.bytes_estimated     # 374_000_000_000

With existing job config

from google.cloud.bigquery import QueryJobConfig, ScalarQueryParameter

result = guard.query(
    sql=sql,
    params=QueryParams(max_cost_usd=1.00, query_tag="observation_troubleshooting"),
    job_config=QueryJobConfig(
        query_parameters=[ScalarQueryParameter("account_id", "INT64", 115)]
    ),
    location="US",
)

Pricing

Live pricing is fetched from the Cloud Billing Catalog API and cached for 24 hours. If the API is unavailable, falls back to the static rate of $6.25/TiB.

from query_cost_guard import QueryCostGuard, OnPricingFailure

# Fail hard if pricing can't be resolved
guard = QueryCostGuard(client=client, on_pricing_failure=OnPricingFailure.RAISE)

# Or pin a known price
guard = QueryCostGuard(client=client, price_per_tib_override=6.25)

Dry-run estimation

estimate = guard.estimate(sql="SELECT * FROM `project.dataset.big_table`")
estimate.estimated_bytes       # 4_831_838_208
estimate.estimated_cost_usd    # 0.0275
estimate.price_per_tib_usd     # 6.25

CLI

Estimate query cost without executing:

query-cost-guard --project my-gcp-project estimate \
  --query "SELECT * FROM \`project.dataset.table\`"

# Estimated bytes:  4,831,838,208
# Estimated cost:   $0.0275 (at $6.25/TiB)

With a cost threshold:

query-cost-guard --project my-gcp-project estimate \
  --query "SELECT * FROM big_table" \
  --max-cost 0.50

# Guard:  ✓ PASS (limit $0.50)

JSON output, file input, stdin:

query-cost-guard --project my-proj estimate --query "SELECT 1" --json
query-cost-guard --project my-proj estimate --file query.sql
cat query.sql | query-cost-guard --project my-proj estimate

Credentials default to Application Default Credentials. Override with --credentials /path/to/sa.json.

How it works

Uses BigQuery's maximum_bytes_billed on the QueryJobConfig. Single API call, no race condition, enforced server-side. Both estimate() and the CLI use dry_run=True for zero-cost estimation.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

query_cost_guard-0.1.2.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

query_cost_guard-0.1.2-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file query_cost_guard-0.1.2.tar.gz.

File metadata

  • Download URL: query_cost_guard-0.1.2.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for query_cost_guard-0.1.2.tar.gz
Algorithm Hash digest
SHA256 9bb4b4f8a6dd51e8cd41fceba9297c812672348e053473d330ea34eee4fad288
MD5 104171eb2c1ee19cc28fd8ac5560fe17
BLAKE2b-256 3dc0a4a8fca753cf96dd120acfc5fee55297d454697764a5631c02250340352f

See more details on using hashes here.

Provenance

The following attestation bundles were made for query_cost_guard-0.1.2.tar.gz:

Publisher: release.yml on yaelmi3/query-cost-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file query_cost_guard-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for query_cost_guard-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 daefc31fb143532b763731b3a6643d1307f72523f053289ab450bfa5fc33831f
MD5 4d5c024d40fff293e984860247a59ecc
BLAKE2b-256 290ac0f56f5fa315f42c16237b4abf8f37e3a8f5789eab982cb840b431c3faec

See more details on using hashes here.

Provenance

The following attestation bundles were made for query_cost_guard-0.1.2-py3-none-any.whl:

Publisher: release.yml on yaelmi3/query-cost-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page